Virtual Machine Template Patching


Everyone knows it, as soon as a new virtual machine template has been created it’s already out of date because new important security hotfixes are available. These are not just small updates, those can get easily be a few hundred megabytes. However, to simplify new deployments, Microsoft at least releases regularly new ISO images which includes already the latest update:

Virtual Machine Template Patching

What does this mean for the previously created virtual machine template? Either it is left in an unpatched state and every new deployed virtual machine has to get patched before handed-over to the business, or the template has to get updated every month as well. In the past this update process was addressed by a tool called “Virtual Machine Servicing Tool” (VMST). Unfortunately this wasn’t updated since System Center 2012 and there are no plans to do so – in other words this tool doesn’t exist anymore. This leaves the questions, which options are these days available?

System Center Configuration Manager

Since the 2012 R2 release, Configuration Manager can also manage virtual hard disks (VHDs). Besides creating and modifying a VHD, also applications and software updates can be applied. The VHD then can get published to the System Center Virtual Machine Manager library directly from the Configuration Manager console. The solution is described in this TechNet article in more detail. For those having Configuration Manager in use also for the datacenter, this might be a good option – unfortunately, Configuration Manager is not everywhere used to manage datacenter workloads.

Manual VM Template patching

As an alternative, there is an option to use PowerShell to patch a single VHD:

# Path to VHD(x) VM Template
#$VMTemplate = "\\\MSSCVMMLibrary\VHDs\TP_WS2012R2_disk_1.vhdx"
$VMTemplate = "D:\TP_WS2012R2G2_disk_1.vhdx"
$TempDirectory = "C:\TemplatePatching"
Mount-WindowsImage -ImagePath "$VMTemplate" -Path $TempDirectory -Index 1
# Get all available Updates from WSUS
$WsusServer = ""
$UpdatelistCab = Get-ChildItem -Path "\\$WsusServer\WsusContent" -Include *.cab -Recurse -File   
$UpdatelistMsu = Get-ChildItem -Path "\\$WsusServer\WsusContent" -Include *.msu –Recurse -File   
Foreach ($UpdateCab in $UpdatelistCab)
{$UpdateReady = Get-WindowsPackage -PackagePath $UpdateCab -Path $TempDirectory    
If ($UpdateReady.PackageState -eq "installed")
	{Write-Output $UpdateReady.PackageName "is already installed"}
Elseif ($UpdateReady.Applicable -eq "true")
	{Add-WindowsPackage -PackagePath $Updatecab.Directory -Path $TempDirectory}}   
ForEach ($UpdateMsu in $UpdatelistMsu)    
	{Add-WindowsPackage -PackagePath $UpdateMsu.Directory -Path $TempDirectory}   
# Dismount the VHD / VHDX
Dismount-WindowsImage -Path $TempDirectory -Save 
#DisMount-WindowsImage -Path $TempDirectory -Discard

Automated VM Template patching using SMA – the real solution

A very powerful solution based on Service Management Automation (SMA) has been described by Microsoft colleague Thomas Roettinger sometimes ago. In his article he describes a method how an entire VMM Library share can get patched automatically on a monthly basis for example.

As the article is available on the Building Cloud Blog there is no need to re-post the PowerShell script. Btw. in case you receive the error message “Get-WindowsPackage: The system cannot find the file specified” this isn’t a problem at all, it just means that the update is not applicable to the operating system used for this virtual machine template.

Cloud Platform , Patches , SCVMM , SMA , System Center

, , , ,

About the Author

Michel Luescher is a solution architect in the worldwide Datacenter & Cloud Infrastructure Center of Excellence (CoE) at Microsoft Corporation based out of Zurich, Switzerland. Primarily, Michel is focused on hybrid cloud solutions (Hyper-V, System Center and Microsoft Azure). In addition Michel is speaker, blogger and author of several books.

Comments (8)

  • Jeremy says:

    Hi Michel,

    I just found this post and am attempting to use it, but have into a problem. For every package that (I think) should be applied, I get the following error:

    WARNING: Failed to add package \\\WsusContentF\
    WARNING: The system cannot find the file specified.

    Any ideas?

  • Pep says:


    The original code has a BUG when it performs package checking when it runs this:

    $UpdateReady = Get-WindowsPackage -PackagePath $UpdateCab -Path $TempDirectory

    Some times get-windowspackage is unable to return any value because “cab” is not available, but $updateReady is not cleared and contains a previous loaded value that is not useful for Add-WindowsPackage.
    To avoid add-Windowspackage errors i’m clearing the $updateReady value before perform the Get, the code is like this:

    $UpdateReady=get-windowspackage -PackagePath $Updatecab -Path $TempDirectory

    Since I’m using this technique i don’t have problems with ADD-Windowspackage with this script


  • Ilkin says:

    Thanks for the script. My WSUS is integrated with SCCM and there is only 1 *.cab file in \WsusContent folder.

    • Ilkin says:

      They all appeared in \\MySCCM\SCCM_UPDATES\DeployementPacks\Win2k12_R2 folder as soon as I downloaded them.

  • mike says:

    If the updating is done through SCC where are exactly located the deployment packs?

  • mike says:

    If the updating is done through SCCM where are exactly located the deployment packs?

  • Michael says:

    Ilkin, what’s the location of the SCCM_Updates\DeploymentPacs?

  • Brian says:


    Nice script, but I have found an issue.

    Allthough you wrote “Get-WindowsPackage: The system cannot find the file specified” is normal I have a problem since I have nearly 8.000 updates in my WSUScontent folder that it is trying to match up against my mounted image. So it will take ages before it is ready to continue the script.
    Is there no way to tell it only to look for Server 2016 updates?


Leave a Reply.

Mounting VHD Error Message “Sorry, there was a problem mounting the file” Windows Azure Pack and it’s licensing