Updated – PS2Wiz – Addition of Out-GridView support

I updated the PS2Wiz tool on CodePlex: http://PS2Wiz.CodePlex.com.


I’ve been using the PowerShell cmdlet Out-GridView for selecting and managing datasets in a graphical manner, and wanted to see if I could extend that functionality to the PS2Wiz tool. Additionally, I was a bit disappointed in the lack of ListBox support in the existing PS2Wiz implementation. The only features to allow a user to select an item from a list was the PromptForChoice() function as a collection of Radio Buttons.

What I ended up with is an override replacement of the Out-GridView cmdlet within PS2Wiz, meaning that when you call Out-GridView in your script, rather than calling the native PowerShell Out-GridView cmdlet with it’s own window, PS2Wiz redirects the command to the PS2Wiz version which displays the content in the Local Wizard Window.

For example if you were to create a PowerShell script for PS2Wiz that ran the command:

get-childitem c:\ | out-gridview

It would show in the wizard like:

You can also output an array of strings to Out-GridView and have it display as a list

type c:\windows\win.ini |out-gridview


The internal PS2Wiz version of Out-GridView supports all of the standard Out-GridView Parameters like -Wait -PassThru and -OutputMode. It’s a pretty good replacement for the internal Out-GridView cmdlet.

One exception is that the PS2Wiz version of Out-GridView supports passing in arrays for the -InputObject parameter. So the following command will list items in PS2Wiz, but not in regular PowerShell.exe

out-gridview -InputObject (get-Process |select-Object ID,Name)


Additionally, I added a treeview control for MDT Objects. This allows for some future MDT management scripts.

Import-Module "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1"
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\DeploymentShare" | out-null
Select-MDTObject -OutputMode Multiple -RootNode "ds001:\Applications"


This allows me to develop some tools that manage MDT Shares, selecting Applications, Operating Systems, Drivers, Packages, TaskSequences, and more..

Could be useful. 🙂


New Tool – PS2Wiz – Run PowerShell scripts in a Wizard Host! http://ps2wiz.codeplex.com/

Posted my first project to CodePlex: PowerShell Host Wizard at http://ps2wiz.codeplex.com

It’s a way to distribute your PowerShell Scripts as an Executable (*.exe) with a Wizard User Interface.


It’s intended for those PowerShell developers who may be getting pressure to create fancy User Interfaces, but don’t want to get into the quagmire of developing custom Forms just as a front end to the PowerShell script that does the real work. PS2Wiz will automatically hook into the PowerShell system and construct the User Interface elements automatically when requested by the script.

* Write-Host – will become a label.
* Read-Host – will become a TextBox.
* Get-Credential – will display two TextBoxes for credentials.
* Copy with -Confirm – will display a radio button to confirm.
* Call a function with Mandatory Parameters – Those get auto generated.
* and more…


I created a video to demonstrate how it works.



Special Thanks to ikarstein for the excellent work on PS2Exe. Got me inspired to release it to CodePlex.
(And to @mikael_nystrom for pointing me to PS2Exe a few weeks ago via twitter)

Customizing Your Windows Deployments

Hello again from Mall of America in Minneapolis Minnesota at the Minnesota Management Summit 2014 (MMS for short). #mmsminnesota

Today I am giving a presentation on “Customizing Your Windows Deployments – Tips, Tricks, and Code”.


Stick with Well-Known and Proven Solutions
MDT Wizard Studio


I wanted share the source code examples from my presentation:

MMS2014 – Customizing Your Windows Deployments.zip

Inside you will find the following:

MMS2014 - Customizing Your Windows Deployments.pptx
1 - Unattend\makevhdx.ps1
1 - Unattend\make_client_vhd.cmd
1 - Unattend\Run-VHD.ps1
1 - Unattend\unattend.Workgroup.xml
1 - Unattend\unattend.xml
2 - ztigather\CustomSettings.ini
2 - ztigather\UserExit.vbs
3 - CMD\AppWrapper.cmd
3 - CMD\Source\7z925x64.msi
4 - VBS\ZTIUtility.vbs
5 - PS1\CM1.CleanUp.ps1
5 - PS1\Get-Service.ps1
5 - PS1\Test-MDTPowerShell.cmd
5 - PS1\Test-MDTPowershell.ps1

In the “1 – Unattend” folder is my example of how to take a Windows *.iso image and mount in Hyper-V.
In the “2 – ZTIGather” folder is a quick example of a customsettings.ini file and a userexit.vbs script.
In the “3 – CMD” folder is an example of using a CMD file to wrap commands in a batch script.
In the “4 – VBS” folder I have some examples on how to create MDT VBScript files.
In the “5 – PS1” folder I have an example of how to call a powershell script from within MDT.


Imaging Factory performance

I’ve been experimenting recently with building a Hydration Imaging Factory on one of my servers. A Hydration Factory is a Windows Host that constructs Windows images for use in deployment.

Perhaps you have a simple setup in your environment using MDT LiteTouch. This could be something like a task sequence that installs Windows 7 x64, runs Windows Update, syspreps and captures back to a *.wim file. Or perhaps you have a laundry list of applications that need to be installed in your corporate standardized image for VDI scenarios. With the correct settings in your CustomSettings.ini file, this process could be fully automated, and repeatable. Spin up a Virutal Machine and 30 minutes later you have a new install.wim file.

A Hydration Imaging Factory will combine the automation of MDT LiteTouch with some PowerShell automation to build out a list of virtual machines.


I’ve been spending some time trying to make my Hydration Factory system modular, and right now I can kick off a new build and my Host.
In my system:

  • All images are fully patched and have IE 11 and the KMDF
  • Some images are “Min” – No applications, just Updated/Patched
  • Some images are “Full” – Applications like Adobe Reader, Chrome, VCRT, etc.
  • I also create a Hyper-V specific versions (PersistAllDeviceInstalls)
  • I have packages for Office and SQL, but did not include below
  • I run a dism /clean command just before sysprep to trim the images
  • Results

    Given my host test machine (Simple single processor multi-core desktop, i7, 32GB of ram, and multiple SSD Drives). It took about 7 hours to build out the following Virtual Machines.

    4,080,851,813 WIN10STPX64.SRV.Full.HV.WIM
    4,080,982,651 WIN10STPX64.SRV.Full.WIM
    3,954,997,709 WIN10STPX64.SRV.Min.Core.HV.WIM
    3,955,009,907 WIN10STPX64.SRV.Min.Core.WIM
    3,955,336,881 WIN10STPX64.SRV.Min.HV.WIM
    3,955,175,443 WIN10STPX64.SRV.Min.WIM
    3,882,925,692 WIN10TPX64.ENT.Full.HV.WIM
    3,882,213,922 WIN10TPX64.ENT.Full.WIM
    3,754,245,946 WIN10TPX64.ENT.Min.HV.WIM
    3,754,582,199 WIN10TPX64.ENT.Min.WIM
    2,989,545,883 WIN10TPX86.ENT.Full.HV.WIM
    2,992,590,857 WIN10TPX86.ENT.Full.WIM
    2,921,467,219 WIN10TPX86.ENT.Min.HV.WIM
    2,921,762,549 WIN10TPX86.ENT.Min.WIM
    5,775,824,112 WIN2008R2SP1.Full.HV.WIM
    5,775,798,368 WIN2008R2SP1.Full.WIM
    4,618,522,652 WIN2008R2SP1.Min.HV.WIM
    4,618,521,668 WIN2008R2SP1.Min.WIM
    4,921,167,148 WIN2012R2U.Full.HV.WIM
    4,921,555,872 WIN2012R2U.Full.WIM
    4,513,623,325 WIN2012R2U.Min.Core.HV.WIM
    4,554,749,492 WIN2012R2U.Min.Core.WIM
    4,451,558,474 WIN2012R2U.Min.HV.WIM
    4,459,989,734 WIN2012R2U.Min.WIM
    5,955,716,470 WIN7SP1X64EVAL.Full.HV.WIM
    5,751,198,710 WIN7SP1X64EVAL.Full.WIM
    4,761,940,473 WIN7SP1X64EVAL.Min.HV.WIM
    4,776,248,329 WIN7SP1X64EVAL.Min.WIM
    4,223,192,736 WIN7SP1X86EVAL.Full.HV.WIM
    4,179,078,039 WIN7SP1X86EVAL.Full.WIM
    3,440,522,203 WIN7SP1X86EVAL.Min.HV.WIM
    3,440,523,165 WIN7SP1X86EVAL.Min.WIM
    5,443,684,448 WIN81UX64EVAL.Full.HV.WIM
    5,442,443,606 WIN81UX64EVAL.Full.WIM
    4,723,143,084 WIN81UX64EVAL.Min.HV.WIM
    4,722,734,367 WIN81UX64EVAL.Min.WIM
    4,278,679,489 WIN81UX86EVAL.Full.HV.WIM
    4,277,099,032 WIN81UX86EVAL.Full.WIM
    3,648,938,088 WIN81UX86EVAL.Min.HV.WIM
    3,650,404,303 WIN81UX86EVAL.Min.WIM
    40 File(s) 172,408,546,058 bytes

    Post Processing

    I have scripts to merge similar install wims together to save space. This is similar to what Microsoft does with the Windows Release DVD’s, putting multiple SKU’s in the same *.wim file.

    4,298,516,365 WIN10STPX64.SRV.wim
    4,053,529,276 WIN10TPX64.ENT.wim
    3,138,798,185 WIN10TPX86.ENT.wim
    6,750,236,116 WIN2008R2SP1.wim
    5,292,634,524 WIN2012R2U.wim
    6,785,580,325 WIN7SP1X64EVAL.wim
    5,080,754,294 WIN7SP1X86EVAL.wim
    6,067,072,626 WIN81UX64EVAL.wim
    4,684,309,077 WIN81UX86EVAL.wim
    9 File(s) 46,151,430,788 bytes

    Additionally, I tried out Johan’s Beyond Zip method to shrink files down even more…

    23,190,306,816 CapturePackage.vhdx

    From 160GB down to 21.6GB, an savings of about 87% Wow!

    Finally, I have other scripts to convert the *.wim images to *.vhdx files for easy import into Hyper-V or Azure. See my last post on persistalldeviceinstalls


    As a service, I’ve been thinking of uploading my updated/patched images for these Operating Systems (and more) to a public internet file sharing site like my OneDrive for Business account. Rebuilding everything from scratch every Patch Tuesday. One drive for business has 1TB for use, I could share the images, how cool would that be?

    First glitch is that OneDrive for Business still has the 2GB file limitation, so that would require splitting the files up into 2047MB chunks and reassembling later.

    However, my biggest problem right now is my ISP connection. Today, I was averaging about 11.14Mbps upload speed to OneDrive. To upload 42GB of Wim files to OneDrive for Business would take more than 8 hours, which is more time than it took to build the images in the first place. That combined with my ISP’s data caps, makes sharing this from my current office cost prohibitive.


    Let me know if you are interested in setting up your own imaging factory environment. I’ve already done this for a large Video Chipset Mfg. And I can customize for your needs.


    PersistAllDeviceInstalls in Hyper-V Environments

    I’ve been creating some images for virtual machine environments.

    One of the goals of sysprep is to take all the elements that make an operating system specific to a machine, and make it generic for other machines. However if you know that the hardware is the same, you can tell Sysprep not to strip out the installed device drivers and keep them for the next machine.

    There are two ways to persist the devices and drivers when calling sysprep. If you are using Windows 8 or greater, you can add the /Mode:VM switch to the end of the sysprep call. However if you want the process to work in Windows 7 or Windows Server 2008 R2, you need to put the PersistAllDeviceInstalls element in an unattend.xml file and pass that through to sysprep.

    I created an unattend.xml file and placed it in my MDT Litetouch deployment share under the Tools directory.

    This particular unattend.xml file is crafted to work for both x86 and x64 platforms.

    <?xml version="1.0" encoding="utf-8"?>
     <settings pass="generalize">

    Within MDT LiteTouch I then can then set my CustomSettings.ini file to:



    After building out some of my virtual machines, I decided to run some performance tests against the images that got the PersistAllDeviceInstalls, and those that did not.

    I have a script that will convert a *.wim to a *.vhdx file, and inject a custom unattend.xml file. Import the *.vhdx file into a virtual machine and start up.

    For the image that was given PersistAllDeviceInstalls, it took 1 minute 20 seconds from the start of the virtual machine to the logon prompt.

    For the normal image without PersistAllDeviceInstalls, it took about 3 minutes from the start of the virtual machine to the logon prompt.

    That cut our install time down by almost HALF! Pretty cool!


    Next up, playing around with the VDI optimization scripts from Jeff and Carl


    My Server of Choice for 2014

    I posted some server specs today for one of my servers (yes I have more than one), and it got some attention. Really it’s not my best server.

    My reference server of choice this year is my SuperMicro box:


    * SUPERMICRO SYS-5038D-I Mid-Tower Server
    * 32GB Crucial 240-Pin DDR3 SDRAM ECC Buffered Ram
    * Intel Intel Xeon E3-1270V3 Haswell 3.5GHz
    * Seagate Barracuda ST2000DM001 2TB 7200 RPM
    * (2x) SAMSUNG 840 EVO 250GB SATA Drives

    I load it up with Windows Server 2012 R2 Server (eval) for testing, and it runs like a dream!

    I use 1 SSD drive for the OS, and the other for holding most of my virtual machines.

    Right now I have about 13-15 Virtual Machines up and running with the Windows 8.1 Enterprise Management Suite. No Problem! https://connect.microsoft.com/pocjumpstart/program8614


    And it’s only using about 55% of the available memory!

    Whole package should be less than $1500 on Newegg.

    Do you have a better configuration for hosting 10-15 Virtual Machines? let me know!

    Update: Forgot to mention my best server:

    The best server I ever had was at Microsoft when I worked in the extended “System Center” group

    HP Z800
    * 96GB of ECC Ram
    * (2x) Intel Xeon E5640 (if I recall) processors (each with 4 cores)
    * (4x) 300GB Seagate 15k SAS drives ( yes 15000 RPM’s )

    The most obscene part was that I had (TWO) of these machines. I will miss them. :^(


    Together they would cost about as much as I paid for my last car.

    Checking for tablets in MDT

    Quick Post:

    How do you test for tablets in MDT?

    Create a new step in your Task Sequence, like “Set Task Sequence Variable” –> IsTablet = True

    Then, in the “Options” tab, add a new “WMI Query” with the following:
    (One Line)

    SELECT * FROM Win32_ComputerSystem 
    WHERE PCSystemType = 2 and PCSystemTypeEx = 8

    This condition appears to correctly identify tablets vs non-tablets. My Lenovo W530 (not tablet), my Surface Pro (IsTablet), and my Dell Venue 8 Pro (is Tablet), and a Virtual Machine (not tablet).

    Hopefully Microsoft will update their documentation, PCSystemTypeEx does not appear in the standard MSDN documentation.