Quantcast
Channel: Aaron Czechowski, MCS
Viewing all 16 articles
Browse latest View live

Scripts for WSUS Import/Export

$
0
0

The WSUS Deployment Guide has good general guidance on how to export/import content and metadata to a disconnected network.  Here are some quick scripts that I whipped up to ease the process, as it's something that you'll probably want to do regularly.

WsusContentBackup.cmd

WsusContent.bks is required.  As is right now it will backup C:\WSUS\WsusContent to C:\WsusExport\WsusContent[date]_[time].bkf.  It will create a summary log at %userprofile%\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\data.  If the initial backup creates a BKF that is too large to fit on a DVD, then you'll need to use another method to transfer the data (xcopy, robocopy, oscdimg, etc.).  However I'd recommend still running the backup the first time as it will clear the archive bit on the files so that the subsequent time this script is run, only the new content will be captured, thus the BKF will be significantly smaller.

@echo off
set datecode=%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set outdir=c:\WsusExport
set bksfile=%outdir%\wsuscontent.bks
set bkffile=%outdir%\WsusContent%datecode%.bkf

ntbackup backup @%bksfile% /j WsusContent /f %bkffile% /v:yes /l:s /m incremental

WsusContent.bks

C:\WSUS\WsusContent\

WsusMetadataExport.cmd

Just an automated way to run the export with a unique CAB and LOG file each time.  Both files, along with the above BKF need to be transfered.

@echo off

set datecode=%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set outdir=c:\WsusExport
set cabfile=%outdir%\WsusMetadata%datecode%.cab
set logfile=%outdir%\WsusMetadata%datecode%.log

"C:\Program Files\Update Services\Tools\wsusutil.exe" export %cabfile% %logfile%

WsusMetadataImport.cmd

Import the content before running this script.  NTBackup cannot be automated to restore data so it must be done manually.  Make sure to select the Alternate Location option and point to the correct WsusContent folder (to ensure the subfolder structure is maintained).  This script requires you to give it the [date]_[time] code for the metadata you want to import. 

@echo off
set indir=C:\WSUSImport
set cabfile=%indir%\WsusMetadata%1.cab
set logfile=%indir%\WsusMetadata%1.log

if exist %cabfile% (
        if exist %logfile% (                "C:\Program Files\Update Services\Tools\wsusutil.exe" import "%cabfile%" "%logfile%"        ) ELSE echo. && echo    ERROR: %logfile% does not exist
) ELSE echo. && echo    ERROR: %cabfile% does not exist

A few other notes:

  • Make sure the update files and language options are identical on both the export and import servers.
  • wsusutil shuts down the Update Service when it runs.
  • After the import completes wait several hours for the content and metadata to fully validate.
  • Close the Update Services console before running the export or import.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.


ConfigMgr Software Updates on an Isolated Network

$
0
0

The Windows Server Update Services (WSUS) 3 Deployment Guide documents a process by which update metadata and update content can be transferred from one server to another isolated server.  Since Configuration Manager 2007 relies upon WSUS for the software update plumbing, a similar process can be used to transfer updates to an isolated network for ConfigMgr.

First, some definitions:

  • Isolated network: no Internet connectivity.  There is a physical or logical "air gap" between the isolated network and a network that has access to the Internet.  This is common in high-security or test lab environments.
  • Update metadata: the details of the updates (KB, Severity, Supercedence, etc.) that is stored in a SQL database.
  • Update content: the bits (.exe, .cab, .msu) that clients run to install the update.  These are stored by WSUS in a folder called WsusContent.  The files are named by their SHA1 hash and then stored in subfolders corresponding to the last two characters of the hash.  E.g., KB935840 (MS07-31) Security Update for Windows Server 2003/Windows XP x64 is a 901 KB executable file from 1 June 2007 that is saved on the WSUS server at D:\WSUS\WsusContent\00\8D0F195FC2024DAC3EF2A19289F3932789C2FF00.exe.

The following is a brief overview of the entire process:

  • DEV-WSUS-01 is an Internet-connected server running WSUS 3 that synchronizes the update metadata and downloads the update content from Microsoft Updates.
  • The update metadata is exported and the recently downloaded update content is copied to a staging area, where it can then be copied to removeable media for transfer across the air gap.
  • PROD-WSUS-01 is an isolated server running WSUS 3 and specified as the ConfigMgr active Software Update Point (SUP).
  • The update content is copied from the removeable media to PROD-WSUS-01 and the update metadata is imported into the WSUS database.
  • PROD-SCCM-01 is an isolated server running ConfigMgr 2007.  The update metadata is synchronized from the WSUS database to the ConfigMgr Update Repository.
  • ConfigMgr clients scan against the available software update metadata and report any required updates.
  • An update list is created of any required updates.
  • An update package is created from the update list, pulling update content from \\PROD-WSUS-01\WsusContent.
  • An update management is created from the update list to deploy the updates in the update package to the specified collection.
  • The rest of the process is then the same for any typical ConfigMgr software update deployment.

Now let's look at the details of this process.

I've provided a script, InstallWsus.cmd, that handles the prerequisites (IIS, .NET 2, Report Viewer 2005) for Windows Server 2003 x86 platform, and then, given the name of the SQL server and instance, silently installs WSUS.  Using this script ensures that WSUS is installed the same on the two servers (Internet-connected and isolated networks).  It does assume SQL is installed already (local or remote).

When configuring the Internet-connected server, the following settings are important:

  • Synchronize from Microsoft Update: ConfigMgr must get its updates from Microsoft Updates, not via an upstream server.
  • Products/Classifications: after the first synchronization (which will update the list of those currently available), customize these as required by the isolated environment.
  • Store update files locally on this server: we want to use WSUS to download the bits.  Ensure the option Download update files to this server only when updates are approved is checked (enabled).  Also ensure the option Download express installation files is unchecked (disabled) as this feature is incompatible with ConfigMgr Software Update Management.
  • Languages: configure the languages are required by the isolated environment.  This setting must be identical between the Internet-connected and isolated WSUS servers.
  • Default Automatic Approval Rule: enable and alter the default rule to approve updates for all computers when an update is in any classification.  This will cause the WSUS server to automatically download the update content after synchronization.

I hope it's obvious but I'll mention that DEV-WSUS-01 needs enough disk space to store the update content for the selected products, classifications and languages.  This can quickly grow to hundreds of gigabytes depending upon the how many options are selected.

It's also important to note that this WSUS server is not intended to support any clients, its sole purpose in life is to suck down content for transfer to the isolated network.  I don't recommend the automatic approval setting on a WSUS server supporting production systems, it's used here to automate the download of update content.  Also keep in mind the timing of the synchronizations, as it will start downloading content right away, which will affect your Internet bandwidth.

The following is a rough summary of the process that can be used each month (or on whatever desired interval) to synchronize the update metadata, download the update content and export both for transfer.

  • Synchronize the WSUS server with Microsoft Updates.  With the above settings it will then automatically download the update content.
  • Manually approve all updates that do not automatically approve due to EULA requirements.  In the Update Services console, you can display all Unapproved updates, select all and then Approve them.
  • Monitor the update content download in the Update Services console (the server home page shows the status).
  • I've provided a PowerShell script, SpanWsusContent.ps1, that scans the WsusContent folder for files with the archive bit set, copies them in 4 GB chunks to a given path, and then clears the archive bit.  The outcome is a series of "Disk#" folders that are about 4GB in size which can be easily burned to DVD for transfer.  By using the archive bit on the files, the next time update content is downloaded from Microsoft Updates, this script will only copy the new content, which will result in a significantly smaller quantity of data to transfer.  The first transfer will be the full content, but each subsequent transfer will only be the deltas.
  • I've provided a simple batch script, WsusMetadataExport.cmd, to run the WsusUtil tool to export the update metadata from the WSUS database.  I use the script for consistency, especially with export file names (to avoid confusion each month).  (NOTE: There's probably a better way to script this, especially with the kludgy datetime stamp, but I'll save that for another rainy day.)
  • Copy the exported update metadata CAB file in with the update content so that it can be easily copied to removeable media (I shoot for the last Disk# folder which typically has available space).
  • I then recommend copying this content to a staging area, but some might see this as an extra, unnecessary step.
  • Now the exported update metadata and delta update content is ready to be transferred across the air gap using whatever process you have defined.

I also recommend a quick spot check by noting the Size (in bytes) and number of Files in the entire WsusContent directory.  This can be used as a quick check that the content is the same between WSUS servers.

The isolated WSUS server should be installed using the same InstallWsus.cmd script (or similar) for consistency. The rough summary of the process on the isolated WSUS server is as follows:

  • I also recommend using a staging area on the isolated network, but again it may be unnecessary in your environment.
  • Copy the update metadata CAB file to PROD-WSUS-01 for import into the WSUS database.
  • Copy the update content to the WSUS server (merging with the existing content).  I use the following command for this task:
    robocopy \\PROD-SERVER-02\WsusStaging\<YYYYMMDD>\Disk#\WSUS\WsusContent \\PROD-WSUS-01\WsusContent /e
  • Now is a good time to verify the Size and number of Files in the WsusContent against what is on the Internet-connected server.
  • I have a similar batch script, WsusMetadataImport.cmd, to run WsusUtil to import the update metadata CAB file.
  • Wait; it can take several hours for the server to import the metadata and (more importantly) validate the new content.

The WSUS server should be configured in ConfigMgr as the active Software Update Point (SUP) role.  ConfigMgr takes control of the WSUS service; configuration via the Update Services console is unnecessary.  The following settings on the SUP need to be configured:

  • Select the option Do not synchronize... which supports the import method in use.
  • By selecting this option you will be unable to configure Classifications and Products.  This is expected and ok.
  • Configure the Languages identically as on the Internet-connected WSUS server.
  • No additional settings are necessary, and no configuration is required in the Update Services console; let ConfigMgr configure the SUP (WSUS) server.

The following is the rough process to use the updates in ConfigMgr:

  • Right-click the Update Repository and Run Synchronization to synchronize the update metadata from the WSUS database to the ConfigMgr database.  Open D:\Program Files\Microsoft Configuration Manager\Logs\wsyncmgr.log in Trace32 to monitor the progress.
  • Once all systems have scanned against the new update metadata and reported status, create an Update List based upon the Required updates.  When creating the update list, do not check Download the files associated with the selected software updates.
  • Right-click the Update List and select Download Software Updates to create the Update Package.  A few screens into the wizard, select Download software update from a location on the local network and enter \\PROD-WSUS-01\WsusContent as the path.  If you've done everything correctly, ConfigMgr will automagically find the imported content and provision it into your Update Package at the package source you provided earlier in the wizard.
    • This is a crucial step where the rubber meets the road.  If you get errors it could be for a variety of reasons: the content was transferred incorrectly or improperly, the update content is invalid or corrupt, etc.  Also check out KB938759 for an update to Windows Server 2003 for handling large, signed files (e.g., service pack updates).
  • Finally, right-click the Update List and select Deploy Software Updates and proceed through the DSUW.  Assuming your update package is ok, the rest of the process is per normal.  If you're prompted to download update content, that means that your Update Package doesn't have the content for all of the updates included in the Update List that you're trying to deploy.

I included a PDF diagram that depicts the data flows for both the update metadata and the update content as a way to visual the above process.

The attached archive includes all of the scripts and diagrams referenced in this post.

I'm always looking for ways to streamline and improve this so please let me know if you have any suggestions, comments or additions.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Check-WsusContentHash.ps1

$
0
0

I wrote the attached script to recursively parse a WsusContent directory and compare the file name to the SHA1 hash of the file.  This performs a basic verification that the content is valid.  WSUS does this by itself, but when moving the content across to a disconnected network I recommend validating the content first to ensure it didn't become corrupt in transit instead of waiting on WSUS to check it for you.

The syntax of the script is quite simple:

.\Check-WsusContentHash.ps1 -RootPath D:\WSUS\WsusContent

The RootPath parameter is required so that it knows where to start the search.

The output is basic: a single period (.) for every file it checks.  In the following example I copied six files into a temporary directory for a test scan:

PS C:\Scripts> .\Check-WsusContentHash.ps1 -RootPath C:\WSUS\Temp
......

PS C:\Scripts> 

Any time it encounters an invalid signature it still writes the period, but then displays the file and signature on a new line, and then continues with the scan.  In the following example I changed the last character of one file name from E to 1, causing the script to find it invalid.  (Typically if the file is corrupt, the signature will be significantly different, not just by one character.)

PS C:\Scripts> .\Check-WsusContentHash.ps1 -RootPath C:\WSUS\Temp
.
 C:\WSUS\Temp\22594247fdbd160a334015ec44ce69661231e081.exe      INVALID 22594247FDBD160A334015EC44CE69661231E08E
.....

PS C:\Scripts>

Happy hashing!

 

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Scripts for WSUS Import/Export

$
0
0

The WSUS Deployment Guide has good general guidance on how to export/import content and metadata to a disconnected network.  Here are some quick scripts that I whipped up to ease the process, as it's something that you'll probably want to do regularly.

WsusContentBackup.cmd

WsusContent.bks is required.  As is right now it will backup C:\WSUS\WsusContent to C:\WsusExport\WsusContent[date]_[time].bkf.  It will create a summary log at %userprofile%\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\data.  If the initial backup creates a BKF that is too large to fit on a DVD, then you'll need to use another method to transfer the data (xcopy, robocopy, oscdimg, etc.).  However I'd recommend still running the backup the first time as it will clear the archive bit on the files so that the subsequent time this script is run, only the new content will be captured, thus the BKF will be significantly smaller.

@echo off
set datecode=%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set outdir=c:\WsusExport
set bksfile=%outdir%\wsuscontent.bks
set bkffile=%outdir%\WsusContent%datecode%.bkf

ntbackup backup @%bksfile% /j WsusContent /f %bkffile% /v:yes /l:s /m incremental

WsusContent.bks

C:\WSUS\WsusContent\

WsusMetadataExport.cmd

Just an automated way to run the export with a unique CAB and LOG file each time.  Both files, along with the above BKF need to be transfered.

@echo off

set datecode=%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set outdir=c:\WsusExport
set cabfile=%outdir%\WsusMetadata%datecode%.cab
set logfile=%outdir%\WsusMetadata%datecode%.log

"C:\Program Files\Update Services\Tools\wsusutil.exe" export %cabfile% %logfile%

WsusMetadataImport.cmd

Import the content before running this script.  NTBackup cannot be automated to restore data so it must be done manually.  Make sure to select the Alternate Location option and point to the correct WsusContent folder (to ensure the subfolder structure is maintained).  This script requires you to give it the [date]_[time] code for the metadata you want to import. 

@echo off
set indir=C:\WSUSImport
set cabfile=%indir%\WsusMetadata%1.cab
set logfile=%indir%\WsusMetadata%1.log

if exist %cabfile% (
        if exist %logfile% (                "C:\Program Files\Update Services\Tools\wsusutil.exe" import "%cabfile%" "%logfile%"        ) ELSE echo. && echo    ERROR: %logfile% does not exist
) ELSE echo. && echo    ERROR: %cabfile% does not exist

A few other notes:

  • Make sure the update files and language options are identical on both the export and import servers.
  • wsusutil shuts down the Update Service when it runs.
  • After the import completes wait several hours for the content and metadata to fully validate.
  • Close the Update Services console before running the export or import.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

ConfigMgr Software Updates on an Isolated Network

$
0
0

The Windows Server Update Services (WSUS) 3 Deployment Guide documents a process by which update metadata and update content can be transferred from one server to another isolated server.  Since Configuration Manager 2007 relies upon WSUS for the software update plumbing, a similar process can be used to transfer updates to an isolated network for ConfigMgr.

First, some definitions:

  • Isolated network: no Internet connectivity.  There is a physical or logical "air gap" between the isolated network and a network that has access to the Internet.  This is common in high-security or test lab environments.
  • Update metadata: the details of the updates (KB, Severity, Supercedence, etc.) that is stored in a SQL database.
  • Update content: the bits (.exe, .cab, .msu) that clients run to install the update.  These are stored by WSUS in a folder called WsusContent.  The files are named by their SHA1 hash and then stored in subfolders corresponding to the last two characters of the hash.  E.g., KB935840 (MS07-31) Security Update for Windows Server 2003/Windows XP x64 is a 901 KB executable file from 1 June 2007 that is saved on the WSUS server at D:\WSUS\WsusContent\00\8D0F195FC2024DAC3EF2A19289F3932789C2FF00.exe.

The following is a brief overview of the entire process:

  • DEV-WSUS-01 is an Internet-connected server running WSUS 3 that synchronizes the update metadata and downloads the update content from Microsoft Updates.
  • The update metadata is exported and the recently downloaded update content is copied to a staging area, where it can then be copied to removeable media for transfer across the air gap.
  • PROD-WSUS-01 is an isolated server running WSUS 3 and specified as the ConfigMgr active Software Update Point (SUP).
  • The update content is copied from the removeable media to PROD-WSUS-01 and the update metadata is imported into the WSUS database.
  • PROD-SCCM-01 is an isolated server running ConfigMgr 2007.  The update metadata is synchronized from the WSUS database to the ConfigMgr Update Repository.
  • ConfigMgr clients scan against the available software update metadata and report any required updates.
  • An update list is created of any required updates.
  • An update package is created from the update list, pulling update content from \\PROD-WSUS-01\WsusContent.
  • An update management is created from the update list to deploy the updates in the update package to the specified collection.
  • The rest of the process is then the same for any typical ConfigMgr software update deployment.

Now let's look at the details of this process.

I've provided a script, InstallWsus.cmd, that handles the prerequisites (IIS, .NET 2, Report Viewer 2005) for Windows Server 2003 x86 platform, and then, given the name of the SQL server and instance, silently installs WSUS.  Using this script ensures that WSUS is installed the same on the two servers (Internet-connected and isolated networks).  It does assume SQL is installed already (local or remote).

When configuring the Internet-connected server, the following settings are important:

  • Synchronize from Microsoft Update: ConfigMgr must get its updates from Microsoft Updates, not via an upstream server.
  • Products/Classifications: after the first synchronization (which will update the list of those currently available), customize these as required by the isolated environment.
  • Store update files locally on this server: we want to use WSUS to download the bits.  Ensure the option Download update files to this server only when updates are approved is checked (enabled).  Also ensure the option Download express installation files is unchecked (disabled) as this feature is incompatible with ConfigMgr Software Update Management.
  • Languages: configure the languages are required by the isolated environment.  This setting must be identical between the Internet-connected and isolated WSUS servers.
  • Default Automatic Approval Rule: enable and alter the default rule to approve updates for all computers when an update is in any classification.  This will cause the WSUS server to automatically download the update content after synchronization.

I hope it's obvious but I'll mention that DEV-WSUS-01 needs enough disk space to store the update content for the selected products, classifications and languages.  This can quickly grow to hundreds of gigabytes depending upon the how many options are selected.

It's also important to note that this WSUS server is not intended to support any clients, its sole purpose in life is to suck down content for transfer to the isolated network.  I don't recommend the automatic approval setting on a WSUS server supporting production systems, it's used here to automate the download of update content.  Also keep in mind the timing of the synchronizations, as it will start downloading content right away, which will affect your Internet bandwidth.

The following is a rough summary of the process that can be used each month (or on whatever desired interval) to synchronize the update metadata, download the update content and export both for transfer.

  • Synchronize the WSUS server with Microsoft Updates.  With the above settings it will then automatically download the update content.
  • Manually approve all updates that do not automatically approve due to EULA requirements.  In the Update Services console, you can display all Unapproved updates, select all and then Approve them.
  • Monitor the update content download in the Update Services console (the server home page shows the status).
  • I've provided a PowerShell script, SpanWsusContent.ps1, that scans the WsusContent folder for files with the archive bit set, copies them in 4 GB chunks to a given path, and then clears the archive bit.  The outcome is a series of "Disk#" folders that are about 4GB in size which can be easily burned to DVD for transfer.  By using the archive bit on the files, the next time update content is downloaded from Microsoft Updates, this script will only copy the new content, which will result in a significantly smaller quantity of data to transfer.  The first transfer will be the full content, but each subsequent transfer will only be the deltas.
  • I've provided a simple batch script, WsusMetadataExport.cmd, to run the WsusUtil tool to export the update metadata from the WSUS database.  I use the script for consistency, especially with export file names (to avoid confusion each month).  (NOTE: There's probably a better way to script this, especially with the kludgy datetime stamp, but I'll save that for another rainy day.)
  • Copy the exported update metadata CAB file in with the update content so that it can be easily copied to removeable media (I shoot for the last Disk# folder which typically has available space).
  • I then recommend copying this content to a staging area, but some might see this as an extra, unnecessary step.
  • Now the exported update metadata and delta update content is ready to be transferred across the air gap using whatever process you have defined.

I also recommend a quick spot check by noting the Size (in bytes) and number of Files in the entire WsusContent directory.  This can be used as a quick check that the content is the same between WSUS servers.

The isolated WSUS server should be installed using the same InstallWsus.cmd script (or similar) for consistency. The rough summary of the process on the isolated WSUS server is as follows:

  • I also recommend using a staging area on the isolated network, but again it may be unnecessary in your environment.
  • Copy the update metadata CAB file to PROD-WSUS-01 for import into the WSUS database.
  • Copy the update content to the WSUS server (merging with the existing content).  I use the following command for this task:
    robocopy \\PROD-SERVER-02\WsusStaging\<YYYYMMDD>\Disk#\WSUS\WsusContent \\PROD-WSUS-01\WsusContent /e
  • Now is a good time to verify the Size and number of Files in the WsusContent against what is on the Internet-connected server.
  • I have a similar batch script, WsusMetadataImport.cmd, to run WsusUtil to import the update metadata CAB file.
  • Wait; it can take several hours for the server to import the metadata and (more importantly) validate the new content.

The WSUS server should be configured in ConfigMgr as the active Software Update Point (SUP) role.  ConfigMgr takes control of the WSUS service; configuration via the Update Services console is unnecessary.  The following settings on the SUP need to be configured:

  • Select the option Do not synchronize... which supports the import method in use.
  • By selecting this option you will be unable to configure Classifications and Products.  This is expected and ok.
  • Configure the Languages identically as on the Internet-connected WSUS server.
  • No additional settings are necessary, and no configuration is required in the Update Services console; let ConfigMgr configure the SUP (WSUS) server.

The following is the rough process to use the updates in ConfigMgr:

  • Right-click the Update Repository and Run Synchronization to synchronize the update metadata from the WSUS database to the ConfigMgr database.  Open D:\Program Files\Microsoft Configuration Manager\Logs\wsyncmgr.log in Trace32 to monitor the progress.
  • Once all systems have scanned against the new update metadata and reported status, create an Update List based upon the Required updates.  When creating the update list, do not check Download the files associated with the selected software updates.
  • Right-click the Update List and select Download Software Updates to create the Update Package.  A few screens into the wizard, select Download software update from a location on the local network and enter \\PROD-WSUS-01\WsusContent as the path.  If you've done everything correctly, ConfigMgr will automagically find the imported content and provision it into your Update Package at the package source you provided earlier in the wizard.
    • This is a crucial step where the rubber meets the road.  If you get errors it could be for a variety of reasons: the content was transferred incorrectly or improperly, the update content is invalid or corrupt, etc.  Also check out KB938759 for an update to Windows Server 2003 for handling large, signed files (e.g., service pack updates).
  • Finally, right-click the Update List and select Deploy Software Updates and proceed through the DSUW.  Assuming your update package is ok, the rest of the process is per normal.  If you're prompted to download update content, that means that your Update Package doesn't have the content for all of the updates included in the Update List that you're trying to deploy.

I included a PDF diagram that depicts the data flows for both the update metadata and the update content as a way to visual the above process.

The attached archive includes all of the scripts and diagrams referenced in this post.

I'm always looking for ways to streamline and improve this so please let me know if you have any suggestions, comments or additions.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Check-WsusContentHash.ps1

$
0
0

I wrote the attached script to recursively parse a WsusContent directory and compare the file name to the SHA1 hash of the file.  This performs a basic verification that the content is valid.  WSUS does this by itself, but when moving the content across to a disconnected network I recommend validating the content first to ensure it didn't become corrupt in transit instead of waiting on WSUS to check it for you.

The syntax of the script is quite simple:

.\Check-WsusContentHash.ps1 -RootPath D:\WSUS\WsusContent

The RootPath parameter is required so that it knows where to start the search.

The output is basic: a single period (.) for every file it checks.  In the following example I copied six files into a temporary directory for a test scan:

PS C:\Scripts> .\Check-WsusContentHash.ps1 -RootPath C:\WSUS\Temp
......

PS C:\Scripts> 

Any time it encounters an invalid signature it still writes the period, but then displays the file and signature on a new line, and then continues with the scan.  In the following example I changed the last character of one file name from E to 1, causing the script to find it invalid.  (Typically if the file is corrupt, the signature will be significantly different, not just by one character.)

PS C:\Scripts> .\Check-WsusContentHash.ps1 -RootPath C:\WSUS\Temp
.
 C:\WSUS\Temp\22594247fdbd160a334015ec44ce69661231e081.exe      INVALID 22594247FDBD160A334015EC44CE69661231E08E
.....

PS C:\Scripts>

Happy hashing!

 

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

ConfigMgr query for blocked or approved clients

$
0
0

This is nothing new; I’m typically not one to repost information that can be found elsewhere online.  This is just so that I have an easy place to find it in the future!

select SMS_R_SYSTEM.ResourceID, SMS_R_SYSTEM.ResourceType, SMS_R_SYSTEM.Name, SMS_R_SYSTEM.SMSUniqueIdentifier, SMS_R_SYSTEM.ResourceDomainORWorkgroup, SMS_R_SYSTEM.Client
from SMS_R_System
inner join SMS_CM_RES_COLL_SMS00001
on SMS_CM_RES_COLL_SMS00001.ResourceId = SMS_R_System.ResourceId
where SMS_CM_RES_COLL_SMS00001.IsBlocked = ‘1’

Replace IsBlocked with IsApproved to query for approved clients.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Windows XP Remote Assistance and DontDisplayLastUserName

$
0
0

While implementing Remote Assistance during a Windows 7 deployment I found that a RA connection to older Windows XP workstations would behave like a Remote Desktop connection: the user would not be prompted to allow the administrator to connect, and the administrator would be prompted to logon.  I eventually traced the issue to the presence of the DontDisplayLastUserName value, set to 1, at HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon.  These specific Windows XP workstations were upgraded from earlier versions of Windows, persisting this setting which is deprecated in Windows XP, but causing this problem with Remote Assistance.  I applied a custom administrative template to modify this older registry value and RA started to work as expected.

The necessary functionality historically provided by this registry value is applied by enabling the group policy setting “Interactive logon: Do not display last user name” at Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options.  This policy setting configures the DontDisplayLastUserName value at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System.  Remote Assistance is not affected by the presence of this setting. 

Microsoft Support article KB306045 has more detail on this issue.


Deploying Windows 7 Language Packs via ConfigMgr

$
0
0

During a Windows 7 64-bit deployment project the customer gave me a requirement to allow users to install a variety of language packs without adding all of them to the baseline image to keep the size down.  They are already using ConfigMgr to advertise applications for user self-service so this seemed the most logical method to provide this capability.

Windows 7 language pack setup, lpksetup, includes parameters to support a managed installation.  I successfully tested the following from the command prompt:

lpksetup.exe /i de-DE /p . /r /s

I advertised a program with this command line, but it quickly failed.  The test system returned an error status message, ID 10003: “An error occurred while preparing to run the program for advertisement….  The operating system reported error 2147942402: The system cannot find the file specified.”

Execmgr.log contained the following:

File C:\Windows\SysWOW64\CCM\Cache\…\lpksetup.exe is not a valid executable file
Invalid executable file lpksetup.exe

I altered the program command line to directly reference the executable at %WinDir%\System32\lpksetup.exe with the same result.

Since ConfigMgr executes from a 32-bit process I launched a 32-bit command prompt (C:\Windows\SysWOW64\cmd.exe) to manually try the lpksetup command line.

C:\Windows\SysWOW64>C:\Windows\System32\lpksetup.exe /?
‘C:\Windows\System32\lpksetup.exe’ is not recognized as an internal or external command, operable program or batch file.

C:\Windows\SysWOW64>dir C:\Windows\System32\lpksetup.exe
Volume in drive C is OSDisk
Volume Serial Number is 1234-5678

Directory of C:\Windows\System32

File Not Found

It turns out that lpksetup.exe on Windows 7 64-bit is a 64-bit-only process so with WOW file redirection in a 32-bit process C:\Windows\System32 redirects to C:\Windows\SysWOW64, which does not contain lpksetup.exe.  So I altered the ConfigMgr program command line to:

%WinDir%\SysNative\lpksetup.exe /i de-DE /p . /r /s

Using the SysNative alias allowed the language pack to be successfully installed on Windows 7 64-bit from a ConfigMgr advertised program.

Disk Cleanup in a MDT Task Sequence

$
0
0

While using MDT to remaster an existing Windows 7 image I added tasks to apply Windows 7 Service Pack 1 and a slew of other updates to the image (so that deployed workstations are up to date out of the gate instead of waiting for updates to come down to each system across the network).  Unfortunately this bloated the end product WIM by almost 2 GB.  I started to look into ways I could cleanup any unnecessary files on the hard drive before capturing the image.  Instead of just hacking away at the disk, deleting temporary files and other caches, I decided to try to integrate the built-in Disk Cleanup utility.

Disk Cleanup, cleanmgr.exe, has command line parameters that are well documented but there is little to nothing on how to automate this, especially in the context of a MDT task sequence.  The typical process is to run cleanmgr.exe /sageset:n (where n is an arbitrary integer) and set the files to delete in the interface.  This then configures a cleanup profile in the registry so that when running cleanmgr.exe /sagerun:n it has a preset configuration to use.

To automate this for the task sequence I made the decision that every cache type (aka handler) is to be deleted in this scenario, including the one most important to me: Service Pack Backup Files.  I wrote the attached MDT-style script that loops through each subkey under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches and sets the StateFlags0042 value to DWORD 2 (in this example, n = 42).  There is an article on MSDN that includes an excellent description of the StateFlags value.  The script then runs cleanmgr.exe /sagerun:42 to do the needful.

I added this cleanup task to the end of the Custom Tasks group of the State Restore phase (for those of you using the Standard Client Task Sequence).  It cleaned almost 3 GB of data from the system, which resulted in the final WIM only growing by 575 MB from the starting custom image (instead of almost 2 GB without the cleanup).

Disclaimer: The information on this site is provided “AS IS” with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

CustomDiskCleanup.zip

How to create a bootable ISO

$
0
0

I know this information exists elsewhere in the world and I really dislike redundant posts.  But I’m always hard-pressed to find this so am posting it here more as a reminder to myself.  If it is of use to anyone else, all the better.

When you update a MDT 2010 Update 1 distribution share that includes the option to create a bootable ISO, the OSCDIMG command (in RunCmd.cmd), as well as a log of the output (PEManager.log), is located at %Temp%\PEManager.####, for example, C:\Users\Aaron\AppData\Local\Temp\PEManager.4336.

RunCmd.cmd contains the following (reformatted for easier readability):

“C:\Program Files\Windows AIK\Tools\AMD64\OSCDIMG.EXE”

-u2
-udfver102
-m
-o
-h
-yo”C:\Program Files\Microsoft Deployment Toolkit\Templates\BootOrder.txt”
-bootdata:2#p0,e,b”C:\Program Files\Windows AIK\Tools\PETools\amd64\boot\ETFSBOOT.COM”#pEF,e,b”C:\Program Files\Windows AIK\Tools\PETools\amd64\boot\EFISYS.BIN”
”C:\Users\Aaron\AppData\Local\Temp\MDTUpdate.4336\ISO”
”C:\Users\Aaron\AppData\Local\Temp\MDTUpdate.4336\LiteTouchPE_x64.iso”
> “C:\Users\Aaron\AppData\Local\Temp\PEManager.4336\PEManager.log” 2>&1

See [some website] for details on the various OSCDIMG parameters.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Using SMBIOS GUID to import computer information for VMware guest

$
0
0

To import computer information into Configuration Manager for OS deployment you have to enter the computer name and then one or both of the following unique identifiers: MAC address or SMBIOS GUID, aka UUID.  Many customers use the MAC address because it is shorter and typically more accessible.  However, if the UUID is required this can seem difficult to obtain especially when the target systems are VMware guests.  When the guest is initially created it is assigned a UUID which is stored in the VMX configuration file as the uuid.bios property.  Here is an example line from the VMX file:

uuid.bios = “42 38 d4 b6 00 90 3e 75-94 06 b3 10 ea fa 2b 1e”

This does not look like a usual SMBIOS GUID in the standard (8)-(4)-(4)-(4)-(12) format.  When the system boots and attempts to PXE boot, the same UUID is visible although formatted differently, for example:

Network boot from Intel E1000
Copyright (C) 2003-2008  VMware, Inc.
Copyright (C) 1997-2000  Intel Corporation

CLIENT MAC ADDR: 00 50 56 B8 00 14  GUID 4238D4B6-0090-3E75-9406-B310EAFA2B1E
CLIENT IP: 192.168.1.100  MASK: 255.255.255.0  DHCP IP: 192.168.1.10
GATEWAY IP: 192.168.1.1

Looking at the actual SMBIOS GUID via the UUID property of the Win32_ComputerSystemProduct WMI class (or the comparable System UUID property on the ConfigMgr System Resource), it appears as:

UUID = “B6D43842-9000-753E-9406-B310EAFA2B1E”

The difference between these two (uuid.bios up above and UUID directly above), which are identical except for formatting, is explained in an older Remote Installation Services article on TechNet.  The VMware VMX uses the “raw byte order” format while Windows and Configuration Manager use the “pretty print” format. (Thanks to Michael Kelley for that nugget of information.)

So taking a UUID from a VMware VMX to import into Configuration Manager for OS deployment requires some conversion.  The attached script does a simple conversion; there may be a more elegant method relying upon the underlying mathematics of the UUID, but that’s beyond my current knowledge.

The script usage is as follows:

.\Convert-UUID.ps1 -rawUUID “<uuid>”

where <uuid> is formatted as follows:

01 23 45 67 89 ab cd ef-fe dc ba 98 76 54 32 10

such as used in the uuid.bios property of a VMX file.  For example, the above rawUUID yields the following output:

67452301-ab89-efcd-fedc-ba9876543210

Disclaimer: The information on this site is provided “AS IS” with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Convert-UUID.zip

Verifying Configuration Manager Backup Task with Windows PowerShell

$
0
0

A seemingly simple requirement for a Desired Configuration Management configuration item is to verify that the Configuration Manager 2007 site backup maintenance task is enabled.  What became the difficult part of this was tracking down the specific location in WMI that this data exists.  I have to give credit to Jamie Moyer for pointing me in the right direction.

Function Get-SccmBackupEnabled {

    # Refresh the site control file
    Invoke-WmiMethod -Path SMS_SiteControlFile -Name RefreshSCF -ArgumentList $sccmSiteCode -Computername $sccmServer -Namespace $sccmNamespace | Out-Null

    # Get the backup task object for this site
    $bkTask = Get-WmiObject -Query "SELECT * FROM SMS_SCI_SQLTask WHERE SiteCode = ‘$sccmSiteCode’ AND ItemName = ‘Backup SMS Site Server’" -Computername $sccmServer -Namespace $sccmNamespace

    If ( -not $bkTask ) { $False }
    ElseIf ( $bkTask.On -eq ‘True’ ) { $True }
    Else { $False }
}

The key here is the SMS_SCI_SQLTask WMI class, not SMS_SCI_MaintenanceTask as I originally suspected.

This cannot be used as-is in DCM; it must be paired with some code to first create the connection to the site server and then call this function.  I use Michael Niehaus’ PowerShell module which works very nicely for many common Configuration Manager automation tasks including the initial connection (New-SCCMConnection).

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

USGCB Policy Bug: Turn off desktop gadgets

$
0
0

The US Government Configuration Baseline (USGCB) group policy object (GPO) for Windows 7 Computer Settings includes the setting:

Computer Configuration\Administrative Templates\Windows Components\Desktop Gadgets
Turn off desktop gadgets = Enabled

This setting is not included in the settings spreadsheet or the associated SCAP content.  It was mistakenly included in the GPO and is expected to be removed in a future release.  If desired, agencies can safely deviate this setting since the SCAP content does not include it.

NOTE: the three other settings in this policy section are still enabled to control the use of Desktop Gadgets.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation.

Using Windows PowerShell to convert collection membership rules

$
0
0

I developed some automation for a customer to help them manage the lifecycle of collections used for assignment of DCM baselines as they are revised.  Part of this required the ability to convert a collection from query-based membership to direct membership rules and vice versa.  I realize this is a very niche piece of automation, but perhaps someone else can gain some benefit from these functions.

I used Michael Niehaus’ Windows PowerShell module for Configuration Manager to provide supporting functions and even derived several of the code blocks from his very handy functions.  SCCM.psm1 is not technically required for these functions, but I assume it was used to create the connection to the site so that variables such as $sccmServer and $sccmNamespace are available.

There are three functions:

  • Add-SCCMCollectionDirectRule: this is a helper function used by both of the following.  It takes two parameters: a collection object and an array of collection members.  (It is a simplification of Michael’s related function.)
  • Convert-SCCMCollectionToDirect: as the name suggests this will take any collection, capture the current membership, remove the rule and then add the members as direct membership rules.  It assumes there is only one query rule and does not refresh the collection membership.
  • Convert-SCCMCollectionToQuery: the converse of the above; it removes all direct membership rules and then adds the given query rule.  It is adapted from Michael’s code with fewer parameters (which could easily be added back for increased functionality).

 

Function Add-SCCMCollectionDirectRule {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection,
        # Array of SMS_CollectionMembers from MemberClassName WMI Class
        [Parameter()] $Members
    )

    # (derived from Add-SCCMCollectionRule in SCCM.psm1 by Michael Niehaus)
    $ruleClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_CollectionRuleDirect"
    ForEach ( $member in $Members ) {
        $newRule = $ruleClass.CreateInstance()
        $newRule.RuleName = $member.Name
        $newRule.ResourceClassName = "SMS_R_System"
        $newRule.ResourceID = $member.ResourceID

        $Collection.AddMembershipRule($newRule) | Out-Null
    }  # end foreach

}  # end Add-SCCMCollectionDirectRule function

Function Convert-SCCMCollectionToDirect {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection
    )

    # Refresh to make sure we have all of the lazy properties
    $Collection.Get()

    # Change the schedule from periodic (2) to manual (1)
    $Collection.RefreshType = 1
    $Collection.Put() | Out-Null

    # Get the collection members
    $collMembers = Get-WmiObject -Class $Collection.MemberClassName -Namespace $sccmNamespace -ComputerName $sccmServer

    # Get the existing query rule, assuming there is only one
    $rule = $Collection.CollectionRules[0]

    # Delete the query rule
    $Collection.DeleteMembershipRule($rule) | Out-Null

    # Add members back as direct membership rules
    Add-SCCMCollectionDirectRule -Collection $Collection -Members $collMembers

}  # end Convert-SCCMCollectionToDirect function

Function Convert-SCCMCollectionToQuery {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection,
        [Parameter()] $QueryName,
        [Parameter()] $Query,
        [Parameter()] [ValidateRange(0, 31)] [int] $RefreshDays
    )

    # Get all lazy properties
    $Collection.Get()

    #Set schedule
    $intervalClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_ST_RecurInterval"
    $interval = $intervalClass.CreateInstance()
    $interval.DaySpan = $refreshDays
    $Collection.RefreshSchedule = $interval
    $Collection.RefreshType = 2    # periodic (2) vs manual (1)
    $Collection.Put() | Out-Null

    # Delete all direct membership rules
    ForEach ( $rule in $Collection.CollectionRules ) {
        $Collection.DeleteMembershipRule($rule) | Out-Null
    }

    # Add query
    Add-SCCMCollectionRule -collectionID $Collection.CollectionID -queryRuleNameb $queryName -queryExpression $query

    # refresh the collection
    $Collection.RequestRefresh() | Out-Null

}  # end Convert-SCCMCollectionToQuery function

 

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.


Moving on

$
0
0

A long overdue post…

In April I changed roles within the company, leaving Microsoft Consulting Services and joining the Windows Intune product team as a program manager.

This blog will remain, but I currently have no plans to make any further posts. I am continually re-evaluating the latter part of that statement….

Viewing all 16 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>