|
| 1 | +<# |
| 2 | +.COPYRIGHT |
| 3 | +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. |
| 4 | +See LICENSE in the project root for license information. |
| 5 | +#> |
| 6 | + |
| 7 | +#Microsoft Remote Desktop Client Migration Script |
| 8 | +#Version 1.0 |
| 9 | +#For more info, visit: https://github.com/microsoft/Windows365-PSScripts |
| 10 | + |
| 11 | +Param( |
| 12 | + [parameter(mandatory = $false, HelpMessage = "Where to source installer payload")] |
| 13 | + [ValidateSet('Store','WinGet','MSIX')] |
| 14 | + [string]$source = "Store", |
| 15 | + [parameter(mandatory = $false, HelpMessage = "Value to set auto update reg key")] |
| 16 | + [ValidateSet(0,1,2,3)] |
| 17 | + [int]$DisableAutoUpdate = 0, |
| 18 | + [parameter(mandatory = $false, HelpMessage = "Do not uninstall Remote Desktop if found")] |
| 19 | + [switch]$SkipRemoteDesktopUninstall , |
| 20 | + [parameter(mandatory = $false, HelpMessage = "Log path and file name")] |
| 21 | + [string]$logpath = "$env:windir\temp\MultiTool.log" |
| 22 | +) |
| 23 | + |
| 24 | +#$DisableAutoUpdate values: |
| 25 | +#0: Enables updates (default value) |
| 26 | +#1: Disable updates from all locations |
| 27 | +#2: Disable updates from the Microsoft Store |
| 28 | +#3: Disable updates from the CDN location |
| 29 | + |
| 30 | +#logging function |
| 31 | +function update-log { |
| 32 | + Param( |
| 33 | + [Parameter( |
| 34 | + Mandatory = $true, |
| 35 | + ValueFromPipeline = $true, |
| 36 | + ValueFromPipelineByPropertyName = $true, |
| 37 | + Position = 0 |
| 38 | + )] |
| 39 | + [string]$Data, |
| 40 | + [validateset('Information', 'Warning', 'Error', 'Comment')] |
| 41 | + [string]$Class = "Information", |
| 42 | + [validateset('Console', 'File', 'Both')] |
| 43 | + [string]$Output |
| 44 | + ) |
| 45 | + |
| 46 | + $date = get-date -UFormat "%m/%d/%y %r" |
| 47 | + $String = $Class + " " + $date + " " + $data |
| 48 | + if ($Output -eq "Console") { Write-Output $string | out-host } |
| 49 | + if ($Output -eq "file") { Write-Output $String | out-file -FilePath $logpath -Append } |
| 50 | + if ($Output -eq "Both") { |
| 51 | + Write-Output $string | out-host |
| 52 | + Write-Output $String | out-file -FilePath $logpath -Append |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +#function to uninstall MSRDC by pulling MSIEXEC.EXE GUID from the registy - primary method |
| 57 | +function uninstall-MSRDCreg{ |
| 58 | + |
| 59 | + $MSRCDreg = Get-ItemProperty hklm:\software\microsoft\windows\currentversion\uninstall\* | Where-Object {$_.Displayname -like "*Remote Desktop*"} | Select-Object DisplayName,DisplayVersion,UninstallString,QuietUninstallString |
| 60 | + if ($MSRCDreg.DisplayName -eq "Remote Desktop"){ |
| 61 | + update-log -Data "Remote Desktop Installation Found" -Class Information -Output Both |
| 62 | + $uninstall = $MSRCDreg.uninstallstring -replace "MsiExec.exe /X","" |
| 63 | + update-log -Data "Uninstalling Remote Desktop" -Class Information -Output Both |
| 64 | + |
| 65 | + try{ |
| 66 | + Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $($uninstall) /q /norestart" -ErrorAction Stop |
| 67 | + } |
| 68 | + catch |
| 69 | + { |
| 70 | + update-log -Data "Something went wrong uninstalling Remote Desktop" -Class Error -Output Both |
| 71 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 72 | + } |
| 73 | + } |
| 74 | + else |
| 75 | + { |
| 76 | + update-log -Data "Remote Desktop not detected via registry. Trying as package" -Class Information -Output Both |
| 77 | + uninstall-MSRDC |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +#Function to uninstall MSRDC via uninstall-package as a secondary method |
| 82 | +function uninstall-MSRDC{ |
| 83 | + try{ |
| 84 | + update-log -Data "Looking to see if Remote Desktop is an installed package" -Class Information -Output Both |
| 85 | + try{ |
| 86 | + $MSRDC = Get-Package -Name "Remote Desktop" -ErrorAction Stop |
| 87 | + } |
| 88 | + catch |
| 89 | + { |
| 90 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 91 | + } |
| 92 | + |
| 93 | + if ($MSRDC.name -eq "Remote Desktop"){ |
| 94 | + update-log -Data "Remote Desktop Install Found" -Class Information -Output Both |
| 95 | + #update-log -Data "Version: " $MSRDC.Version |
| 96 | + update-log -Data "Uninstalling Remote Desktop" -Class Information -Output Both |
| 97 | + try{ |
| 98 | + Uninstall-Package -Name "Remote Desktop" -force -ErrorAction Stop| Out-Null |
| 99 | + } |
| 100 | + catch |
| 101 | + { |
| 102 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 103 | + } |
| 104 | + |
| 105 | + update-log -Data "Remote Desktop uninstalled" -Class Information -Output Both |
| 106 | + } |
| 107 | + } |
| 108 | + catch |
| 109 | + { |
| 110 | + update-log -Data "Remote Desktop not found as package." -Class Information -Output Both |
| 111 | + } |
| 112 | +} |
| 113 | + |
| 114 | +#function to install Windows App from MS Store - write install process log to $env:windir\temp\WindowsAppStoreInstall.log |
| 115 | +function install-windowsappstore{ |
| 116 | + update-log -Data "Writing install process log to $env:windir\temp\WindowsAppStoreInstall.log" -Class Information -Output Both |
| 117 | + try{ |
| 118 | + invoke-command -ScriptBlock { winget install 9N1F85V9T8BN --accept-package-agreements --accept-source-agreements} | Out-File -FilePath $env:windir\temp\WindowsAppStoreInstall.log -Append #MS Store Install |
| 119 | + } |
| 120 | + catch |
| 121 | + { |
| 122 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 123 | + Exit 1 |
| 124 | + } |
| 125 | +} |
| 126 | + |
| 127 | +#Function to install Windows App from Winget CDN - write install process log to $env:windir\temp\WindowsAppWinGetInstall.log |
| 128 | +function install-windowsappwinget{ |
| 129 | + update-log -Data "Writing install process log to $env:windir\temp\WindowsAppWinGetInstall.log" -Class Information -Output Both |
| 130 | + try{ |
| 131 | + invoke-command -ScriptBlock {winget install Microsoft.WindowsApp --accept-package-agreements --accept-source-agreements} | Out-File -FilePath $env:windir\temp\WindowsAppWinGetInstall.log -Append #Winget Install |
| 132 | + } |
| 133 | + catch |
| 134 | + { |
| 135 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 136 | + Exit 1 |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +#Function to install Windows App from MSIX direct download |
| 141 | +function install-windowsappMSIX{ |
| 142 | + |
| 143 | + try{ |
| 144 | + if ((test-path -Path $env:windir\Temp\WindowsApp.msix) -eq $true){Remove-Item -Path $env:windir\Temp\WindowsApp.msix -Force -ErrorAction Stop} |
| 145 | + |
| 146 | + $Payload = Invoke-WebRequest -uri "https://go.microsoft.com/fwlink/?linkid=2262633" -UseBasicParsing -OutFile $env:windir\Temp\WindowsApp.msix -PassThru -ErrorAction Stop |
| 147 | + $filename = ($Payload.BaseResponse.ResponseUri.AbsolutePath -replace ".*/") |
| 148 | + |
| 149 | + if ((test-path -Path $env:windir\Temp\$filename) -eq $true){Remove-Item -Path $env:windir\Temp\$filename -Force -ErrorAction Stop} |
| 150 | + |
| 151 | + Rename-Item -Path $env:windir\Temp\WindowsApp.msix -NewName $filename -Force -ErrorAction Stop |
| 152 | + update-log -Data "Downloaded $filename to $env:windir\temp" -Class Information -Output Both |
| 153 | + } |
| 154 | + catch{ |
| 155 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 156 | + } |
| 157 | + try{ |
| 158 | + Add-AppxPackage -Path $env:windir\temp\$filename -ErrorAction Stop |
| 159 | + } |
| 160 | + catch{ |
| 161 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 162 | + } |
| 163 | +} |
| 164 | + |
| 165 | +#Function to check if Windows App is installed |
| 166 | +function invoke-WAInstallCheck{ |
| 167 | + if ((($testWA = get-appxpackage -name MicrosoftCorporationII.Windows365).name) -eq "MicrosoftCorporationII.Windows365" ){ |
| 168 | + update-log -Data "Windows App Installation found." -Class Information -Output Both |
| 169 | + Return 0 |
| 170 | + } |
| 171 | + else |
| 172 | + { |
| 173 | + update-log -Data "Windows App installation not found." -Class Information -Output Both |
| 174 | + Return 1 |
| 175 | + } |
| 176 | +} |
| 177 | + |
| 178 | +#function to set the registry key to control auto updates |
| 179 | +function invoke-disableautoupdate($num){ |
| 180 | + update-log -Data "Setting disableautoupdate reg key" -Class Information -Output Both |
| 181 | + $path = "HKLM:\SOFTWARE\Microsoft\WindowsApp" |
| 182 | + If (!(Test-Path $path)) { |
| 183 | + New-Item -Path $path -Force |
| 184 | + } |
| 185 | + try{ |
| 186 | + New-ItemProperty -Path $path -Name DisableAutomaticUpdates -PropertyType DWORD -Value $num -Force -ErrorAction Stop| Out-Null |
| 187 | + } |
| 188 | + catch{ |
| 189 | + Update-Log -data $_.Exception.Message -Class Error -Output Both |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +#check if Windows App is installed. If so, skip installation. Else, install |
| 194 | +if ((invoke-WAInstallCheck) -eq 0){ |
| 195 | + update-log -Data "Skipping Windows App Installation" -Class Information -Output Both |
| 196 | + } |
| 197 | +else |
| 198 | + { |
| 199 | + if ($source -eq "Store"){ |
| 200 | + update-log -Data "Starting Windows App installation from Microsoft Store" -Class Information -Output Both |
| 201 | + install-windowsappstore |
| 202 | + } |
| 203 | + if ($source -eq "WinGet"){ |
| 204 | + update-log -Data "Starting Windows App installation from WinGet" -Class Information -Output Both |
| 205 | + install-windowsappwinget |
| 206 | + } |
| 207 | + if ($source -eq "MSIX"){ |
| 208 | + update-log -Data "Starting Windows App installation from MSIX download" -Class Information -Output Both |
| 209 | + install-windowsappMSIX |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | +#verify if Windows App has now been installed. If so, move to uninstalling MSRDC. Else, fail. |
| 214 | +if ((invoke-WAInstallCheck) -eq 0){ |
| 215 | + update-log -Data "Validated Windows App Installed" -Class Information -Output Both |
| 216 | + if ($SkipRemoteDesktopUninstall -eq $False){uninstall-MSRDCreg} |
| 217 | + } |
| 218 | + else |
| 219 | + { |
| 220 | + update-log -Data "Windows App does not appear to be installed. Something went wrong" -Class Error -Output Both |
| 221 | + exit 1 |
| 222 | + } |
| 223 | + |
| 224 | +#Apply auto update registry key if option selected |
| 225 | +if ($DisableAutoUpdate -ne 0){ |
| 226 | + if ($DisableAutoUpdate -eq 1){invoke-disableautoupdate -num 1} |
| 227 | + if ($DisableAutoUpdate -eq 2){invoke-disableautoupdate -num 2} |
| 228 | + if ($DisableAutoUpdate -eq 3){invoke-disableautoupdate -num 3} |
| 229 | +} |
| 230 | + |
| 231 | +update-log -Data "Installation Complete" -Class Information -Output Both |
| 232 | +update-log -data "************" -Class Information -Output File |
0 commit comments