Disconnected WSUS – The “fun” of importing updates

, , , ,

Air gap networks have their own special challenges…


My name is Charles, I went to the Midwest Management Summit back in May 2019. It was my second time attending the conference. You might remember me as “that guy who has no remote users” 🙂

I said I would blog about a tip I talked about shortly after the conference… This blog post is about 7 months late, I’m sorry!

So for those that do not know this conference, there is a session where anyone can go up on stage and present an IT-related tip or trick.

I went on the stage to talk very briefly about a rather important detail that you need to know when you deal with a disconnected/offline WSUS server: You need to track your update approvals on your internet-connected WSUS server.

On your disconnected WSUS server, you must not approve an update that was not approved on your internet-connected WSUS server or you will have issues.


Microsoft’s official documentation regarding setting up a disconnected WSUS instance can be summarized with the following 3 steps:

  1. Matching advanced configuration:
    • Express updates: If you want to use express updates, make sure that both the internet-connected WSUS and the disconnected WSUS instances have the same setting configured
    • Languages: Make sure that you select the same languages for update files
  2. WsusContent: This one is simple, just copy the “WsusContent” folder on the internet-connected WSUS to the disconnected one.
  3. Metadata: Export & Import the WSUS metadata with wsusutil.exe import/export

The problem

OK, so you made sure that you have the same advanced configuration, you copied the “WsusContent” folder and you imported the metadata from your internet-connected WSUS server… now what?

Well, now you have a bunch of unapproved updates in your WSUS Console on your disconnected WSUS Server. You don’t know which ones were approved or declined on the internet-connected WSUS.

The next part is from my personal experience… If you approve a bunch of updates and some are missing the associated content, WSUS gets stuck. In your WSUS console, it will show that you have thousands of updates “needing files”. What’s happening here is that you approved updates for which your disconnected WSUS does not have the content. In a normal scenario, WSUS would simply download the content from Microsoft. In our case, the WSUS server simply gets stuck there because some updates are missing files. And for some &*%!$% reason, WSUS will not skip over and verify the other updates once it gets stuck with a couple of updates missing content.

This is what happens when you approve updates that your disconnected WSUS does not have the content.

The solution

Make sure that the same approvals are mirrored on your disconnected WSUS instance.

And when I say update approvals, I mean which updates were declined and which updates were approved.

“OK, I will create the same automatic approval rules on my disconnected WSUS. Done.”

Sure, that might work if you don’t do any kind of cleanup on your WSUS instance. There are various solutions online of scripts that people use to decline/delete updates they don’t need (Itanium, Ia64, superseded updates, etc.)

The automatic approval rules criteria in WSUS are very basic and you will end up approving updates on your disconnected WSUS that are declined on your internet-connected. Ask me how I know…

I personally use Bryan Dam’s software update maintenance script, see his blog posts here and here. This script was originally written to maintain SCCM software update point WSUS instances but later he added the WSUS Standalone mode which I’m using for my WSUS Servers.

I won’t go into details here about which updates I’m declining and whatnot. Just know that if you use a WSUS Server, you should probably have some sort of maintenance script running regularly or you will have a bad time…

“How am I supposed to keep track of all the updates that I declined/approved?”


With PowerShell we can get the information we want and it’s possible to script this so that we can export and import the update approvals.

When you’re ready to do an export of your internet-connected WSUS, you will have to export the metadata, copy the “WsusContent” folder and also get the list of which updates were approved. Make sure you copy all three at the same time to make sure that you have the matching metadata, content and update approvals.

My script

So where I work, the team responsible for copying content over to the disconnected WSUS server is different than the team maintaining WSUS. A procedure was written about how to perform the export and import process but it never worked really well and WSUS crapped itself… many times.

I decided that I had enough with this and tried to automate the process as much as I could.

I wrote a script that I called “Invoke-WSUSImportExportManager”

At first, I simply wanted to automate the following:

  • Exporting
    • Copy “WsusContent” to $folder
    • Copy the WSUS Metadata to $folder
    • Record WSUS information in a XML file and copy to $folder
      • WSUS Configuration
      • WSUS Computer groups hierarchy
      • WSUS Update approvals
  • Importing
    • Copy “WsusContent”
    • Import the WSUS Metadata
    • Update WSUS Configuration
      • Match the configuration
      • Re-create the same computer groups hierarchy
      • Approve the same updates to the same computer groups

And then it became bigger and bigger…

On top of doing the import and export process, it also does the following tasks:

  • Reindex the WSUS Database
  • Adds or Removes the custom indexes (Taken from Bryan Dam’s script)
  • Sets a couple of common IIS settings for the WsusPool that should be changed from its default values
  • Show locally published updates (third-party updates) in the WSUS console

All these “Actions” that the script performs are customizable.

The script is available on GitHub here. I tried to explain how the script works in the readme but feel free to ask me any questions if you need more information.

Note: My PowerShell skills are not super awesome so I’m sorry for the state of the scripts. If you have some feedback/suggestions regarding that, please let me know and I’ll try my best to improve the scripts.

Thank you.

Feel free to contact me on Twitter.

Package Software While You Sleep Using the SCCM Application Packager Script

, , , , ,

Don’t you love when Chrome, Firefox and Flash all release critical updates all at the same time? Packaging software that changes frequently was taking a lot of my time, I knew that there must be a better way. I search for solutions, but found nothing that satisfied my needs at the time. In the end, I decided to create my own solution. This solution became a powerful PowerShell script that required nothing but the internet, a console connection and the built-in ConfigurationManager module. The SCCM Application Packager script takes the work out of packaging applications by automating the Download, Packaging, Distribution and Deployment of applications using flexible XML files called “recipes”. The script is open source and available on GitHub for anyone to use! In this post I’ll go over the process of setting up the script so you can package applications while you sleep!


We’ll start with a few prerequisites. You will need at least the following to get started with the scripts:

  • Computer that will do the packaging should have access to the SCCM Primary Site and the internet to download packages
  • SCCM Console installed and it is recommended, but not required, to connect to your site through the console at least once
  • I also recommend opening Internet Explorer once and going through the initial setup. This allows the script to download the applications without running into blocks

After you have confirmed you have the proper setup to run the script, you can begin downloading the script and setting up the preferences for your site.

Download the SCCM Application Packager tool from GitHub

  1. You can download directly from GitHub here: https://github.com/asjimene/SCCM-Application-Packager
  2. Unzip the downloaded file at a location of your choosing, I chose “C:\”.
  3. Navigate to “C:\SCCM-Application-Packager-master” and open the “SCCMPackager.prefs” file.

Setting up the SCCM Application Packager tool

  1. Set the ContentLocationRoot to your SCCM Content Folder. The script will create a folder for each application in this Content Folder.
  2. Set the IconRepo to the location where you store all of your icons if you don’t have an icon folder many are included with the Application Packager tool in the “ExtraFiles\icons” folder.
  3. Set the SCCMSite to your SCCM Site Code (Don’t forget the “:” at the end).
  4. If you would like an email sent at the end of the packaging, you can set the email preferences, otherwise set “SendEmailPrefences” and “NotifyOnDownloadFailure” to False
  5. Set the PreferredDistributionLoc to a Distribution Point Group that you want packages to be distributed by default
  6. Set the PreferredDeployCollection to a collection that you want packages to be deployed to by default

Running the initial setup

This creates an Application and some Global Conditions that the script uses as a template for requirements rules and install behavior

  1. Open a PowerShell Window in the SCCM Application Packager Directory and run the “SCCMPackager.ps1” script. Typing “powershell” in the location bar will automatically open PowerShell in the current directory.
  2. While the script is running, you can follow along by watching the log file, which is located by default at “C:\Temp\SCCMPackager”
  3. When the script has completed it’s first run, the log file will provide instructions on how to proceed. These extra steps allow the script to create applications that use Install Behaviors. Simply open your Configuration Manager Console and add an install behavior to the Application Requirements Template.
  4. Please note that some applications require the 7za executable from the 7-zip project to be packaged. I recommend downloading 7zip-extra from https://www.7-zip.org/download.html and copying the “7za.exe” file from there into the root of your SCCM Application Packager folder before continuing.
  5. You may also want to take advantage of the application icons that have already been specified in the Application Packager. There are application icons included for every recipe provided on the GitHub. Those can be found in the “ExtraFiles\icons” folder. I would recommend copying them to the “IconRepo” specified in step 2.
  6. Initial Setup is now complete! Time to package some Applications!

Packaging Applications

Once the initial setup is complete, packaging applications is as simple as copying or moving some files to a folder and running the script!

  1. Navigate to the SCCM Application Packager Script directory.
  2. Look through the “Disabled” folder and determine what XML files (called “recipes”) you want to package.
  3. Cut or Copy the recipes that you want to package from the “Disabled” folder into the “Recipes” folder.
  4. Run the “SCCMPackager.ps1” script using PowerShell, just as you did during the Initial Setup
  5. Sit back and relax! You can always look at the log file to see how packaging is proceeding. Once packaging is finished, it is always good to test the packaged apps to ensure they deploy and function in the way you expect. The applications the script creates will be fully featured, including icons, descriptions, estimated and max install times, and take advantage of requirements and Install behavior if needed.
    SCCM Application Packager

Automate packaging

Once the script is in good working order, I prefer to have everything happen automatically. My current preferred method of doing so is using the built-in Windows Task Scheduler to run the script weekly at 4 AM on Wednesday mornings. Feel free to adjust the schedule to your specific needs and goals.

  1. Open the Task Scheduler, and navigate to the Task Scheduler Library (I just search for it in the start menu, but you can go through MMC if you are feeling fancy.)
  2. Right click and create a new Basic Task.
  3. General Tab

    1. Name: “SCCM Application Packager” has a nice ring to it
    2. A Description of your choosing
    3. Choose the user account you want to run the script with, here I chose my regular user account, but in my Production environment I have a service account dedicated to the task (just make sure you log in with the service account and ensure it has done the IE setup and can get to the Console)
    4. Choose the “Run whether user is logged on or not” radio button.
    5. Some apps require the application be installed and uninstalled to figure out the version numbers and other information, so you may want to check the box to “Run with highest privileges” if any of your recipes require it.
  4. Triggers Tab

    1. Click “New…”, and choose: Run: “On a schedule”
    2. I chose Weekly at 4 AM on Wednesday.
    3. Stop the task if it runs longer than 2 hours
    4. Click “OK”
  5. Actions Tab

    1. Click “New…”, and choose “Start a program” as your Action
    2. Program/script: powershell.exe
    3. Add arguments: -executionpolicy bypass -file “C:\Path\To\SCCMPackager.ps1”
    4. Click “OK”
  6. Conditions

    1. The only condition I would check on this page may be “Start only if the following network connection is available” Otherwise, leave everything unchecked
  7. Settings

    1. Check “Allow task to be run on demand” (We will use this for testing)
    2. Stop the task if it runs longer than: ” hours”
    3. If the task is already running: “Do not start a new instance”
  8. Once the Scheduled Task is set up click OK, and enter your username and password to save the credentials to run if you aren’t logged in.
  9. Finally, right-click the newly created task and click “Run”, then watch the log file to ensure it is running properly.


That’s it! After everything is set up and you have the scheduled task created, the script will run when scheduled and download, package, distribute, and deploy your applications to your specified collection. All you have to do is test and deploy to production! If you set up the email feature, the script will email you a report of newly packaged applications and if it ran into any errors in the process.

If you think the SCCM Application Packager tool would make your life easier, you can find it at GitHub here: https://github.com/asjimene/SCCM-Application-Packager. I also happily accept pull requests with new features, or for recipes. If you are interested in creating recipes, stick around for Part 2, where I will go over how the script and recipes work!

Thank you for reading this post! I hope this script helps save a lot of time and headaches!


Andrew Jimenez

Twitter: @AndrewJimenez_

Status Message ID 11756

, , , , , , ,

I was working at a customers site where there were some infrequent issues with patching. While I was viewing all status message queries there was a frequent occurrence for status message ID 11756. This particular error points to a GPO Conflict. You can also use the report “Last Scan States By Collection” to validate my findings.

The problem was occurring at an entire office location where all scans were failing. You can see below the majority of the failures are due to group policy conflict.

I have verified there were no problems with the GPO setting the WSUS and determined the local system had issues laying down policy. It’s a meh thing, but you will find this in different environments from time to time. This is an easy fix for my customers by rebuilding the registry.pol located at “C:WindowsSystem32GroupPolicyMachineRegistry.pol”

My quick fix is to create a package with the bat file created from the lines of text. You see I delete the file, force gpupdate, software update scan and machine policy.


DEL /q “C:WindowsSystem32GroupPolicyMachineRegistry.pol”
Echo N | gpupdate /force
WMIC /namespace:\rootccm path sms_client CALL TriggerSchedule “{00000000-0000-0000-0000-000000000113}” /NOINTERACTIVE
WMIC /namespace:\rootccm path sms_client CALL TriggerSchedule “{00000000-0000-0000-0000-000000000022}” /NOINTERACTIVE

You can set up auto-remediation by creating a collection based on any system reporting status message 11756 within 24 hours and deploying the package to rebuild local policy.

Query below for collection:
select distinct SYS.Name,SYS.Client from sms_r_system as SYS join SMS_StatusMessage as stat on stat.machinename = SYS.name where stat.ModuleName = “SMS Client” and stat.MessageID = 11756 and DateDiff(dd,stat.Time, GetDate()) <1

After this runs monitor your log files to verify the software update scan has ran successfully and also run the last software update scan report for additional validation.

Please see this link for TechNet to download the bat file



ALSO SEE : Windows 10 Migration Project (General UEFI Queries)