Import-VcCmApp.ps1
Function Import-VcCmApp { <# .SYNOPSIS Creates Visual C++ Redistributable applications in a ConfigMgr site. .DESCRIPTION Creates an application in a Configuration Manager site for each Visual C++ Redistributable and includes setting whether the Redistributable can run on 32-bit or 64-bit Windows and the Uninstall key for detecting whether the Redistributable is installed. Use Get-VcList and Get-VcRedist to download the Redistributable and create the array of Redistributables for importing into ConfigMgr. .NOTES Name: Import-VcCmApp Author: Aaron Parker Twitter: @stealthpuppy .LINK https://stealthpuppy.com .PARAMETER VcList An array containing details of the Visual C++ Redistributables from Get-VcList. .PARAMETER Path A folder containing the downloaded Visual C++ Redistributables. .PARAMETER Release Specifies the release (or version) of the redistributables to download or install. .PARAMETER Architecture Specifies the processor architecture to download or install. .PARAMETER SMSSiteCode Specify the Site Code for ConfigMgr app creation. .PARAMETER CMPath Specify a UNC path where the Visual C++ Redistributables will be distributed from .EXAMPLE #> [CmdletBinding(SupportsShouldProcess = $True)] [OutputType([Array])] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $False, ` HelpMessage = "An array containing details of the Visual C++ Redistributables from Get-VcList.")] [ValidateNotNull()] [array]$VcList, [Parameter(Mandatory = $True, Position = 1, HelpMessage = "A folder containing the downloaded Visual C++ Redistributables.")] [ValidateScript( {If (Test-Path $_ -PathType 'Container') { $True } Else { Throw "Cannot find path $_" } })] [string]$Path, [Parameter(Mandatory = $False, HelpMessage = "Specify the version of the Redistributables to install.")] [ValidateSet('2005', '2008', '2010', '2012', '2013', '2015', '2017')] [string[]]$Release = @("2008", "2010", "2012", "2013", "2015", "2017"), [Parameter(Mandatory = $False, HelpMessage = "Specify the processor architecture/s to install.")] [ValidateSet('x86', 'x64')] [string[]]$Architecture = @("x86", "x64"), [Parameter(Mandatory = $True, HelpMessage = "Specify ConfigMgr Site Code.")] [ValidateScript( { If ($_ -match "^[a-zA-Z0-9]{3}$") { $True } Else { Throw "$_ is not a valid ConfigMgr site code." } })] [string]$SMSSiteCode, [Parameter(Mandatory = $True, HelpMessage = "Specify the ConfigMgr UNC path.")] [string]$CMPath, [Parameter()]$Publisher = "Microsoft", [Parameter()]$Language = "en-US", [Parameter()]$CMAppFolder = "VcRedist" ) Begin { # CMPath will be the network location for copying the Visual C++ Redistributables to Set-Location -Path $Path If (!([bool]([System.Uri]$CMPath).IsUnc)) { Throw "$CMPath must be a valid UNC path." } If (Test-Path $CMPath) { # Copy VcRedists to the network location. Use robocopy for robustness If ($PSCmdlet.ShouldProcess("$($Path) to $($CMPath)", "Copy")) { Robocopy.exe *.exe $Path $CMPath /S /XJ /R:1 /W:1 /NP /NJH /NJS /NFL /NDL } } Else { Write-Warning "Unable to confirm $CMPath exists. Please check that $CMPath is valid." } # If the ConfigMgr console is installed, load the PowerShell module; Requires PowerShell module to be installed If (Test-Path $env:SMS_ADMIN_UI_PATH) { Try { # Import the ConfigurationManager.psd1 module Import-Module "$($env:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" | Out-Null } Catch { Throw "Could not load ConfigMgr Module. Please make sure that the ConfigMgr Console is installed." Break } } Else { Throw "Cannot find environment variable SMS_ADMIN_UI_PATH. Is the ConfigMgr Console and PowerShell module installed?" Break } # Create the folder for importing the Redistributables into If ($CMAppFolder) { If ($PSCmdlet.ShouldProcess("$($SMSSiteCode):\Application\$($CMAppFolder)", "Creating")) { New-Item -Path "$($SMSSiteCode):\Application\$($CMAppFolder)" -ErrorAction SilentlyContinue } } If (Test-Path "$($SMSSiteCode):\Application\$($CMAppFolder)") { Write-Verbose "Successfully created folder $($SMSSiteCode):\Application\$($CMAppFolder)" $CMAppFolder = "$($SMSSiteCode):\Application\$($CMAppFolder)" } Else { Write-Verbose "Defaulting to folder: $($SMSSiteCode):\Application" $CMAppFolder = "$($SMSSiteCode):\Application" } # Output variable $Output = @() } Process { # Filter release and architecture if specified If ($PSBoundParameters.ContainsKey('Release')) { Write-Verbose "Filtering releases for platform." $VcList = $VcList | Where-Object { $_.Release -eq $Release } } If ($PSBoundParameters.ContainsKey('Architecture')) { Write-Verbose "Filtering releases for architecture." $VcList = $VcList | Where-Object { $_.Architecture -eq $Architecture } } ForEach ($Vc in $VcList) { Write-Verbose "Importing app: [$($Vc.Name)][$($Vc.Release)][$($Vc.Architecture)]" # Import as an application into ConfigMgr If ($PSCmdlet.ShouldProcess("$($Vc.Name) in $CMPath", "Import ConfigMgr app")) { # Configure parameters and change to the SMS Site drive Set-Location -Path $Path $Target = "$($(Get-Item -Path $CMPath).FullName)\$($Vc.Release)\$($Vc.Architecture)\$($Vc.ShortName)" $Filename = Split-Path -Path $Vc.Download -Leaf # Change to the SMS Application folder before importing the applications Set-Location $CMAppFolder -ErrorVariable ConnectionError # Create the ConfigMgr application with properties from the XML file If ($pscmdlet.ShouldProcess($Vc.Name + " $($Vc.Architecture)", "Creating ConfigMgr application")) { $App = New-CMApplication -Name "$($Vc.Name) $($Vc.Architecture)" ` -Description "$($Publisher) $($Vc.Name) $($Vc.Architecture) imported by $($MyInvocation.MyCommand)" ` -SoftwareVersion "$($Vc.Release) $($Vc.Architecture)" ` -LinkText $Vc.URL ` -Publisher $Publisher ` -Keyword "Visual C++ Redistributable" ` -ErrorVariable CMAppError $Output += $App $App | Move-CMObject -FolderPath $CMAppFolder -ErrorAction SilentlyContinue | Out-Null } # Add a deployment type to the application If ($pscmdlet.ShouldProcess($Vc.Name + " $($Vc.Architecture)", "Adding deployment type")) { $App | Add-CMScriptDeploymentType ` -InstallCommand "$Filename $($Vc.Install)" ` -ContentLocation $Target ` -ProductCode $Vc.ProductCode ` -SourceUpdateProductCode $Vc.ProductCode ` -DeploymentTypeName ("SCRIPT_" + $Vc.Name) ` -UserInteractionMode Hidden ` -UninstallCommand "msiexec /x $($Vc.ProductCode) /qn-" ` -LogonRequirementType WhetherOrNotUserLoggedOn ` -InstallationBehaviorType InstallForSystem ` -Comment "Generated by $($MyInvocation.MyCommand)" ` -ErrorVariable CMDtError | Out-Null } } } } End { Set-Location -Path $Path # Output array of applications created in ConfigMgr $Output } } |