Updated "Bootstrap portable Remote Desktop Manager version" ;-)
`$PackageRootDirectory = "D:\USR"
$ErrorActionPreference = "Stop"
# Resolve root path
$PackageRootDirectory = Resolve-Path $PackageRootDirectory
$RdmDir = Join-Path $PackageRootDirectory "RDMFree"
$DotNetDir = Join-Path $PackageRootDirectory "NET9"
# Validate RDM directory and exe
if (-not (Test-Path $RdmDir)) {
Write-Error "RDM directory not found at $RdmDir"
exit 1
}
$RdmExe = Join-Path $RdmDir "RemoteDesktopManager.exe"
if (-not (Test-Path $RdmExe)) {
Write-Error "RemoteDesktopManager.exe not found at $RdmExe"
exit 1
}
Write-Host "Fetching .NET 9 release metadata..."
try {
$releasesJson = Invoke-RestMethod -Uri "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/9.0/releases.json"
$latestRelease = $releasesJson.releases[0]
Write-Host "Latest .NET Release: $($latestRelease.'release-version')"
}
catch {
Write-Error "Failed to retrieve .NET 9 metadata: $_"
exit 1
}
# Extract valid zip URLs
$runtimeZip = $latestRelease.runtime.files | Where-Object { $_.rid -eq "win-x64" -and $_.url -like "*.zip" } | Select-Object -First 1
$desktopRuntimeZip = $latestRelease.'windowsdesktop-runtime'.files | Where-Object { $_.rid -eq "win-x64" -and $_.url -like "*.zip" } | Select-Object -First 1
# If missing, fallback to constructed URLs
if (-not $runtimeZip -or -not $desktopRuntimeZip) {
Write-Host "Missing ZIP URLs in metadata. Constructing fallback blob URLs..."
$releaseVer = $latestRelease.'release-version'
$runtimeZip = [PSCustomObject]@{
name = "dotnet-runtime-$releaseVer-win-x64.zip"
url = "https://dotnetcli.blob.core.windows.net/dotnet/Runtime/$releaseVer/dotnet-runtime-$releaseVer-win-x64.zip"
}
$desktopRuntimeZip = [PSCustomObject]@{
name = "windowsdesktop-runtime-$releaseVer-win-x64.zip"
url = "https://dotnetcli.blob.core.windows.net/dotnet/windowsdesktop/$releaseVer/windowsdesktop-runtime-$releaseVer-win-x64.zip"
}
}
Write-Host "`n.NET 9 Download Targets:"
Write-Host " Runtime: $($runtimeZip.name)"
Write-Host " Runtime URL: $($runtimeZip.url)"
Write-Host " Desktop Runtime: $($desktopRuntimeZip.name)"
Write-Host " Desktop URL: $($desktopRuntimeZip.url)"
# Confirm URLs are accessible
foreach ($zip in @($runtimeZip, $desktopRuntimeZip)) {
Write-Host "`nTesting URL: $($zip.url)"
try {
$response = Invoke-WebRequest -Uri $zip.url -Method Head -ErrorAction Stop
if ($response.StatusCode -ne 200) {
throw "Returned status code $($response.StatusCode)"
}
}
catch {
Write-Error "Failed to access $($zip.url): $_"
exit 1
}
}
# Ensure output directory exists
if (-not (Test-Path $DotNetDir)) {
New-Item -Path $DotNetDir -ItemType Directory -Force | Out-Null
}
# Download and install each component
function Install-Zip {
param (
[string]$zipUrl,
[string]$zipName,
[string]$targetDir
)
$zipPath = Join-Path $PackageRootDirectory $zipName
Write-Host "`nDownloading $zipName..."
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -ErrorAction Stop
Write-Host "Unblocking $zipPath..."
Unblock-File -Path $zipPath
Write-Host "Extracting $zipName to $targetDir..."
try {
Expand-Archive -Path $zipPath -DestinationPath $targetDir -Force -ErrorAction Stop
}
catch {
Write-Warning "Expand-Archive failed: $_"
Write-Host "Trying manual extraction..."
try {
Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction Stop
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $targetDir)
}
catch {
Write-Error "Manual extraction failed: $_"
throw
}
}
Write-Host "Cleaning up $zipPath..."
Remove-Item -Path $zipPath -Force
Write-Host "Contents of $targetDir after extraction:"
Get-ChildItem -Path $targetDir -Recurse | Select-Object FullName
}
Install-Zip -zipUrl $runtimeZip.url -zipName $runtimeZip.name -targetDir $DotNetDir
Install-Zip -zipUrl $desktopRuntimeZip.url -zipName $desktopRuntimeZip.name -targetDir $DotNetDir
# Build launcher script
$LaunchScript = @"
`$env:DOTNET_ROOT = "$DotNetDir"
`$rdm = "$RdmExe"
Push-Location "$RdmDir"
if (-not (Test-Path `$rdm)) { Write-Error "RemoteDesktopManager.exe not found at `$rdm"; exit 1 }
& "`$rdm"
Pop-Location
"@
$LaunchScriptPath = Join-Path $PackageRootDirectory "Launch-RdmFree.ps1"
$LaunchScript | Out-File -FilePath $LaunchScriptPath -Encoding UTF8 -Force
Write-Host "`nLauncher created at: $LaunchScriptPath"
Write-Host "Run it with:`n & `"$LaunchScriptPath`""
Write-Host "Or create a shortcut with target:`n powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"$LaunchScriptPath`""
Write-Host "For debugging, use: powershell.exe -NoExit -NoProfile -ExecutionPolicy Bypass -File `"$LaunchScriptPath`""`
Hello,
Thank you for taking the time to share this update with us. We truly appreciate your contribution and will review the documentation article based on the sample you provided.
Best regards,
Jean-Sébastien Simard
Learning experience team leader