Public/Get-IntunePackagingTool.ps1
|
function Get-IntunePackagingTool { <# .SYNOPSIS Downloads the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe). .DESCRIPTION The Get-IntunePackagingTool function downloads a release of the Microsoft Win32 Content Prep Tool from GitHub (github.com/microsoft/Microsoft-Win32-Content-Prep-Tool), extracts it to a temporary folder and copies IntuneWinAppUtil.exe to Path. The downloaded archive and the extracted files are removed afterwards. By default the latest release is downloaded. Use DownloadTag to pin a release, or DownloadUrl to download a specific zip file. The downloaded IntuneWinAppUtil.exe is verified before it is copied to Path, and refused when a check fails: - On Windows it must have a valid Authenticode signature from Microsoft Corporation (Get-AuthenticodeSignature: Status Valid and O=Microsoft Corporation in the signer subject). - With ExpectedSha256 its SHA256 hash must match. Where Authenticode signatures cannot be checked (PowerShell on Linux or macOS), ExpectedSha256 is required. .PARAMETER Path The folder that IntuneWinAppUtil.exe is copied to. It is created when it does not exist. .PARAMETER DownloadTag The release tag to download, for example 'v1.8.6'. .PARAMETER DownloadUrl The URL of a zip file that contains IntuneWinAppUtil.exe. Used instead of the GitHub release archive. .PARAMETER ExpectedSha256 The expected SHA256 hash (64 hexadecimal characters) of IntuneWinAppUtil.exe. When given, the downloaded file must match it. .PARAMETER Force Overwrites IntuneWinAppUtil.exe when it already exists in Path. .OUTPUTS System.IO.FileInfo The copied IntuneWinAppUtil.exe file. .EXAMPLE Get-IntunePackagingTool -Path "C:\Tools" Downloads the latest release and copies IntuneWinAppUtil.exe to C:\Tools. .EXAMPLE Get-IntunePackagingTool -Path "C:\Tools" -DownloadTag 'v1.8.6' -Force Downloads release v1.8.6 and overwrites an existing C:\Tools\IntuneWinAppUtil.exe. .EXAMPLE Get-IntunePackagingTool -Path "C:\Tools" -DownloadTag 'v1.8.6' -ExpectedSha256 '<sha256 of IntuneWinAppUtil.exe>' Downloads release v1.8.6 and only keeps IntuneWinAppUtil.exe when its hash matches. .LINK https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool #> [CmdletBinding(DefaultParameterSetName = 'Latest')] [OutputType([System.IO.FileInfo])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Mandatory = $true, ParameterSetName = 'DownloadTag')] [ValidateNotNullOrEmpty()] [string]$DownloadTag, [Parameter(Mandatory = $true, ParameterSetName = 'DownloadUrl')] [ValidateNotNullOrEmpty()] [string]$DownloadUrl, [ValidatePattern('^[0-9A-Fa-f]{64}$')] [string]$ExpectedSha256, [switch]$Force ) $TelemetryArgs = @{ ModuleName = $MyInvocation.MyCommand.Module.Name ModuleVersion = [string]$MyInvocation.MyCommand.Module.Version CommandName = $MyInvocation.MyCommand.Name ExecutionID = [guid]::NewGuid().ToString() } Invoke-TelemetryCollection @TelemetryArgs -Stage Start -ClearTimer try { $RepositoryUrl = 'https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool' switch ($PSCmdlet.ParameterSetName) { 'DownloadTag' { Write-Verbose "Using the specified download tag '$DownloadTag'." $DownloadUrl = "$RepositoryUrl/archive/refs/tags/$DownloadTag.zip" } 'Latest' { Write-Verbose 'Getting the latest release of the Microsoft Win32 Content Prep Tool.' try { $LatestRelease = Invoke-RestMethod -Uri "$RepositoryUrl/releases/latest" -Headers @{ Accept = 'application/json' } -UseBasicParsing -ErrorAction Stop } catch { throw "Failed to get the latest release of the Microsoft Win32 Content Prep Tool: $($_.Exception.Message)" } if ([string]::IsNullOrEmpty($LatestRelease.tag_name)) { throw 'Failed to get the latest release of the Microsoft Win32 Content Prep Tool: the response did not contain a tag name.' } Write-Verbose "Latest tag: $($LatestRelease.tag_name)" $DownloadUrl = "$RepositoryUrl/archive/refs/tags/$($LatestRelease.tag_name).zip" } } $WorkFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath "IntuneWinAppUtil-$([guid]::NewGuid().ToString('N'))" $DownloadPath = Join-Path -Path $WorkFolder -ChildPath 'IntuneWinAppUtil.zip' $ExtractionPath = Join-Path -Path $WorkFolder -ChildPath 'extracted' try { $null = New-Item -Path $WorkFolder -ItemType Directory -Force -ErrorAction Stop Write-Verbose "Downloading '$DownloadUrl' to '$DownloadPath'." try { Invoke-WebRequest -Uri $DownloadUrl -OutFile $DownloadPath -UseBasicParsing -ErrorAction Stop } catch { throw "Failed to download the Microsoft Win32 Content Prep Tool from $($DownloadUrl): $($_.Exception.Message)" } Write-Verbose "Extracting '$DownloadPath'." Expand-Archive -Path $DownloadPath -DestinationPath $ExtractionPath -Force -ErrorAction Stop $ToolFile = Get-ChildItem -Path $ExtractionPath -Recurse -File -Filter 'IntuneWinAppUtil.exe' -ErrorAction Stop | Select-Object -First 1 if (-not $ToolFile) { throw "IntuneWinAppUtil.exe was not found in the archive downloaded from $DownloadUrl." } # Refuse a tool that is not signed by Microsoft or does not match the expected hash Assert-IntuneWinAppUtilFile -Path $ToolFile.FullName -ExpectedSha256 $ExpectedSha256 if (-not (Test-Path -Path $Path -PathType Container)) { $null = New-Item -Path $Path -ItemType Directory -Force -ErrorAction Stop } $Destination = Join-Path -Path $Path -ChildPath $ToolFile.Name if ((Test-Path -Path $Destination -PathType Leaf) -and -not $Force) { throw "'$Destination' already exists. Use -Force to overwrite it." } Copy-Item -LiteralPath $ToolFile.FullName -Destination $Destination -Force -ErrorAction Stop Write-Verbose "IntuneWinAppUtil.exe has been copied to '$Path'." Get-Item -LiteralPath $Destination } finally { if (Test-Path -LiteralPath $WorkFolder) { Remove-Item -LiteralPath $WorkFolder -Recurse -Force -ErrorAction SilentlyContinue } } Invoke-TelemetryCollection @TelemetryArgs -Stage End } catch { Invoke-TelemetryCollection @TelemetryArgs -Stage End -Failed $true -Exception $_ throw } } |