Upload-IntuneVcRedist.ps1
<#PSScriptInfo .VERSION 1.0.0 .GUID 658923cb-0d36-42c8-9b4d-7763a16ebf91 .AUTHOR cbruscato .COMPANYNAME .COPYRIGHT .TAGS Intune Visual C++ Runtime .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION This script downloads the latest Visual C++ redistributable installers, packages them, and uploads them to Intune. #> Param() <# .SYNOPSIS This script downloads the latest Visual C++ redistributable installers, packages them, and uploads them to Intune. .DESCRIPTION This saves you from having to register 8 different applications with Intune, in less than 10 minutes. .PARAMETER TenantName This is the .onmicrosoft.com domain for your tenant. Example: contoso.onmicrosoft.com .EXAMPLE Upload-IntuneVCRedist.ps1 -TenantName contoso.onmicrosoft.com .INPUTS None. You cannot pipe objects to Upload-IntuneVCRedist .OUTPUTS None. The script does not return any objects when finished. .NOTES YOU MUST RUN INTERNET EXPLORER 11 AT LEAST ONE TIME BEFORE RUNNING THIS SCRIPT AS IT IS REQUIRED TO UPLOAD TO AZURE YOU MUST LOGIN AS A GLOBAL ADMINISTRATOR WHEN PROMPTED AND AUTHENTICATE WITH MODERN AUTHENTICATION SCRIPT MUST BE RUN AS AN ADMINISTRATOR #> Param( [Parameter(Mandatory=$true)] [string]$TenantName ) #Bypass Execution Policy Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force #Install PowerShell Modules Set-PSRepository -Name PSGallery -InstallationPolicy Trusted Install-Module -Name VcRedist, IntuneWin32App, PSIntuneAuth, AzureAD #Create directory structure $Path = "C:\Temp\VcRedist" if (!(Test-Path "$Path\Package")) { New-Item -itemType Directory -Path $Path -Name "Package" } else { write-host "Folder already exists" } $VcRedists = Get-VcList -Release 2012, 2013, 2015, 2019 Save-VcRedist -Path "$Path\Package" -VcList $VcRedists #Connect to Intune Connect-MSIntuneGraph -TenantName $TenantName -PromptBehavior Always #Download VC Redistributables $Path = "C:\Temp\VcRedist" ForEach ($VcRedist in $VcRedists) { # Create variables for the package source and output folders $Package = [System.IO.Path]::Combine($Path, "Package", $VcRedist.Release, $VcRedist.Version, $VcRedist.Architecture) $Output = [System.IO.Path]::Combine($Path, "Output", $VcRedist.Release, $VcRedist.Version, $VcRedist.Architecture) New-Item -Path $Output -ItemType "Directory" # Find the Redistributable setup.exe $Installer = $package + "\" + (Split-Path -Leaf $vcredist.download) # Wrap the installer Start-Process -FilePath "IntuneWinAppUtil.exe" -ArgumentList "-c $Package -s $Installer -o $Output -q" -Wait -NoNewWindow } #Download the App Icon for Intune $IconSource = "https://raw.githubusercontent.com/Insentra/intune-icons/main/icons/Microsoft-VisualStudio.png" $ImageFile = "$Path\$(Split-Path -Leaf $IconSource)" Invoke-WebRequest -Uri $IconSource -OutFile $ImageFile -UseBasicParsing $Icon = New-IntuneWin32AppIcon -FilePath $ImageFile #Create Application Detection Rule in Intune $KeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ForEach ($VcRedist in $VcRedists) { # Configure detection for each application # Enable 'Associated with a 32-bit app on 64-bit clients' as required $params = @{ Existence = $true KeyPath = "$KeyPath\$($VcRedist.ProductCode)" Check32BitOn64System = If ($VcRedist.UninstallKey -eq "32") { $True } Else { $False } DetectionType = "exists" } $DetectionRule = New-IntuneWin32AppDetectionRuleRegistry @params } #Create Application Requirements Rule in Intune ForEach ($VcRedist in $VcRedists) { Switch ($VcRedist.Architecture) { "x86" { $PackageArchitecture = "All" } "x64" { $PackageArchitecture = "x64" } } $params = @{ Architecture = $PackageArchitecture MinimumSupportedOperatingSystem = "1607" } $RequirementRule = New-IntuneWin32AppRequirementRule @params } #Upload Win32 Apps to Azure Storage Blob and Register the Application with Intune $Publisher = "Microsoft" $n = 0 ForEach ($VcRedist in $VcRedists) { $n++ $PackageNew = [System.IO.Path]::Combine($Path, "Output", $VcRedist.Release, $VcRedist.Version, $VcRedist.Architecture) $IntuneWin = $PackageNew + "\" + (Split-Path -Leaf $vcredist.download) $IntuneWin = $IntuneWin -replace "exe", "intunewin" $params = @{ FilePath = $IntuneWin DisplayName = "$Publisher Visual C++ Redistributable $($VcRedist.Release) $($VcRedist.Version) $($VcRedist.Architecture)" Description = "$Publisher $($VcRedist.Name) $($VcRedist.Version) $($VcRedist.Architecture)." Publisher = $Publisher InformationURL = $VcRedist.URL PrivacyURL = "https://go.microsoft.com/fwlink/?LinkId=521839" CompanyPortalFeaturedApp = $false InstallExperience = "system" RestartBehavior = "suppress" DetectionRule = $DetectionRule RequirementRule = $RequirementRule InstallCommandLine = ".\" + (Split-Path -Leaf $vcredist.download) + " " + ($VcRedist.SilentInstall) UninstallCommandLine = $VcRedist.SilentUninstall Icon = $Icon Verbose = $true } $Params $App = Add-IntuneWin32App @params $params = @{ Id = $App.Id Intent = "required" Notification = "hideAll" DeliveryOptimizationPriority = "foreground" Verbose = $true } $Params Add-IntuneWin32AppAssignmentAllDevices @params #Sleep for 30 seconds to avoid 400 Bad Request errors from throttling on Azure Write-Host "Finished Application Upload $n. Sleeping for 30 seconds" -ForegroundColor Green Start-Sleep -Seconds 30 #Cleanup Files Remove-Item -Path C:\Temp\VcRedist -Recurse -Force } |