Skip to content

Commit 8834a74

Browse files
Remote Desktop Migration Tool (#46)
* Update Get-AVDW365Gateways.ps1 Changed URL to GCCH JSON Download * Squashed commit of the following: commit 33f3d0b Author: Donna Ryan <100233767+DonnaRyanMicrosoft@users.noreply.github.com> Date: Wed Mar 26 15:17:12 2025 -0400 Initial Commit Includes both detection and remediation script, plus readme.md files * Initial Commit * Changed MSRDC uninstall order Also some minor formatting changes * DisableAutoUpdate reg key support created function to allow admins to set the DisableAutoUpdate registry key * Updated outputs minor bug fix * Added logging for install processes Store and Winget installation output now logged separately * Fixed ID10T error deleted extra stuff that shouldn't have been pasted * added comments * Added Param Block commented out old variable assignments * Formatting * Logging enabled + error handling Added logging module, Added error handling Added rename MSIX download and rename to original file name. * Added Readme.Md instructions Wrote the basic instructions * Changed MSRDC Uninstall Parameter Changed parameter type to Switch. This makes the parameter true if present, otherwise false. Changed the name of the parameter for clarity. * Updated Readme.md Removed notes from head of script. Updated Readme.md * Formatting and Copyright Minor formatting changes with copyright, name, and version added * Changed name of file to new name renamed script * Changed Folder Name Renamed Folder * Updated Documentation Also changed log name to reflect new script name * Added WAIT to msiexec command, fixed RD query Added -WAIT to the msiexec uninstall command string. Also changed RD client query from "-like" to "-eq" --------- Signed-off-by: Donna Ryan <100233767+DonnaRyanMicrosoft@users.noreply.github.com>
1 parent bffda68 commit 8834a74

2 files changed

Lines changed: 211 additions & 83 deletions

File tree

Remote Desktop Client Migration Script/Remote Desktop Client Migration Script.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Param(
1818
[parameter(mandatory = $false, HelpMessage = "Do not uninstall Remote Desktop if found")]
1919
[switch]$SkipRemoteDesktopUninstall ,
2020
[parameter(mandatory = $false, HelpMessage = "Log path and file name")]
21-
[string]$logpath = "$env:windir\temp\MultiTool.log"
21+
[string]$logpath = "$env:windir\temp\RDC-Migration.log"
2222
)
2323

2424
#$DisableAutoUpdate values:
@@ -56,14 +56,14 @@ function update-log {
5656
#function to uninstall MSRDC by pulling MSIEXEC.EXE GUID from the registy - primary method
5757
function uninstall-MSRDCreg{
5858

59-
$MSRCDreg = Get-ItemProperty hklm:\software\microsoft\windows\currentversion\uninstall\* | Where-Object {$_.Displayname -like "*Remote Desktop*"} | Select-Object DisplayName,DisplayVersion,UninstallString,QuietUninstallString
59+
$MSRCDreg = Get-ItemProperty hklm:\software\microsoft\windows\currentversion\uninstall\* | Where-Object {$_.Displayname -eq "Remote Desktop"} | Select-Object DisplayName,DisplayVersion,UninstallString,QuietUninstallString
6060
if ($MSRCDreg.DisplayName -eq "Remote Desktop"){
6161
update-log -Data "Remote Desktop Installation Found" -Class Information -Output Both
6262
$uninstall = $MSRCDreg.uninstallstring -replace "MsiExec.exe /X",""
6363
update-log -Data "Uninstalling Remote Desktop" -Class Information -Output Both
6464

6565
try{
66-
Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $($uninstall) /q /norestart" -ErrorAction Stop
66+
Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $($uninstall) /q /norestart" -Wait -ErrorAction Stop
6767
}
6868
catch
6969
{
Lines changed: 208 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,233 @@
1-
# Windows App Installer MultiTool
1+
# Remote Desktop Client Migration Script
22

3-
A PowerShell utility to detect and install the Windows 365 "Windows App" client, optionally set its auto-update registry key, and remove legacy "Remote Desktop" installs when present. This README documents the script behavior, parameters, examples, logs and troubleshooting.
3+
## Overview
4+
This PowerShell script automates the migration from the legacy Remote Desktop client to the new **Windows App** (formerly Windows 365). It handles the installation of Windows App from multiple sources and optionally uninstalls the old Remote Desktop client.
5+
6+
**Version:** 1.0
7+
**Copyright:** Microsoft Corporation. All rights reserved. Licensed under the MIT license.
48

59
## What it does
6-
- Detects whether the Windows App (`MicrosoftCorporationII.Windows365`) is installed.
10+
- Detects whether the Windows App (`MicrosoftCorporationII.Windows365`) is already installed
711
- Installs the Windows App from one of three sources:
812
- Microsoft Store (via winget id `9N1F85V9T8BN`) — `Store` (default)
913
- WinGet CDN package (`Microsoft.WindowsApp`) — `WinGet`
1014
- Direct MSIX download (FWLINK) and `Add-AppxPackage``MSIX`
11-
- Optionally writes `HKLM:\SOFTWARE\Microsoft\WindowsApp\DisableAutomaticUpdates` to control auto updates.
12-
- Optionally uninstalls legacy "Remote Desktop" via registry/MSI or package uninstall methods.
13-
- Writes logs to console and to the configured log file.
14-
15-
## Files
16-
- `Windows App Installer.ps1` — main script.
17-
- Runtime logs:
18-
- Default log: `%windir%\Temp\MultiTool.log` (can be changed with `-logpath`)
19-
- Store install trace: `%windir%\Temp\WindowsAppStoreInstall.log`
20-
- WinGet install trace: `%windir%\Temp\WindowsAppWinGetInstall.log`
21-
22-
## Requirements
23-
- Windows (modern Windows 10/11 recommended).
24-
- PowerShell (script compatible with Windows PowerShell 5.1 and later).
25-
- Administrative privileges to install packages and write to HKLM.
26-
- Internet access for Store/WinGet/MSIX downloads.
27-
- Winget and/or Microsoft Store available for corresponding install methods (use `MSIX` when Store is blocked).
15+
- Validates successful Windows App installation
16+
- Optionally uninstalls legacy "Remote Desktop" client using two fallback methods:
17+
- Primary: Registry-based MSI uninstall
18+
- Fallback: Package-based uninstall
19+
- Optionally configures automatic update behavior via registry key
20+
- Comprehensive logging to console and file
21+
22+
## Prerequisites
23+
- Windows 10/11 operating system
24+
- PowerShell 5.1 or later
25+
- Administrator privileges (required for package installation and registry modifications)
26+
- Internet connectivity (for downloading Windows App)
27+
- WinGet (if using WinGet installation method)
28+
- Microsoft Store access (if using Store installation method, or use `MSIX` when Store is blocked)
2829

2930
## Parameters
30-
- `-source` (string)
31-
Where to source the installer payload. Allowed values: `Store` (default), `WinGet`, `MSIX`.
32-
- `-DisableAutoUpdate` (int)
33-
Sets the registry DWORD `HKLM:\SOFTWARE\Microsoft\WindowsApp\DisableAutomaticUpdates`. Allowed values:
34-
- `0` — Enable updates (default)
35-
- `1` — Disable updates from all locations
36-
- `2` — Disable updates from Microsoft Store
37-
- `3` — Disable updates from the CDN
38-
- `-SkipRemoteDesktopUninstall` (switch)
39-
If present, skip attempting to remove legacy Remote Desktop.
40-
- `-logpath` (string)
41-
Path to the primary log file (default: `$env:windir\temp\MultiTool.log`).
42-
43-
## High-level functions (what they do)
44-
- `update-log` — logging helper (console / file / both).
45-
- `invoke-WAInstallCheck` — returns 0 if Windows App is present, 1 otherwise.
46-
- `install-windowsappstore` — triggers Store install (uses winget id `9N1F85V9T8BN`) and logs to temp file.
47-
- `install-windowsappwinget` — triggers WinGet install for `Microsoft.WindowsApp` and logs to temp file.
48-
- `install-windowsappMSIX` — downloads MSIX via FWLINK and installs with `Add-AppxPackage`.
49-
- `uninstall-MSRDCreg` — primary uninstall of legacy Remote Desktop via registry MSI uninstall string.
50-
- `uninstall-MSRDC` — secondary uninstall via `Get-Package` / `Uninstall-Package`.
51-
- `invoke-disableautoupdate` — creates/sets `DisableAutomaticUpdates` DWORD.
52-
53-
## Usage examples (run elevated)
54-
Default (Store) install:
31+
32+
### `-source`
33+
Specifies where to source the Windows App installer payload.
34+
35+
**Type:** String
36+
**Valid Values:** `Store`, `WinGet`, `MSIX`
37+
**Default:** `Store`
38+
**Required:** No
39+
40+
- `Store`: Installs from Microsoft Store (ID: 9N1F85V9T8BN)
41+
- `WinGet`: Installs from WinGet CDN using package ID `Microsoft.WindowsApp`
42+
- `MSIX`: Downloads and installs directly from MSIX package (use when Store is blocked)
43+
44+
### `-DisableAutoUpdate`
45+
Controls the automatic update behavior for Windows App by setting the registry key `HKLM:\SOFTWARE\Microsoft\WindowsApp\DisableAutomaticUpdates`.
46+
47+
**Type:** Integer
48+
**Valid Values:** `0`, `1`, `2`, `3`
49+
**Default:** `0`
50+
**Required:** No
51+
52+
- `0`: Enables updates (default)
53+
- `1`: Disables updates from all locations
54+
- `2`: Disables updates from Microsoft Store only
55+
- `3`: Disables updates from CDN location only
56+
57+
### `-SkipRemoteDesktopUninstall`
58+
Prevents the script from uninstalling the Remote Desktop client.
59+
60+
**Type:** Switch
61+
**Default:** `$false`
62+
**Required:** No
63+
64+
### `-logpath`
65+
Specifies the location and filename for the script log.
66+
67+
**Type:** String
68+
**Default:** `$env:windir\temp\RDC-Migration.log`
69+
**Required:** No
70+
71+
## Usage Examples
72+
73+
### Basic Usage (Microsoft Store - Default)
74+
```powershell
75+
.\Remote Desktop Client Migration Script.ps1
76+
```
77+
78+
### Install from WinGet
79+
```powershell
80+
.\Remote Desktop Client Migration Script.ps1 -source WinGet
81+
```
82+
83+
### Install from MSIX (Direct Download)
84+
```powershell
85+
.\Remote Desktop Client Migration Script.ps1 -source MSIX
86+
```
87+
88+
### Disable All Auto-Updates
89+
```powershell
90+
.\Remote Desktop Client Migration Script.ps1 -DisableAutoUpdate 1
91+
```
92+
93+
### Disable Store Updates Only
94+
```powershell
95+
.\Remote Desktop Client Migration Script.ps1 -source WinGet -DisableAutoUpdate 2
96+
```
97+
98+
### Keep Remote Desktop Client Installed
5599
```powershell
56-
PowerShell -ExecutionPolicy Bypass -File ".\Windows App Installer.ps1"
100+
.\Remote Desktop Client Migration Script.ps1 -SkipRemoteDesktopUninstall
57101
```
58102

59-
Install via WinGet and disable Store updates (set key = 2):
103+
### Custom Log Location
60104
```powershell
61-
PowerShell -ExecutionPolicy Bypass -File ".\Windows App Installer.ps1" -source WinGet -DisableAutoUpdate 2
105+
.\Remote Desktop Client Migration Script.ps1 -logpath "C:\Logs\RDC-Migration.log"
62106
```
63107

64-
Install via MSIX and skip removing legacy Remote Desktop:
108+
### Full Example with All Parameters
65109
```powershell
66-
PowerShell -ExecutionPolicy Bypass -File ".\Windows App Installer.ps1" -source MSIX -SkipRemoteDesktopUninstall
110+
.\Remote Desktop Client Migration Script.ps1 -source Store -DisableAutoUpdate 2 -logpath "C:\Logs\migration.log"
67111
```
68112

69-
Specify an alternate log file:
113+
### Run with Execution Policy Bypass
70114
```powershell
71-
PowerShell -ExecutionPolicy Bypass -File ".\Windows App Installer.ps1" -logpath "C:\Temp\WinAppInstall.log"
115+
PowerShell -ExecutionPolicy Bypass -File ".\Remote Desktop Client Migration Script.ps1" -source MSIX -SkipRemoteDesktopUninstall
72116
```
73117

74-
## Exit behavior & logs
75-
- On fatal install failures the script calls `exit 1`.
76-
- Normal success writes completion messages to logs and returns normally.
77-
- Check logs for details:
78-
- Primary: `%windir%\Temp\MultiTool.log` (or the `-logpath` you supplied)
79-
- Install traces: `%windir%\Temp\WindowsAppStoreInstall.log`, `%windir%\Temp\WindowsAppWinGetInstall.log`
118+
## How It Works
119+
120+
The script follows this workflow:
121+
122+
1. **Pre-Installation Check**: Verifies if Windows App is already installed
123+
- If found, skips installation
124+
- If not found, proceeds to installation
125+
126+
2. **Installation**: Installs Windows App from the specified source
127+
- **Store**: Uses WinGet with Store ID `9N1F85V9T8BN`
128+
- **WinGet**: Uses WinGet CDN package `Microsoft.WindowsApp`
129+
- **MSIX**: Downloads from `https://go.microsoft.com/fwlink/?linkid=2262633` and installs via `Add-AppxPackage`
130+
131+
3. **Validation**: Confirms successful Windows App installation
132+
- Checks for AppX package `MicrosoftCorporationII.Windows365`
133+
- Exits with error code 1 if not found
134+
135+
4. **Uninstallation** (unless `-SkipRemoteDesktopUninstall` is used):
136+
- **Primary Method**: Registry-based MSI uninstall using `MsiExec.exe /x`
137+
- **Fallback Method**: Package-based uninstall using `Uninstall-Package`
138+
139+
5. **Configuration**: Applies auto-update registry settings if specified
140+
141+
6. **Completion**: Logs final status and exits
142+
143+
## Log Files
144+
145+
### Main Script Log
146+
- **Default Location:** `%windir%\temp\RDC-Migration.log`
147+
- **Configurable via:** `-logpath` parameter
148+
- **Contains:** Detailed information about script execution with timestamps, actions, warnings, and errors
149+
150+
### Installation Process Logs
151+
- **Store Installation:** `%windir%\temp\WindowsAppStoreInstall.log`
152+
- **WinGet Installation:** `%windir%\temp\WindowsAppWinGetInstall.log`
153+
- **MSIX Download:** Payload downloaded to `%windir%\temp\`
154+
155+
### Log Format
156+
Each log entry includes:
157+
- Log level (Information, Warning, Error, Comment)
158+
- Timestamp in format: `MM/DD/YY HH:MM:SS AM/PM`
159+
- Descriptive message
160+
161+
## Exit Codes
162+
- **0**: Success (normal completion)
163+
- **1**: Failure (Windows App installation failed or not detected after installation)
164+
165+
## Script Functions
166+
167+
The script includes the following key functions:
168+
169+
- **`update-log`**: Logging helper that writes to console and/or file with timestamps
170+
- **`invoke-WAInstallCheck`**: Checks if Windows App is installed (returns 0 if present, 1 if not)
171+
- **`install-windowsappstore`**: Installs Windows App from Microsoft Store via WinGet
172+
- **`install-windowsappwinget`**: Installs Windows App from WinGet CDN
173+
- **`install-windowsappMSIX`**: Downloads and installs Windows App from direct MSIX download
174+
- **`uninstall-MSRDCreg`**: Primary method to uninstall Remote Desktop via registry MSI uninstall string
175+
- **`uninstall-MSRDC`**: Fallback method to uninstall Remote Desktop via `Get-Package`/`Uninstall-Package`
176+
- **`invoke-disableautoupdate`**: Creates/sets the `DisableAutomaticUpdates` registry key
177+
178+
## Registry Configuration
179+
180+
When using `-DisableAutoUpdate`, the script creates/modifies:
181+
182+
```
183+
Registry Key: HKLM:\SOFTWARE\Microsoft\WindowsApp
184+
Value Name: DisableAutomaticUpdates
185+
Value Type: DWORD
186+
```
80187

81188
## Troubleshooting
82-
- Permission / access denied:
83-
- Run PowerShell as Administrator.
84-
- Winget not found or Microsoft Store disabled:
85-
- Use `-source MSIX` to attempt a direct MSIX install.
86-
- `Add-AppxPackage` errors:
87-
- Ensure sideloading is allowed or that the package signature and system policy permit the install.
88-
- Remote Desktop uninstall fails:
89-
- The script tries registry/MSI first then package uninstall. Manual removal may be required if uninstall strings are missing.
90-
- For diagnostics:
91-
- Inspect the three logs listed above for error messages and stack traces.
92-
93-
## Known limitations
94-
- Script assumes availability of `winget` for Store/WinGet flows; environments with Store disabled may fail unless `MSIX` chosen.
95-
- Error handling is present but could be more granular (some functions catch and log but do not standardize exit codes).
96-
- Not explicitly tested on Windows LTSC or older Windows 10 branches — behavior may vary.
97-
98-
## Recommended next steps
99-
- Add a `-WhatIf`/dry-run mode.
100-
- Add explicit checks for `winget`/Store presence before choosing install path.
101-
- Convert `update-log` to structured logging (timestamped JSON) for automation.
102-
- Add more granular exit codes to represent specific failure types.
189+
190+
### Permission or Access Denied Errors
191+
- Ensure PowerShell is running as Administrator
192+
- Verify write permissions to log directory and registry
193+
194+
### Windows App Installation Fails
195+
- **Check Internet Connectivity**: Ensure the device can reach Microsoft services
196+
- **WinGet Not Found**: If using Store or WinGet source, verify WinGet is installed
197+
- **Microsoft Store Disabled**: Use `-source MSIX` for direct MSIX installation
198+
- **Review Logs**: Check installation logs in `%windir%\temp\` for specific errors
199+
200+
### AppX Package Installation Errors
201+
- Ensure sideloading is allowed in Windows settings
202+
- Verify package signature and system policy permit installation
203+
- Check if Developer Mode is required
204+
205+
### Remote Desktop Uninstall Issues
206+
- The script automatically tries two methods (registry-based MSI and package-based)
207+
- Check the main log file for specific error messages
208+
- Use `-SkipRemoteDesktopUninstall` to bypass uninstallation if problematic
209+
- Manual removal may be required if uninstall strings are missing
210+
211+
### Script Exits with Error Code 1
212+
- Windows App installation failed or was not detected after installation
213+
- Review all log files for error details
214+
- Try an alternative installation source
215+
216+
### WinGet Command Not Recognized
217+
- Install App Installer from Microsoft Store
218+
- Or use `-source MSIX` to bypass WinGet requirement
219+
220+
## Known Limitations
221+
- Script assumes WinGet availability for Store/WinGet installation methods
222+
- Error handling logs exceptions but may not provide granular exit codes for all failure types
223+
- Not extensively tested on Windows LTSC or older Windows 10 branches
224+
- Requires internet connectivity for all installation sources
225+
226+
## Additional Information
227+
228+
For more information about this script and other Windows 365 PowerShell scripts, visit:
229+
**https://github.com/microsoft/Windows365-PSScripts**
103230

104231
## License
105-
No license is specified. Add a `LICENSE` file if you intend to publish or share.
232+
Copyright (c) Microsoft Corporation. All rights reserved.
233+
Licensed under the MIT license. See LICENSE in the project root for license information.

0 commit comments

Comments
 (0)