Care and feeding for your non-persistent Desktop and Server VDI environments is a regular administrative process for IT Admins, and with their non-persistent design, many tools in the IT Toolbelt don’t perform well when these machines revert when rebooted. Also these images often need special steps to be done when the machine is shutdown for proper capture and deployment. In particular;
- Removing the machine from Entra AD
- Scanning the image with AV, especially when AV products can identify the scanned files haven’t been changed and are skipped on catch-up scans.
- Caching the Group Policy Objects to the image.
- Refreshing the WEM local cache
- Resetting identifiers for software in the registry, or filesystem.
- and many more
Also keeping all the internet delivered software packages on the image also can be an arduous task. So why not leverage scriptable update processes, if possible? Like my Teams PowerShell update script I host on this site. Or utilize internet hosted package managers, like https://www.chocolatey.org, to deploy and manage internet hosted applications.
My Process
So I create my initial machine image. People call this a golden image, a maintenance machine, or as I like to refer to it. Patient Zero. Since your provisioning tools will create auto numbered machines starting at 1, I will often name this machine with the same prefix, and 0 as the suffix. So if for instance my pool would have machines named Win11-01 to Win11-10, I would name my maintenance machine for that catalog as Win11-00. I also will store this maintenance machine in the same OU and Configuration Set as the Read-Only machines built from it.
Now when it is time to update, my update will always follow these steps.
- Boot the maintenance machine (This machine should be turned off 100% of the time when not actively being used, to keep it clean and safe from anything on the network.)
- Run the Machine-Updates PowerShell script.
- Run Windows Updates to install any updates detected from the script in Step 2.
- Do any additional modifications, installations, removals, etc to the image that isn’t handled programattically.
- Reboot the machine.
- Run the Machine-Sealing PowerShell script to prepare the image for capture, and shut it down when completed.
- Deploy the Image via any provisioning method, such as MCS, PVS, or Omnissa Deployment processes.
Setup Process
Extract the zip file attached to this article to a network location of your choice.

If you don’t use Teams or OneDrive in your organization, you can delete those PS1 files and the update script will continue without them.
Sign the PowerShell scripts with a code signing certificate generated in your AD Domain. See my handy article that will be coming soon to my site, and will be linked here. If you don’t have the ability to sign your PowerShell objects, you can use the set-executionpolicy to allow the script to run. Just be sure and set it back to restricted, such as by adding it to the end of your Machine-Sealing.ps1.
Then from your maintenance machine, just right click on Machine-Updates.ps1 and select Run with PowerShell.
The update script does the following processes.
- The PowerShell script will prompt you to elevate the script to administrative mode if you aren’t there already.
- The script will then start a Transcript Log of the Update process, and will store it under %temp%\Updates.log.
- Starts the BITS and Windows Updates services, and connects to Microsoft to get available updates for your machine. It won’t install them automatically. You can modify the ArgumentList on line 27 to change this behavior.
- Executes my Teams Install/Update script, unless you delete that script from the source.
- Checks for M365 Click to Run and executes it for updates.
- Executes my OneDrive Install/Update script, unless you delete that script from the source. It will give you the installed and available versions, and will prompt you to install or update it.
- Checks to see if choco.exe is used for package installs. If it is, it will execute an update of all installed chocolatey packages.
- If choco.exe isn’t used, it will then look for Chrome and Firefox installs, if found, it will launch their update processes.
- The script will then do a Group Policy Update to refresh all the GPOs
- It will then complete the transcript and close out the PowerShell script, you now can manually do any additional processes on the maintenance machines.
When you are ready to seal your machine and deploy it to your users, just right click on Machine-Sealing.ps1 and select Run with PowerShell. The machine will shut itself down once the script completes, and you then can deploy this image as needed.
The seal script does the following.
- The PowerShell script will prompt you to elevate the script to administrative mode if you aren’t there already.
- Checks to see if FSLogix is installed in the environment, and if it is used, remove the CCDLocations and VHDLocations from the registry. These items are placed into the system as Group Policy Preferences, so they are not removed if your GPO changes for FSLogix locations. The same or updated entries will be replaced as a later portion of this script.
- Checks to see if uberAgent is installed, and if it is, stop the service and generalize the registry for the next boot.
- Updates the Group Policy to replace any entries previously removed in Step 2.
- Repairs the SetDisplayRequiredMode setting in the registry if needed to guarantee screen saver timeouts in Server OS deployments.
- Installs the necessary Teams registry entries to ProcessWhiteList msedgewebview2, and to disable auto-updates of the Teams client.
- Stops and disables Windows Update Services
- Runs a Windows Defender Update and quick scan if Defender is installed
- Updates the WEM Cache if WEM is installed
- Disables any Scheduled Tasks in the root of the Scheduled Tasks console. If your organization uses Scheduled Tasks, make sure to store those in a custom folder under the root to prevent them from being disabled.
- Clear Temp Files and Desktop shortcuts from the C:\Users\Public\Desktop folder. If you are using that shared Desktop storage location, be sure and remove that entry on line 83.
- Remove Azure Arc tray icon setup.
- Remove the maintenance machine from Entra AD
- Gracefully shuts the machine down for proper capture.
If you boot this machine again, just ensure you use the sealing script to shut the machine down for capture, as you will want the necessary generalizations in place before the image is deployed.
Feel free to add any additional entries into the Machine Updates or Machine Sealing script to automate your process. Here are some examples of things my clients have added to their copies of these scripts.
- Update and Generalize Cisco AMP on shutdown.
- Update CrowdStrike cached definitions.
- Join SCCM, update the image from corporate packages, and then leave SCCM.
- Remove Machine IDs from HKLM registry entries for their in-house software packages.
- Update wget deployed packages.
- Deploy scheduled tasks to machines to disable offload on vmxnet3 adapters on new machine creations. (24H2 Issues)
Planned Updates
- Modifying the Workplace Join Scheduled Task to run at Startup and Login for Hybrid Joined Machines.
- Adding a better VMXNet3 offloading script as an option like the Teams and OneDrive ones.
- Identifying additional package management systems, and triggering them like it triggers choco.