Wednesday, January 23, 2013

Building A Hyper-V Test Lab on Windows 8 – Part 4 Creating a DC


This the fourth part in a multi-part set of articles on building a test lab with Hyper-V and PowerShell. See the following prior articles in this series.

Creating the DC

The starting point for creating a DC is having a simple work group VM created and run. In the last article I covered how to build a Hyper-VM Based a differencing/parent pair of disks. That process generates a work group computer, with a known IP address, a known hostname and a known user id/password set of credentials. The VM that is created has just the standard set of services and features that the base installation process generates (i.e. the same as if you just click next/next/next installing a VM from a DVD).

In Windows Server 2012, the process of creating a DC has changed quite considerably from earlier versions of Windows Server. DCPromo.exe is no more – you now promote a server by using PowerShell cmdlets (although I suppose you could use the GUI – but where’s the fun in that?). 

The installation process for a new DC in a new forest comprises two simple steps:

1. Using Install-WindowsFeature to add the AD-Domain-Services and related management tools.

2. Using Install-ADDSForest, create a new domain and domain controller, install DNS, and set the domain/forest modes (i.e. what DCPromo.exe used to do in years gone past).

Using remoting to perform the DC promotion

In the first two scripts that create and start up the VM, I created a function that I then ran on the local system, i.e. the host you are using to run Hyper-V. All the development was done using Windows 8 and Server 2012 which both run Hyper-V. The remainder of the scripts to setup and configure the domain and servers is done using remoting plus some local hyper-v stuff. Basically, the remaining scripts all have the following pattern:

a) Create a script block containing PowerShell code to perform some configuration on a server.

b) Use Invoke-Command to run that script block on a remote server (i.e. one or more of the Hyper-V VMs you are building/configuring.

This process is flexible and allows me to do things before invoking the script block. For example, to install SQL, Exchange and Lync, I need to have the product CD inserted in the D: drive. For Exchange, I have to load some pre-requisites onto the server, for example bits of IIS, etc. In that case, my published script file can create a couple of script blocks to divide up the work.

When I am building out a new set of VMs, I open ALL the scripts in the ISE on the Hyper-V host (which in most cases is actually being used via a terminal services window!) With all the scripts up, I just work through them, building the base disk, building then promoting DC1, finishing off DC1 configuration, configuring a CA, Configuring the IIS servers, etc.

Promoting with PowerShell

The PowerShell code to carry out the promotion is as follows:

Install-WindowsFeature –Name AD-Domain-Services –IncludeManagementTools
$PasswordSS = ConvertTo-SecureString  -string 'Pa$$w0rd' -AsPlainText -Force
Install-ADDSForest -DomainName Reskit.Org –Force –InstallDNS `
SafeModeAdministratorPassword $PasswordSS  -DomainMode Win2012 `
  -ForestMode Win2012

The first step involves windows loading the necessary components to enable the host to be configured into some sort of DC as well as all the management tools. The second step involved creating a new domain in a new forest. In my case, I set both the forest and domain into Win2012 mode (why not?) as well as specifying a safe mode password.

Completing the DC Promotion

After running these few lines of PowerShell, the Install-ADDSForest cmdlet reboots the machine. At which point, assuming nothing hairy has gone on, you now have a DC. It has one main user, Administrator, whose password is the same as the local machine’s Administrator password (in my case Pa$$w0rd).

Unfortunately, for scripting purposes, the reboot is an asynchronous event – there’s no easy way for a PowerShell script to wait for the reboot and continue. Sure – you can use work flows for that, but I don’t (well not yet!). So to finish off the process of configuring the DC, I’ve created a couple more scripts. The first of these, which I’ll describe later, is one you run after the DC has rebooted. This second script does a bit more configuration on the DC, including adding any users, OUs, computers, etc. that might be needed. The second, at least in my case, is adding a Certificate Authority to the DC. I’ll look at both of these scripts in future articles.

Getting the Scripts

I have published the full set of deployment scripts to my web site, at Note that some of the scripts in this zip file are still works in progress. I reserve the right to change any of all of them from time to time. I will try to blog any important changes.

I am also publishing the individual scripts over on my PowerShell Scripts Blog:

Tuesday, January 22, 2013

Improving PowerShell with 3rd party Modules

PowerShell is an awesome product with amazing potential. But as we al know, the product team can not do everything and neither can the various product teams at Microsoft. As has been quite evident since Monad first peeked it’s head outside Redmond, the community can provide a lot of great extra functionality. Some an alternative to MS produced code (e.g. the Quest AD cmdlets), while other add-ons add features not available elsewhere.

These add-ons are typically, at least since V2, wrapped up in a module and the module then published somewhere. Finding these modules can be quite a chore as they are scattered all over the Interweb! The Microsoft Script Gallery project has quite a few add-on modules published in their archives.

Here’s a set of the most popular modules published at the Microsoft Script Centre:

File System Security PowerShell Module 2.1.
Allows a much easier management of permissions on files and folders using PowerShell. Download this module at:

Local Account Management Module 2.1
This module allows managing local groups and user accounts, local group membership and some other useful tasks. It is mostly based on the .net classes in System.Dir. Download this module at:

Active Directory Replication PowerShell Module 2.01
Managing Active Directory Sites, Site Links and Subnets very easily with PowerShell. Also checking the Active Directory Replication is easy and richer than repadmin.exe, the cmdlets in this module do return objects and not just text. So no more boring test parsing. Download at:

DHCPAlternateConfiguration PowerShell Module
The DHCP Alternate Configuration module is a command line interface for managing the DHCP client alternate configuration as described. Download at:

Kerberos Module
The module gives access to the Kerberos ticket cache. It can read and purge tickets of the current logon session. Download from:

Windows Update PowerShell Module
The PSWindowsUpdate module helps you manage Windows Update on a computer system running Windows. Whole module contain 9 function to check, download and install updates from PowerShell. Download at:

Registry Security PowerShell
Allows a much easier management of permissions inside the registry database using PowerShell. Download at:

Monday, January 21, 2013

Building A Hyper-V Test Lab on Windows 8 – Part 3 Creating VMs

This the third part in a multi-part set of articles. See the first article for the start of the set and to understand better what this is all about – see here: And to see the prior article on creating a reference VHDX see here:
Building a VM
The overall purpose of my VM Build scripts is to create and configure a set of VMs in a test environment. In the last article, I showed how you can create a base or reference disk. In this article, I show how you can take that base disk and create both a differencing disk and a VM that uses that new disk.
Each VM created gets a customised Unattend.XML file, which is stored on the differencing disk, once that disk is created. Thus, when the VM is started, OS installation is completed using the XML file. This allows me to do some simple things, like kill the firewall, set the right language(s), etc.  Creating this file was one of my early stumbling blocks!
From the earliest days of Windows NT, you could create an Unattend.txt file, put it on a floppy disk, insert the floppy into your system then install the OS from the CD. That enabled Windows NT setup to get the details of the installation coming from the Unattend.Txt. I did a lot of that in then NT 3.5/3.51/4.0 days. But with Vista, Microsoft shipped a totally new setup method, with WIM files and with Unattend.txt replaced with (a more complex) Unattend.XML. Pretty much everything I knew about unattend.txt files goes out the window.
A key objective I had in creating these build scripts was to avoid having to know too much about these XML files. I got a ‘starter’ copy form my good pals at Lab Center in Stockholm and have tweaked it (removing things I don’t need) and creating useful default settings for things (e.g. keyboard).
I really wanted to avoid becoming a deployment wizard and use a generic Unattend.XML file. But sadly, that objective proved to be a little unreasonable, but I’ve tired hard to minimise the number of things configured in the XML file and do as much as I can via PowerShell scripts after the OS has been installed.
Using Unattend.XML files is pretty simple, as long as you understand both the Windows build model and the components you can add to windows. To use the Unattend.XMO file, you create/configure the XML file, save it on the differencing disk and add the differencing disk to the VM. This way, the unattend.XML file guides Windows Setup to create the VM as you need it.  Subsequent scripts that configure the VM further (e.g. adding application specific windows component, adding applications and features, etc.).
In the Unattend.XML file, I currently specify 14 components in three passes as follows



The effect of this component

Generalize Microsoft-Windows-Shell-Setup Specifies that Sysprep should not remove any icons from the Quick Launch toolbar
Specialize Microsoft-Windows-UnattendedJoin Specifies the domain to join and credentials needed to join or whether to just ‘join’ a named workgroup
  Microsoft-Windows-Shell-Setup Specifies Computer name, registered organsiation and owner, and time zone
  Microsoft-Windows-IE-InternetExplorer Sets home page to blank and whether to disable the run-once wizard
  Microsoft-Windows-Deployment Enables local administrator account
  Microsoft-Windows-International-Core Specifies Input Locale, System Locale, UI Language and UserLocale. The input locale sets an initial keyboard layout.
  Microsoft-Windows-TapiSetup Tapi settings
  Microsoft-Windows-IE-ESC Turns off the IE security settings
  Microsoft-Windows-TerminalServices-LocalSessionManager Enables Terminal services connection to the VM
  Networking-MPSSVC-Svc Turns the firewall off on the VM
  Microsoft-Windows-TCPIP Sets TCP/IP settings, including IP address, subnet mask and default gateway
  Microsoft-Windows-DNS-Client Specifies the DNS Server IP address
OobeSystem Microsoft-Windows-Shell-Setup Specifies local administrator password, whether to hide the EULA pages plus sets the time zone
  Microsoft-Windows-International-Core Specifies a 2nd language to be setup for this VM
The Create-VM function
The core aspects of the VM creation is done with the Create-VM function. The function takes parameters including the VM name, the path to store the VM information for Hyper-V, the path to the reference disk, what network to use, how much memory to set, which Unattend.XML file to use and the IP address, subnet mask and DNS Server Address.
The details of the VM created is determined by what is in the Create-VM function, details in the the Unattend.XML file and some details set by the call to the create-VM function. For example, the keyboard settings used are set in the XML file only, whereas the use of dynamic memory is set only in the Create-VM function. The IP address, on the other hand, has a default set  in the XML ( The Create-VM function, however, overwrites this address with the IP address/subnet mask specified  in the call to Create-VM.  The parameters specified on the call to Create-VM are used to update the Unattend.XML file stored on the differencing disk and used to install the OS.
I use two XML files – one is used to create a stand alone server the other to create a domain joined server. I use the former to create DC1 and once DC1 has been promoted to be a DC, the later XML file is used to create servers that are domain joined. Both XML files, on the other hand, set keyboard layout
This approach of setting some installation options in the XML and others via the function (and resulting in updated XML) seemed to be a good compromise. I only implement parameters to Create-VM that need to be differ3ent in different VMs, whereas installation options
Creating the VM
The task of creating/building the VM is performed by the Create-VM function and involves the following steps:
  1. Creating a differencing disk – this is the ‘difference’ between a reference or parent Vhdx  and  the disk. 
  2. Creating a VM in Hyper-V.
  3. Adding the differencing disk into the VM.
  4. Mounting the VHD on the host computer.
  5. Based on a pre-built Unattend.XML, creating a customised Unattend.XML file and saving it to the on the mounted VHDX.
  6. Dismounting the VHDX from the host
  7. Setting VM settings including memory, startup actions etc.
  8. Starting the VM.

Once the VM has started, windows setup proceeds to install Windows as per the Unattend.XML file. The creation of the VM itself takes just 20-30 seconds, followed by the actual installation which takes 10-15 more minutes (and more if you are doing multiple installations in parallel).

The Created VM
The VM created by the Create-VM function will either be a workgroup VM or a VM that has been joined to the domain, as specified in the Unattend.XML file. This VM will be fairly vanilla with only a few options specified (as noted above). There are no extra applications loaded, and the file only ‘works’ once you have the DC up and running.

The Create-VM script takes around 27-30 seconds to create and start the VM in Hyper-V. On my WIn8 laptop, it take a further 5 minutes to complete the creating of the first DC.

Once you have the reference disk, you can call the Build-VM function like this:

$ref    = …   # Path to the reference disk
$Path   = …   # Path to where to put the VM and differencing disk
$unadj  = …   # Path to Unattend.XML
#     Now Create the VM
Create-VM -Name "Srv1"  -VmPath $Path –ReferenceVHD $Ref  -Network "Internal" `
          -UnattendXML $unadj -Verbose -IPAddr '' `
          -DNSSvr  -VMMemory 512mb

You run this script ON the Hyper-V server. Once the Create-VM function completes, which takes between 20-25 seconds in my case, Hyper-V starts up the VM and completes the installation of the OS inside the VM. The complete installation takes 20 minutes or so (depending on your system, how much RAM you give the VM, the speed of your system, etc.). Once the setup is complete, you can move on and configure the VM with application and application settings.

Where are we on this journey?
In the these first three blog posts, I’ve set out the objectives of a VM Build module for building VMs and the two core functions/scripts. The two scripts create a base VM disk, a differencing disk and a VM. Each VM is customised a little in the call to Create-VM – in effect creating a base VM. Once this VM has been created, you can then load additional applications and Windows features (e.g. making the DC a certificate authority). In the next episodes of this set of blog articles, I’ll start looking at the scripts that add those applications and features. And I’ll share the interesting things I’ve discovered along the way. I’ll also publish the scripts and the unattended XML files.




Technorati Tags: ,,

Viewing PowerShell Function Definitions in the ISE–Part 2

Last Friday, I published an article about a neat script I’d come across. At the end, I mentioned it would be nice to extend this to enable me to highlight a function name I’m calling in code and either use a menu item or short-cut keys to get the definition up.

Well, I spend several hours today playing and have done just that. Yesterday, I polished up the code a bit and published it over on my PowerShell Scripts blog. At home, I’ve incorporated it into my personal ISE module and it now loads every time I start up the ISE.

The script, as extended, defines a function (Open-FunctionInISE), then adds it to an ISE menu. The function takes input in three ways: you can specify the function name to open, you can highlight the function name in an open edit window and use either short-cut keys or the ISE menu. And if those fail, the function prompts for a function name. I’ve also taken the liberty of renaming the function to be, hopefully, closer to best practice naming!

In converting the function, it was interesting working with a single function that could take input from the pipeline, from the command line of via selected ISE text (and which prompts for a function name if all those fail). In doing the conversion, changed the parameter from a string array to string, which felt nearer to the way I see the script being used. I might play around a bit with the script and add that back in. To simplify such changes, I’ve left the function to operate in the Process block, but I have pulled out the enumeration of objects within each process block.

Another thing the extended script did was to add the function to a menu item in the ISE. That turns out to be easy. Before the script adds the function to the add-on menu, it checks to see if it’s already been added (as might happen if you decide to edit the function and start running it!). Of course, if you already have the menu item created, to make changes in the function itself, just comment out the menu addition code. Or use the function to bring the function definition into the ISE, make your changes and re-run just that script (remembering to persist any changes you decide to make!).

Thanks to the original author of this script (Cookie.Monster) for giving me something fun to do on a Sunday afternoon. Comments most welcome.

Technorati Tags:

Friday, January 18, 2013

Microsoft PowerShell V3 Course (10961) Announced

Microsoft’s just published details of it’s ‘official’ course on PowerShell V3. This is being written by Don Jones, so it should be a pretty solid course. I look forward to teaching this course, which is meant to go live in May. I don’t know who the TE will be, but I’ve certainly volunteered!

The course looks to be a good beginners look at PowerShell V3. As the Microsoft web site points out, this will be a 200-level look and is not intended to teach much about scripting or programming. For those IT pros who have never seen PowerShell, this looks to be a very good course, although it will be pedestrian and will not be overly technically deep.

I have my own PowerShell V3 material and have been teaching V3 for some months. My material is more condenses, and at a higher level (300-400), and I have more advanced material for those needing more specific PowerShell related skills such as using PowerShell to manage XML and SQL. One (if I do say so myself) awesome aspect of my material is that delegates build their own VM test environment using PowerShell scripts (i.e. ones I started blogging about this week).

I am looking forward to the new course – which should be great fun to deliver as well as being able to challenge delegates with more advanced material as needs be.

As soon as I get the courseware and am able to, I’ll post more about this course.

Viewing PowerShell Function Definitions in the ISE

I came across a neat script, recently posted to Microsoft's Script Center. The function, Open-ISEFunction.ps1 takes the name(s) of function(s) that are currently defined and creates an ISE edit tab for each function.  It’s pretty simple in that it jut grabs the function definition from the function: drive, wraps the definition in a function/script block, then opens and adds the definition in a new ISE window.

If I get time, I might extend this function for the ISE into a menu item. The expanded function, which could as a menu item have a command key short-cut, could take any selected text and try to open the module of the same name. I’d also like to add a couple of comments at the start that might help.


Technorati Tags:

Thursday, January 17, 2013

PowerShell Profile Files

As a power user of PowerShell, I have heavily customised my environment, through the use of profile files. I create additional PS drives, define key variables and aliases, create credential objects for my test labs and local domain, configure the title bar to make the user I’m running PowerShell as a bit clearer, etc.  My ISE profile file also imports a few modules which add menus to the ISE console. I rely on my profiles – and even when teaching. I’ve put up a base console and ISE profile on my DropBox account and have loaded the basic files there.

But when it comes to running background jobs or doing remoting, those profile files are not, as it were, in play. Mike Pfeiffer, over on Don Jones (old) blog, writes an interesting article about this very point. While the post dates from 2011, the relevance of profiles is all the more these days as remoting becomes much more prevalent (and the ‘missing’ profiles become more of an irritation!).

This article is worth a read!


Wednesday, January 16, 2013

Building A Hyper-V Test Lab on Windows 8–Part 2 Creating a Reference VHDX

This the second part in a multi-part set of articles. See the first article for the start of the set and to understand better what this is all about – see here:
Base/Parent Disks in Hyper-V
With Hyper-V, you assign one or more virtual disks to a VM. One trick, borrowed from VMware, is the ability to create parent and differencing disks. The parent disk is a normal VHDX drive built out to a certain point. This can be a completed installation, or a partial installation. The differencing disk is then the difference between the base or parent virtual disk and the contents of the combined virtual disk at some later point in time i.e. after installation. Thus if the base disk was the uninstalled image, the differencing disk would only hold the changed made since installation.
On my Windows 8 box, the reference disk is 8.2GB while each of the differencing disk are between 2-3 GB.  In all the 4 VMs currently in a configuration I am testing takes up around 23 GB. Were I to create a full separate drive for each VM, I’d need nearer to 40 GB, so the space reduction is useful!
The way I use this in my labs is simple. I create a base disk which contains the uninstalled image of Windows server using the Create-ReferenceVHDX script. Then I use that reference disk in the Create-VM function that actually creates and starts a VM.
Creating a Reference VHDX using PowerShell
Creating the reference VHDX is pretty simple. The Create-ReferenceVHDX.PS1 script file creates a function, Create-ReferenceVHDX, then at the bottom invokes that function to actually create a reference VHDX. In my testing, it takes around 8 minutes to create the reference disk, most of which is taken up by DISM.EXE applying the relevant image to the base disk.

The creation process is as follows:
  1. First, we load the DISM module.
  2. Next we mount the ISO image used as the basis for the VHDX into the host machine (I.e. the Hyper-V host). The name of the VHDX is passed as a parameter to Create-ReferenceVHDX. We have to get the volume object to then get the drive letter where the IOS is mounted.
  3. We read the install.wim from the appropriate spot on the DVD and get the user to specify which installation contained in the WIM is to be used as the basis for the base disk. I use Out-GridVIew for this, but you could I suppose just take whatever the last option is (or the first) as needed.
  4. The function then creates a new VHDX file to hold this image, which is then initialised. Sometimes this throws up a dialog box but that can be safely ignored.
  5. DISM.exe then runs which applies the chosen install image onto the VHDX. This is quite a long process and can take 10 minutes.
  6. Once the image is laid down, BDCBoot ensures the disk can be booted from.
  7. Finally, the VHDX is dismounted form the local host and the function finished.

See the script for the details of how these steps are carried out!

Using the Create-ReferenceVHDX Function
Using the reference VHDX is pretty simple – three lines in all:

$Iso          = …    # Path to Server 2012 DVD    
$Refvhdxpath  = …    # Path to where the reference VDHX is to go
Create-ReferenceVHDX -Iso $iso -RefVHDXPath $RefVHDXPath  -Verbose

Using the Reference VHDX
Once the reference VHDX is created, you can use it as the basis for creating differencing disks you can then insert into VMs. See Part 3 of this tutorial to see how to do that.

Getting the scripts
The scripts are all published to a zip file: Use carefully and enjoy!

Monday, January 14, 2013

Learn PowerShell Toolmaking in a Month of Lunches – A great new book!

Over the recent holiday period, I got my hands on Don Jones and Jeff Hick’s latest book: Learn PowerShell Toolmaking in a Month of Lunches, published by Manning (see: for details of the book).

For anyone wanting a deeper set of PowerShell skills, this book is great. It firstly covers the journey from writing simple scripts to writing re-usable functions and modules. In doing that the book also covers things like help information for your functions, using work flows, globalisation, etc.

If you think you know PowerShell, then you really should read this book as you probably will still learn things (I did!). And if you are a novice with PowerShell, this book will teach you good practice.

As with all Don’s books, this one is easy to read, the examples work and the flow is easy to follow. The authors’ viewpoints and biases are also on display. You can easily spend your lunch break each day reading another chapter and experimenting with the techniques shown. Or as I did, sit down and read it all the way through in a couple of days. Either way this is a very good book for those wanting more and deeper PowerShell skills.

As my quote on the cover of the book stays: Yet another great book from PowerShell legends Don and Jeff.

Technorati Tags: ,

Sunday, January 13, 2013

Building a Hyper-V Test Lab on Windows 8 – Part 1

This is the first part of a multi-part blog article on a set of scripts to create VMs using Microsoft’s Hyper-V on both Windows 8 and Server 2012.

Note: this page is being updated along with others in this set as I slowly get all this documented and published.


For many years, I’ve used virtual machines heavily. The articles, courses and books I write rely on VMs for their content. I’ve lost count of the number of domains I’ve built, re-built, broken, fixed over the years. 

The only downside is that I was regularly building and re-building the systems by doing creating a new VM and installing the OS from scratch. This was slow and tedious as well as somewhat error prone.

What I needed was a good, reliable system of creating sets of VMs and configuring them. The base set of services I want to be able to install and use was not that long: the OS (with AD, ADCS, DHCP, DNS, File Services), SQL, and Exchange.

Now that I have these scripts working, or nearly so, I am amazed at how much easier it is to create a set of VMs for particular purpose (e.g. write an article, create a class, build a demo for a talk). I am also finding others that have similar needs. I hope others find these scripts useful!

Building VMs Using Scripts

In the autumn of 2012, I, along with super-star MVP colleague Niklas Goude, started running PowerShell Geek Weeks in Stockholm. A lot of fun – 5 days of going as deep as we can with PowerShell. A key part of the Geek Week adventure is for the delegates to build their own environment AND to be able to take away the tools to re-create this environment at home.

I spent quite some time building some basic scripts – and encountered a lot of dead ends along the way. The first time out was a limited success – limited in that some pieces did not fit together well but a success in that it taught a lot of cool PowerShell features and showed us where we needed to do more. It also helped me to refine the real objectives the tools had to meet. Thanks goes to Mikael Nystrom for helping me with a good starting Unattend.XML!

Objectives of the VM Build module

My main objectives of these build tools were:

1. To enable someone with fairly limited PowerShell skills (or greater!) to use the the scripts simply and flexibly in the classroom and later.

2. To enable building out of a small farm of up to say half a dozen servers with minimal effort.

3. To enable extensibility, in that one could add more scripts to refine the configuration (e.g. adding a script to implement a failover DHCP).

4. To encode things like domain/forest names, user ids, passwords and IP address information to a given standard but make it not too difficult to change that.

5. To avoid the user having to use too much of the new automated setup approach.

6. To keep the use of disk space to a minimum.

The Architecture

The basic architecture of what I am trying to build is shown here:



The idea is simple – a single reference, parent, disk with a number of separate VMs based on differencing disks. This approach hits objective 6, and enables a simple solution to objective 4.

The Scripts

The key scripts here are as follows:

  1. Create-ReferenceVHDX – this script creates a parent VHDX based on an image from the Install.WIM from a Server (or client) installation DVD.
  2. Create-VM – this script creates a differencing VHDX, based on the reference VHDX, and creates an updated Unattend.xml file, stores this on the differencing drive. The script then starts the VM which then installs Windows onto the differencing disk. You run this script to create the VMs and VHDXs for DC1, Exch1, SQL1, SRV1, SRV2.
  3. Configure-DC1-1 – this script turns the first VM, DC1, into a domain controller in a new forest.
  4. Configure-DC1-2 – this script configures DC1, post installation as a DC. This includes adding and configuring DHCP and creating some users in AD.
  5. Configure –DC1-CA – this script convers DC1 into an Enterprise Root CA, and creates a web responder, complete with SSL support for the /Certsrv application.
  6. Configure-Exch1 – this script configures the Exch1 VM, including installing Exchange 2008 on the Exch1 VM.
  7. Configure SQL1-1 – this script configures the SQL server VM, including installing SQL server itself.
  8. Configure-SRV1-1 - Configure-SRV2-1, these scripts create a pair of application servers, including adding all of the RSAT tools and IIS.
  9. Utility Scripts – these include Set-DVDDriveOnAll (sets a particular DVD/ISO to be in the DVD drive of all VMs), Set-LanguageOnAll – sets the administrator logon have a particular kb layout for all vms, Set-NetFrameworkCoreOnAll (adds the base .NET onto all systems – which is needed for PowerShell V2).

These scripts are now online and you can get them from


What’s Next?

There are several next steps:

  1. I’ll publish each script both to the PowerShell scripts blog ( as well as publishing details of each scripts here. IN publishing the details here, I’ll explain what each script is doing and why I did it that way. As ever, comments are welcome – and may cause further updates to the script set!
  2. I’ll update this page with pointers and anything updated as I complete this set of posts.
  3. Package these scripts up as a downloadable module. Right now, these are just a bunch of scripts and some XML – making a proper module out of it is high on my agenda.
  4. Do a better job of centralising the variables across the scripts – things like user name, password, domain name, etc. I had in mind an XML file with all the key stuff in just one place!
  5. Take feedback and refine. Comments on these scripts are most welcome.


With the release of Server 2012 and Windows 8, building a set of Hyper-V VMs is now easier than ever – and these VMs can easily be moved from server to client and back as needs dictate. The set of scripts I’ve created have helped me create lab environments quickly and easily and may help you too.

Comments most welcome!

Catching Exceptions in PowerShell

In a recent class, I was discussing how you can deal with exceptions that occur when PowerShell hits a terminating error. Doing this allows you to gather information around events that should not have happened – but did! I wrote up a blog article a couple of years ago which describes error handling in PowerShell that describes how you can catch errors.

The question was not so much, how do I do it, but what are the specific errors you can actually trap. For example,

Trap [System.DivideByZeroException] { 'whoops - divide by zero'; }
$z = 0


Try {
  $z = 0
Catch [System.DivideByZeroException] {
'whoops - divide by zero' }

That bit is fairly easy.  But do I what I can trap for? Turns out, answering that question is relatively easy as long as you know the .NET exception names you wish to trap or catch.  Within .NET, an Exception is a specific terminating error that I can explicitly catch. In the above code fragment, the code catches the specific Divide by Zero exception.

I have just posted a script to my PowerShell Scripts blog which does this. The script is posted at: If you download it and run it, look in the right hand column - those are the exceptions you can catch.

To find more about the individual exceptions, MSDN is your friend.