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
}