|
| 1 | +function Invoke-DownloadIntuneTool { |
| 2 | + <# |
| 3 | + .SYNOPSIS |
| 4 | + Downloads the latest IntuneWinAppUtil.exe from GitHub and caches it under |
| 5 | + %APPDATA%\IntuneWinAppUtilGUI\bin. |
| 6 | + .DESCRIPTION |
| 7 | + - Forces TLS 1.2 for GitHub downloads. |
| 8 | + - Creates (or ensures) the bin directory under $env:APPDATA\IntuneWinAppUtilGUI\bin. |
| 9 | + - Removes any stale IntuneWinAppUtil.exe in the bin directory. |
| 10 | + - Downloads the repository master ZIP, extracts it to a unique temp folder, |
| 11 | + locates IntuneWinAppUtil.exe, and copies it into the bin directory. |
| 12 | + - Cleans up all temp files/folders in a finally block. |
| 13 | + - Returns the full path to the cached IntuneWinAppUtil.exe. |
| 14 | + - Throws on failure (caller can catch and show a message box). |
| 15 | + .PARAMETER DestinationRoot |
| 16 | + Optional base path for the cache (default: $env:APPDATA\IntuneWinAppUtilGUI). |
| 17 | + .PARAMETER RepoZipUrl |
| 18 | + Optional ZIP URL (default: master branch of Microsoft-Win32-Content-Prep-Tool). |
| 19 | + .OUTPUTS |
| 20 | + [string] Full path to IntuneWinAppUtil.exe. |
| 21 | + .EXAMPLE |
| 22 | + $exe = Invoke-DownloadIntuneTool |
| 23 | + # $exe now points to %APPDATA%\IntuneWinAppUtilGUI\bin\IntuneWinAppUtil.exe |
| 24 | + #> |
| 25 | + |
| 26 | + [CmdletBinding()] |
| 27 | + param( |
| 28 | + [string]$DestinationRoot = (Join-Path $env:APPDATA 'IntuneWinAppUtilGUI'), |
| 29 | + [string]$RepoZipUrl = 'https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool/archive/refs/heads/master.zip' |
| 30 | + ) |
| 31 | + |
| 32 | + # Ensure TLS 1.2 for GitHub |
| 33 | + try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {} |
| 34 | + |
| 35 | + $binDir = Join-Path $DestinationRoot 'bin' |
| 36 | + $exePath = Join-Path $binDir 'IntuneWinAppUtil.exe' |
| 37 | + $tempZip = Join-Path $env:TEMP ("IntuneWinAppUtil-{0}.zip" -f ([guid]::NewGuid())) |
| 38 | + $tempDir = Join-Path $env:TEMP ("IntuneExtract-{0}" -f ([guid]::NewGuid())) |
| 39 | + |
| 40 | + try { |
| 41 | + # Prepare target folder and clean stale exe |
| 42 | + New-Item -ItemType Directory -Path $binDir -Force | Out-Null |
| 43 | + if (Test-Path $exePath) { Remove-Item $exePath -Force -ErrorAction SilentlyContinue } |
| 44 | + |
| 45 | + # Download |
| 46 | + Invoke-WebRequest -Uri $RepoZipUrl -OutFile $tempZip -UseBasicParsing -ErrorAction Stop |
| 47 | + |
| 48 | + # Extract (fallback if overwrite overload isn't available) |
| 49 | + New-Item -ItemType Directory -Path $tempDir -Force | Out-Null |
| 50 | + $zipType = [System.IO.Compression.ZipFile] |
| 51 | + $hasOverwrite = $zipType.GetMethod( |
| 52 | + 'ExtractToDirectory', |
| 53 | + [Reflection.BindingFlags]'Public, Static', |
| 54 | + $null, |
| 55 | + @([string], [string], [bool]), |
| 56 | + $null |
| 57 | + ) |
| 58 | + if ($hasOverwrite) { |
| 59 | + [System.IO.Compression.ZipFile]::ExtractToDirectory($tempZip, $tempDir, $true) |
| 60 | + } else { |
| 61 | + [System.IO.Compression.ZipFile]::ExtractToDirectory($tempZip, $tempDir) |
| 62 | + } |
| 63 | + |
| 64 | + # Locate exe |
| 65 | + $found = Get-ChildItem -Path $tempDir -Recurse -Filter 'IntuneWinAppUtil.exe' -File -ErrorAction SilentlyContinue | Select-Object -First 1 |
| 66 | + if (-not $found) { |
| 67 | + throw "IntuneWinAppUtil.exe not found in the extracted archive." |
| 68 | + } |
| 69 | + |
| 70 | + # Copy into cache |
| 71 | + Copy-Item -Path $found.FullName -Destination $exePath -Force |
| 72 | + return $exePath |
| 73 | + } catch { |
| 74 | + throw $_ |
| 75 | + } finally { |
| 76 | + # Best-effort cleanup |
| 77 | + foreach ($p in @($tempZip, $tempDir)) { |
| 78 | + try { |
| 79 | + if (Test-Path $p) { |
| 80 | + if (Test-Path $p -PathType Container) { |
| 81 | + Remove-Item $p -Recurse -Force -ErrorAction SilentlyContinue |
| 82 | + } else { |
| 83 | + Remove-Item $p -Force -ErrorAction SilentlyContinue |
| 84 | + } |
| 85 | + } |
| 86 | + } catch {} |
| 87 | + } |
| 88 | + } |
| 89 | +} |
0 commit comments