Public/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. .OUTPUTS System.Array .NOTES Author: Aaron Parker Twitter: @stealthpuppy .LINK https://github.com/aaronparker/Install-VisualCRedistributables .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 CMPath Specify a UNC path where the Visual C++ Redistributables will be distributed from .PARAMETER SMSSiteCode Specify the Site Code for ConfigMgr app creation. .PARAMETER AppFolder Import the Visual C++ Redistributables into a sub-folder. Defaults to "VcRedists". .PARAMETER Release Specifies the release (or version) of the redistributables to download or install. .PARAMETER Architecture Specifies the processor architecture to download or install. .EXAMPLE $VcList = Get-VcList | Get-VcRedist -Path "C:\Temp\VcRedist" Import-VcCmApp -VcList $VcList -Path "C:\Temp\VcRedist" -CMPath "\\server\share\VcRedist" -SMSSiteCode LAB Description: Download the supportee Visual C++ Redistributables to "C:\Temp\VcRedist", copy them to "\\server\share\VcRedist" and import as applications into the ConfigMgr site LAB. #> [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 = $True, HelpMessage = "Specify a distribution UNC path to copy the Redistributables to.")] [string]$CMPath, [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 = $False, HelpMessage = "Specify Applications folder to import the VC Redistributables into.")] [ValidatePattern('^[a-zA-Z0-9]+$')] [string]$AppFolder = "VcRedists", [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()]$Publisher = "Microsoft", [Parameter()]$Language = "en-US", [Parameter()]$Keyword = "Visual C++ Redistributable" ) 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 ( $AppFolder ) { If ($PSCmdlet.ShouldProcess("$($SMSSiteCode):\Application\$($AppFolder)", "Creating")) { New-Item -Path "$($SMSSiteCode):\Application\$($AppFolder)" -ErrorAction SilentlyContinue } } If ( Test-Path "$($SMSSiteCode):\Application\$($AppFolder)" ) { Write-Verbose "Importing into: $($SMSSiteCode):\Application\$($AppFolder)" $DestFolder = "$($SMSSiteCode):\Application\$($AppFolder)" } Else { Write-Verbose "Importing into: $($SMSSiteCode):\Application" $DestFolder = "$($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 Write-Verbose "Setting location to $($Path)" 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 Write-Verbose "Setting location to $($DestFolder)" Set-Location $DestFolder -ErrorVariable ConnectionError # Create the ConfigMgr application with properties from the XML file If ( (Get-Item -Path $DestFolder).PSDrive.Name -eq $SMSSiteCode ) { 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 $Keyword ` -ErrorVariable CMAppError $Output += $App $App | Move-CMObject -FolderPath $DestFolder -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 } } Else { Write-Error "Unable to change to ConfigMgr drive location $($DestFolder). Cannot import VcRedist." } } } } End { Set-Location -Path $Path # Output array of applications created in ConfigMgr $Output } } |