Working with Active Directory Certificate Services from Windows PowerShell

In Active Directory Certificate Services, the primary administration interface is the MMC snap-in Certification Authority exposed through Server Manager in Windows Server 2008 and Windows Server 2008 R2:


More advanced administration options is available through the command line utility certutil.exe.

I recently worked with an environment with an unusual amount of issued certificates (several hundreds of thousands), and working with the MMC-tools was not efficient.

I first started by exporting the issued certificates to a CSV-file by using certutil.exes csv option. This options seems to be new in Windows Server 2008 R2, although I havent found any documentation on this. Actually it`s possible to use certutil.exe from a Windows Server 2008 R2 member server against a Certification Authority running an earlier version of Windows Server to export issued certificates to CSV. It should also be noted that this can be accomplished using the Export List option in the Certification Authority MMC in both Windows Server 2008 R2 and earlier versions of Windows Server.

When the CSV-file are exported, we can import it to Windows PowerShell and do things like grouping and sorting:

#Export certificates to CSV
certutil -view -out "RequestID,RequesterName,RequestType,NotAfter,CommonName,Certificate Template" csv > c:tempcerts.csv

#Import CSV
$csv = Import-Csv C:Tempcerts.csv

#Group by requester name, and sort by count
$csv | Select-Object "requester name" | Group-Object -Property "requester name" | Sort-Object -Property count

#Work further with a specific computer based on the above results
$computer = $csv | Where-Object {$_."requester name" -eq "computer01"}


Note that using CSV when working with very large data sets might consume large amounts of system resources (up to 2,5 GB in my case), so this might not be the best approach. Another option would be to work directly against the Certification Authority database, where we can set filters directly on the queries.

There are several Com-objects available for working with Active Directory Certificate Services, which makes it possible to work directly against the Certification Authority database from PowerShell.

PowerShell MVP Vadim Podans has written a blog-post showing how this can be accomplished.

Another Com-object to look into is the ICertAdmin2 Interface, which can be accessed from PowerShell like this:

012 013
#Create Com-object
$certadmin = new-object -com "CertificateAuthority.Admin.1"

#Explore Com-object
$certadmin | Get-Member

#Sample usage for one of the available methods
"lab-dc-01Issuing CA 01", #Config-string
 0x0, #Flags, not set
 0x0, #Date, not set when using RowID
 0x0, #Table, set to 3 for CVRC_TABLE_REQCERT
 21 #RowId

DFS-R Health Report for SYSVOL

Distributed File System Replication (DFS-R) was introduced as a replacement for File Replication Service (FRS) in Windows Server 2008, and was further enhanced in Windows Server 2008 R2. When your domain functional level are set to Windows Server 2008, you have the option to migrate SYSVOL-replication from the deprecated FRS to the new and more reliable DFS-R service. A major advantage of using DFS-R over FRS is that FRS copies the whole file when a change are made, while DFS-R only copies the changed bits. This and further details are discussed here. Ive also included some links in the resource section below on how to perform an FRS to DFS-R migration.

Included in the Windows Server 2008 and Windows Server 2008 R2 are the DFS Management-console as well as several command-line tools for administering DFS. A great built-in feature in these tools is the diagnostic reports.

This is available in the DFS Management-console:


As well as from the DfsrAdmin.exe command-line tool:


Using this feature we can generate an HTML-report containing a great overview of the replication health for the SYSVOL replication group:


Any errors and warnings will be shown with detailed explanations. In addition we can view general information and statistics i.e. regarding free diskspace on the domain controllers, bandwith savings and so on (click on the thumbnail to view):


Since the reporting feature are available from the DfsrAdmin.exe command-line tool, it makes it easy to set up a script as a scheduled task that also sends the generated report via e-mail i.e. every morning. Ive published a simple PowerShell-script to accomplish this which is available here.


SYSVOL Replication Migration Guide: FRS to DFS Replication (Word-version available here)

Verifying File Replication during the Windows Server 2008 DFSR SYSVOL Migration


Configuring DFSR to a Static Port

FRS to DFSR Migration Tool (not for SYSVOL migration)

Automate Active Directory Migration Tool using Windows PowerShell

Active Directory Migration Tool (ADMT) provides the ability to restructure Active Directory domain structures. It allows you to migrate users, groups and computers between domains, both intra-forest and inter-forest. Features includes password migration, SID migration and security translation among several others.
ADMT was recently released in version 3.2, adding support for Windows Server 2008 R2 and Managed Service Accounts. You can find the download here, and the ADMT migration guide here.

ADMT provides three options on how to use it, where the first and maybe most used is the GUI:


Its wizard driven and pretty straightforward to use.
The second option is the admt.exe command line utility:


In my opinion this is a pretty good example on how inconsistent various command line tools are compared to PowerShell. Although ADMT is a great tool, hopefully the next version will be rebuilt based on PowerShell.

The third option is scripting. There is a COM-object called ADMT.Migration, and there is a sample VB-script (templatescript.vbs) in the ADMT installation directory (by default C:WindowsADMT). This sample script is a good place to start to explore how the COM-object works.

Based on this Ive written a sample PowerShell script, Invoke-ADMTUserMigration, to migrate user accounts and passwords using Windows PowerShell. This script uses the “ADMTDomain” option, which means that all users from the source OU will be migrated to the target OU. To see other available options, see the ADMT documentation and the sample VBScript. Migrating other objects, like groups and computers, the same way should be pretty easy when comparing Invoke-ADMTUserMigration to templatescript.vbs.

Note that since ADMT is a 32-bit application the script must be run from an x86 instance of Windows PowerShell. It also requires elevated privileges (Run as Administrator). Trying to run it in an x64-bit PowerShell instance or without elevated privileges will result in the following error:
New-Object : Retrieving the COM class factory for component with CLSID {285029CC-5048-4D90-8B38-22D304F513DC} failed du
e to the following error: 80040154.

Before trying to run the script I would recommend that you read the ADMT migration guide and ensures that migration works as expected by running a few test migrations from the GUI.

When this is done, I also would recommend to split the migration in batches as recommended in the migration guide. A maximum of 100 objects at a time might be appropriate. Before moving on to the next batch, check the migration logs (by default in C:WindowsADMTLogs) to see that everything went OK before proceeding.

To take this a step further, Ive created a function, Migrate-ADMTUser, that migrates a single user object. This would allow you to easily do things like this:
Get-ADUser -Filter {Company -like "Oslo"} | Migrate-ADMTUser

This example combines the Active Directory module for PowerShell with ADMT, allowing us to more fine grained control on what objects to migrate.
Note that both the sample script and sample function I
ve created is meant as a guidance on how to use PowerShell to automate ADMT. The optimal way as I see it would be creating an ADMT PowerShell module with functions for migrate other objects like computers and groups in addition to users and passwords.


ADMT 3.2: Common Installation Issues

ADMT Guide: Migrating and Restructuring Active Directory Domains (TechNet-version)

Send text messages (SMS) using Windows PowerShell

In Microsoft Office Outlook there is an add-in called Microsoft Outlook SMS Add-in (MOSA), which provides the ability to send text messages (SMS). MOSA is builtin to Outlook 2010, and are available as a plugin for Outlook 2003 and 2007 here.

On the Microsoft Office Online Help you can find guidance on how to set up the service account and sending a text message. To find the necessary settings for your mobile service provider, go here.

I looked into the COM-object for Outlook, and it turned out to be rather easy to use this API to send text messages from MOSA.
Based on that I created an Advanced function in Windows PowerShell v2 called Send-SMSMessage.

To define the function you can either paste it directly into your session, save it as a ps1 script-file and dot source it, put it into your profile or into a module.

When that is accomplished you can find usage information using the consistent Get-Help cmdlet:


Sample usage:


The function checks if Outlook are installed, and breaks out with a warning if not:


It also checks to see if an account are configured for Text Messaging (SMS):


Any errors related to service availabilty, correct phonenumber format and so on are handled by the SMS Add-in itself. These error messages appear in the Outlook inbox:


The function is tested from Outlook 2010 only, but should work from 2003 and 2007 also when MOSA is installed.

Since the function accepts ValueFromPipeline and ValueFromPipelineByPropertyName you can use it in conjunction with e.g. the Active Directory cmdlets for Windows PowerShell.  A given example of this retrieves all users from Active Directory with a derfined mobilephone number and sends them an SMS with their username:


Another practical usage scenario I can think of is combining the Send-SMSMessage function with user provisioning, sending the new user it`s new username and password.
Feel free to come up with more usage scenarios in the comment field below.

Bonus tips

  • You can also send MMS messages using the Outlook COM-object. To do this, use “olMobileItemMMS” instead of “olMobileItemSMS” in the following line: $NewMessage = $outlook.CreateItem(“olMobileItemMMS”). You should also look into the other properties for MMS messages, like the Attachment-property.
  • If you got more than one account configured for text messaging, you can use the SendUsingAccount-property to define which account to send from.
  • If you use the Norwegian mobile service provider Telenor, the “Service Provider URL” in the account settings is

Backing up Group Policy Objects using Windows PowerShell

A best practice in domain environments are backing up the Group Policy Objects regularly. Even though a GPO may be restored by restoring a system state backup from a domain controller to an alternate location, and then copy the contents from the deleted GPO to a new GPO to restore the settings, this may be a hazzle since its not pretty straightforward. It also requires you to restart the domain controller affected in Directory Services Restore Mode.
PowerShell MVP Don Jones has written a good article on this topic, available here.

For those of you who may not want to do GPO restore the hard way, or buy a commercial third party product, I would encourage you to schedule regular GPO backups using the Windows PowerShell Group Policy-module available in Windows Server 2008 R2, as well as RSAT in Windows 7.
To accomplish this, I
ve written a small script which backs up all modified GPO`s in the specified timespan. I would generally recommend to have the script run once a day, thereby setting the timespan-variable to the last 24 hours. The script are called Backup-ModifiedGPOs.ps1, and available from here.

All Group Policy Objects modified in the specified timespan are backup up to the specified backup path.
Also, an HTML-report are created for each GPO-backup, with the unique backup GUID as part of the filename. This way you can easily see what settings each backup contains.

When restoring a GPO, you must first note the GUID of the backup you want to restore. Then you can restore the GPO by using the Restore-GPO cmdlet in the Group Policy-module. Sample usage:


Administrators who feels more comfortable working with the GUI, may use the Group Policy Management Console to do the restore.

The following procedure from the Group Policy Planning and Deployment Guide on Microsoft TechNet describes how to accomplish the restore operation from the GUI:

To view the list of GPO backups

  1. In the GPMC console tree, expand the forest or domain that contains the GPOs that you want to back up.
  2. Right-click Group Policy Objects, and the click Manage Backups.
  3. In the Manage Backups dialog box, enter the path to the location where you stored the GPO backups that you want to view. Alternatively, you can click Browse, locate the folder that contains the GPO backups, and then click OK.
  4. To specify that only the most recent version of the GPOs be displayed in the Backed up GPOs list, select the Show only the latest version of each GPO check box. Click Close.

Using the GPMC to restore GPOs

You can also restore GPOs. This operation restores a backed-up GPO to the same domain from which it was backed up. You cannot restore a GPO from a backup into a domain that is different from the GPO’s original domain.

To restore a previous version of an existing GPO

  1. In the GPMC console tree, expand Group Policy Objects in the forest or domain that contains the GPOs that you want to restore.
  2. Right-click the GPO that you want to restore to a previous version, and then click Restore from Backup.
  3. When the Restore Group Policy Object Wizard opens, follow the instructions in the wizard, and then click Finish.
  4. After the restore operation completes, a summary will state whether the restore succeeded. Click OK.

To restore a deleted GPO

  1. In the GPMC console tree, expand the forest or domain that contains the GPO that you want to restore.
  2. Right-click Group Policy Objects, and then click Manage Backups.
  3. In the Manage Backups dialog box, click Browse, and then locate the file that contains your backed-up GPOs.
  4. In the Backed up GPOs list, click the GPO that you want to restore, and then click Restore.
  5. When you are prompted to confirm the restore operation, click OK.
  6. After the restore operation completes, a summary will state whether the restore succeeded. Click OK. Click Close.

Important: Since Group Policy links are stored on the Organizational Unit objects in Active Directory, this information are not backup up and also not restore. However, the HTML backup-reports contains this information, so you may manually re-link the GPO to the correct OU(s).

Also note that WMI filters and IPSec policies are not backed up by the backup feature in the Group Policy Management Console. For more information on how to manage these items, see the before mentioned Group Policy Planning and Deployment Guide.


Dynamic Remote Desktop Connection Manager connection list

Microsoft recently released a free tool for managing multiple remote desktop connections called “Remote Desktop Connection Manager”.

A sample screenshot:


There are several nice features, such as “Connect group” which lets you connect to all servers in a group at once:


On the “Group Properties” you may set common settings for all connections in the group, like logon credentials:


Further, there are group properties for RDS Gateway (formerly TS Gateway), display settings, local resources and so on.

There are several applications for remote desktop connections on the market, and some of them got these settings as a per server setting. Its nice to be able to group servers and configure common settings.

Dynamically creating the connection list

When you work in larger environments with hundreds, maybe thousands of servers, setting up each connection manually isnt an option.

Since Remote Desktop Connection Manager stores the config-files in xml-files, its rather easy to create dynamic config-files for a domain using Windows PowerShell. Ive created a script to accomplish this, called New-RDCManFile.ps1, available from here. It uses Microsofts PowerShell-module for Active Directory, which is available in Windows Server 2008 R2 and RSAT for Windows 7.

The script does the following:
Creates a template xml-file
Inserts the logged on user
s domain name in the file properties
Inserts the logged on users domain name in the group properties
Inserts the logged on user
s username in the logoncredentials section
Inserts the logged on users domain name in the logoncredentials section
Retrieves all computer objects from Active Directory with the word “server” in the operatingsystem property
Adds each computer object as a server object
Saves the XML-file to %userprofile%domain-name.rdg

When done you can open the rdg-file in Remote Desktop Connection Manager. I would recommend you to insert your password in the Group Properties to avoid being asked for credentials for each connection.

Feel free to customize the script to your needs, in example by editing the XML-template to edit the Group Properties. Another customization might be creating a group for each server OU for enhanced overview in larger environments.

If you would rather use Quests PowerShell Commands for Active Directory (which works on downlevel operatingsystems like Windows XP and Windows Server 2003), or any other way to retrieve the server names, you may customize this on line 110.

You might also want to schedule the script to run on a regular basis, saving the file to a central location. This way the IT personnel will always have access to the latest version with the most recent servers added.

If you got any further ideas or comments, please let me know in the comments section below.

Enable and configure Windows PowerShell Remoting using Group Policy

As you may know, Windows PowerShell 2.0 introduced a new remoting feature, allowing for remote management of computers.

While this feature can be enabled manually (or scripted) with the PowerShell 2.0 cmdlet Enable-PSRemoting, I would recommend using Group Policy whenever possible. This guide will show you how this can be accomplished for Windows Vista, Windows Server 2008 and above. For Windows XP and Windows Server 2003, running Enable-PSRemoting in a PowerShell startup script would be the best approach.

Windows PowerShell 2.0 and WinRM 2.0 shipped with Windows 7 and Windows Server 2008 R2. To take advantage of Windows PowerShell Remoting, both of these are required on the downlevel operating systems Windows XP, Windows Server 2003, Windows Vista and Windows Server 2008. Both Windows PowerShell 2.0 and WinRM 2.0 are available for download here, as part of the Windows Management Framework (Windows PowerShell 2.0, WinRM 2.0, and BITS 4.0). To deploy this update to downlevel operating systems I would recommend to use WSUS, which are described in detail in this blog post by Kurt Roggen.

Group Policy Configuration

Open the Group Policy Management Console from a domain-joined Windows 7 or Windows Server 2008 R2 computer.

Create or use an existing Group Policy Object, open it, and navigate to Computer Configuration->Policies->Administrative templates->Windows Components

Here you will find the available Group Policy settings for Windows PowerShell, WinRM and Windows Remote Shell:


To enable PowerShell Remoting, the only setting we need to configure are found under “WinRM Service”, named “Allow automatic configuration of listeners”:


Enable this policy, and configure the IPv4 and IPv6 addresses to listen on. To configure WinRM to listen on all addresses, simply use *.

In addition, the WinRM service are by default not started on Windows client operating systems. To configure the WinRM service to start automatically, navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsSystem ServicesWindows Remote Management, doubleclick on Windows Remote Management and configure the service startup mode to “Automatic”:

No other settings need to be configured, however, Ive provided screenshots of the other settings so you can see whats available:





There is one more thing to configure though; the Windows Firewall.

You need to create a new Inbound Rule under Computer Configuration->Policies->Windows Settings->Windows Firewall with Advanced Security->Windows Firewall with Advanced Security->Inbound Rules:


The WinRM port numbers are predefined as “Windows Remote Management”:


With WinRM 2.0, the default http listener port changed from TCP 80 to TCP 5985. The old port number are a part of the predefined scope for compatibility reasons, and may be excluded if you dont have any legacy WinRM 1.1 listeners.



When the rule are created, you may choose to make further restrictions, i.e. to only allow the IP addresses of your management subnet, or perhaps some specific user groups:


Now that the firewall rule are configured, we are done with the minimal configuration to enable PowerShell Remoting using Group Policy.


On a computer affected by the newly configured Group Policy Object, run gpupdate and see if the settings were applied:


As you can see, the listener indicates “Source*”GPO”, meaning it was configured from a Group Policy Object.

When the GPO have been applied to all the affected computers you are ready to test the configuration.

Here is a sample usage of PowerShell Remoting combined with the Active Directory-module for Windows PowerShell:


The example are saving all computer objects in the Domain Controller Organization Unit in a variable. Then, a foreach-loop are invoking a scriptblock, returning the status of the Netlogon-service on all of the Domain Controllers.


Weve now had a look on how to enable and configure PowerShell Remoting using Group Policy.
There are an incredible number of opportunities opening up with the new Remoting feature in Windows PowerShell 2.0. For a complete walkthrough on how you can use this new feature, I would like to recommend the excellent Administrator’s Guide to Windows PowerShell Remoting written by Dr. Tobias Weltner, Aleksandar Nikolic and Richard Giles.

Validate SPN mappings using Windows PowerShell


What is a SPN mapping?

A Service Principal Name (SPN) mapping allows a service running on an Active Directory computer to be associated with a domain account that are responsible for the management of the service. This allows the use of mutual Kerberos authentication, and an account defined in a SPN mapping are able to request Kerberos tickets on the requesting users behalf. Examples of services that uses Kerberos and SPN mappings include SQL Servers, web servers, LDAP servers, Exchange servers and so on.

Validation of SPN mappings

A SPN mapping must be unique within an Active Directory domain, and duplicate mappings will result in problems for the involved services.

While the command line tool setspn.exe, which are used for managing SPN mappings also can be used for queries, I wanted to use Windows PowerShell to accomplish this. Ive put together a script module with two functions:
Resolve-SPN – Resolves the provided SPN mapping
Resolve-AllDuplicateDomainSPNs – Resolves all SPN mappings in the domain and reports duplicate mappings

The script module are available on the TechNet Script Center Gallery, click here for the direct link.

Save the script module as a psm1-file in the following directory: %userprofile%DocumentsWindowsPowerShellModulesSPNValidation
You need to manually create the 3 subfolders under %userprofile%Documents if they doesnt exist.

When done, start Windows PowerShell and type the following command:


You should now see the SPNValidation module.
Import the module with the Import-Module cmdlet:


Resolve-AllDuplicateDomainSPNs can be executed without any parameters:


Resolve-SPN has one mandatory parameter: –SPN
Example usage:


Note that the PowerShell Active Directory module for Windows
Server 2008 R2 are required, because the Get-ADObject cmdlet are used in one of the script module
s functions.
The PowerShell Active Directory module are also available in Remote Server Administration Tools (RSAT) for Windows 7.

Automate Group Policy Preferences printer-management using Windows PowerShell

Ive written a couple of blog posts earlier on Group Policy Preferences and printer deployment using Group Policy.

Using Group Policy Preferences is a very flexible way to deploy printer connections. This is also very manageable in smaller environments. What if you got hundreds, or even thousands of printer connections you need to deploy? Do you want to sit down and make several thousands of mouse clicks to accomplish the task? There are better alternatives!

Based on SDM Softwares Group Policy Automation Engine, Ive created a script module to handle this. The script module are available from this link.

Save the script module as a psm1-file in the following directory: %userprofile%DocumentsWindowsPowerShellModulesGPPreferencesPrinters
You need to manually create the 3 subfolders under %userprofile%Documents if they doesn
t exist.

When done, start Windows PowerShell and type the following command:


You should now see the GPPreferencesPrinters module.
Import the module with the Import-Module cmdlet:


As you can see there are two functions in addition to SDM Software`s cmdlet: Add-GPPreferencesPrinter and Get-GPPreferencesPrinter.

Example 1:


Example 2:

If you got the printers listed in an Excel spreadsheet, save the document in csv-format:


The csv-file may be used like this to import the printer connections:



Additional functions and parameters will later be added to the script module, i.e. Remove-GPPreferencesPrinter and Item-Level Targeting. Note that example usage for Item-Level Targeting are provided in the Group Policy Automation Engine User Manual.