Generate an installation-report for specific hotfixes using Windows PowerShell

Windows PowerShell 2.0 contains a cmdlet called Get-HotFix, which retrieves installed hotfixes from the local computer or specified remote computers.

This is quite useful when you need to check if a particular hotfix is installed prior to installing new software that requires a specific set of hotfixes, or when a critical security hotfix is released and you want to make sure the hotfix is installed.

The Get-HotFix cmdlet retrieves all hotfixes installed by Component-Based Servicing. If you would like to know more about CBS, I would recommend the article Understanding Component-Based Servicing on the Windows Server Performance Teams blog.

When you need to check several computers, and maybe also check for several hotfixes, it might be a time consuming process to run Get-HotFix against each computer and also keep track of the status for each computer/hotfix. To ease this scenario, Ive written a script named Get-HotFixReport.ps1.


Get-HotFixReport.ps1 overview

  • Retrieves the computers to run Get-HotFix against using the Get-ADComputer cmdlet, which is available in Microsofts PowerShell-module for Active Directory
  • Loops through each computer and creates a custom object for every hotfix, containing information about the installation of the current hotfix for the current computer. Any error that occurs is also stored in the custom object. Get-HotFix are only run if the current computer responds to a ping request.
  • Every custom object are added to an array, which at last are exported to a csv-file.

The following three variables must be customized before running the script:

The example above retrieves all computer objects in Active Directory running a Windows Server operating system. You may specify only one computer, or a secific Organizational Unit, if required.

In the HotFix-variable you need to specify one or more hotfixes to check for. If more than one are specified, they must be separated with a comma. The hotfix-variable in the example above contains all hotfixes that are the prerequisites to install Exchange Server 2010 SP1 on Windows Server 2008 R2.

The csv-file may be opened in Microsoft Office Excel where its possible to apply filters to sort on e.g. “true” in the HotfixInstalled-column:



Note that the Get-HotFix cmdlet actually leverages the Win32_QuickFixEngineering WMI-class, and thus, it would be possible to run the script under Windows PowerShell 1.0 if you replace Get-HotFix with Get-WmiObject -Class Win32_QuickFixEngineering.

Of course you might also choose other ways to retrieve the computer-list, e.g. a csv-file, a txt-file or by using Quest`s PowerShell commands for Active Directory.

Export BitLocker-information using Windows PowerShell


Active Directory can be used to store both Windows BitLocker Drive Encryption recovery information and Trusted Platform Module (TPM) owner information.

On the Microsoft Windows Support site, the following information are provided:

Storage of BitLocker Recovery Information in Active Directory

BitLocker recovery information is stored in a child object of a computer object in Active Directory. That is, the computer object is the container for the BitLocker recovery object.

More than one BitLocker recovery object can exist for each computer object, because there can be more than one recovery password associated with a BitLocker-enabled volume.

Each BitLocker recovery object on a BitLocker-enabled volume has a unique name and contains a globally unique identifier (GUID) for the recovery password.

The name of the BitLocker recovery object is limited to 64 characters because of Active Directory constraints. This name incorporates the recovery password GUID as well as date and time information. The form is:

<Object Creation Date and Time><Recovery Password GUID>

For example:


The Active Directory common name (cn) for the BitLocker recovery object is ms-FVE-RecoveryInformation and includes attributes such as ms-FVE-RecoveryPassword and ms-FVE-RecoveryGuid.

Storage of TPM Recovery Information in Active Directory

There is only one TPM owner password per computer; therefore the hash of the TPM owner password is stored as an attribute of the computer object in Active Directory. It is stored in Unicode. The attribute has the common name (cn) of ms-TPM-OwnerInformation.

Active Directory Requirements

In order to store BitLocker and TPM information in Active Directory, all domain controllers must run Windows Server 2003 with Service Pack 1 or later. Schema extensions will also need to be installed on servers running Windows Server 2003.


To see if a computer has stored any BitLocker Recovery information in Active Directory, you must install the BitLocker Recovery Password Viewer and check the BitLocker Recovery tab on the computer object to see if a Recovery Password are present:


Doing this for every computer manually isnt an option in a domain environment. To ease this task Ive written a PowerShell-script, available here, that will generate a CSV-file containing all Windows Vista and Windows 7 computer objects in the domain. The CSV-file will contain the following information:

  • Computername
  • OperatingSystem
  • HasBitlockerRecoveryKey
  • HasTPM-OwnerInformation

I havent found a way to retrieve ms-FVE-RecoveryInformation objects or msTPM-OwnerInformation information on computer objects using Microsofts PowerShell-module for Active Directory. Because of that Ive leveraged Quests free PowerShell Commands for Active Directory.

To retrieve correct information, you must run the script with a user that has been granted the following permission: Read-permission on msFVE-RecoveryInformation objects and Read-permissions on msTPM-OwnerInformation on computer-objects (e.g. Domain Admins).

When the CSV-file is generated, you can use the “Text to columns”-feature in Microsoft Office Excel and save the document as an Excel spreadsheet. Then you can apply filters to sort on e.g. HasBitlockerRecoveryKey or HasTPM-OwnerInformation.

If you`re using the BitLocker feature on other operatingsystems than Windows Vista or Windows 7, i.e. Windows Server 2008 or Windows Server 2008 R2, you may customize the filtering in the computers-variable.


BitLocker resources on Microsoft TechNet

BitLocker Drive Encryption

BitLocker Drive Encryption Overview

Backing Up BitLocker and TPM Recovery Information to Active Directory

Using Cmdlet Extension Agents to customize mailbox provisioning in Exchange Server 2010

Exchange Server 2010 introduced a new feature for automatically assigning a database while provisioning mailboxes, which uses the Mailbox Resources Management cmdlet extension agent. This feature are demonstrated and described in further detail in this blog post by Mike Pfeiffer.

While this new feature is a great enhancement to Exchange Server, its actually possible to customize it further by using another cmdlet extension agent named Scripting Agent.

There are several common ways to distribute mailboxes to databases:

  • Alphabetically
  • Per location
  • Per department
  • Random

My example will focus on using the alphabetically approach to distribute the mailboxes. Ive re-used the regular expression switch I wrote in this blog post.

Before we proceed, you might want to read this blog post by Pat Richard on how the Scripting Agent work, as well as reading up on Cmdlet Extension Agents on the Exchange Server TechCenter on Microsoft TechNet.

1. Create a file named ScriptingAgentConfig.xml and save it to the CmdletExtensionAgents-folder which by default are C:Program FilesMicrosoftExchange ServerV14BinCmdletExtensionAgents. You can find my sample ScriptingAgentConfig.xml here. You will need to customize the names of the databases, as well as the domain name and the Exchange organization name in the $user.database property. Then you would need to copy the ScriptingAgentConfig.xml to the CmdletExtensionAgents-folder on all Exchange 2010 servers in your organization.

2. From the Exchange Management Shell, run Enable-CmdletExtensionAgent “Scripting Agent”. This will enable the Scripting Agent, which will use the ScriptingAgentConfig.xml file we created.

3. From the Exchange Management Shell, run Disable-CmdletExtensionAgent “Mailbox Resources Management Agent”. The Mailbox Resources Management Agent must be disabled when we want to assign the database for the new mailbox using the Scripting Agent, else the Mailbox Resources Management Agent will take precedence. Alternatively we could have changed the priority of the Scripting Agent.

When the above configuration are in place, it`s time to test the new configuration, which of course should be done in a lab environment prior to putting it to production.

From the Exchange Management Console, create a new mailbox and be sure to not select “Specify the mailbox database rather than using a database automatically selected”:


Alternatively, if using the New-Mailbox cmdlet from the Exchange Management Shell, do not specify the “-Database” parameter.

When the test mailbox are created, verify that the database the new mailbox was assigned to is the expected one. For troubleshooting, I would recommend you to use the “–Verbose” parameter on the New-Mailbox cmdlet.

You can use the very same technique to customize database selection based on i.e. the per department approach, by accessing other properties from $provisioningHandler.UserSpecifiedParameters