The Deployment Bunny

OS Deployment, Virtualization, Microsoft based Infrastructure…

  • Archives

  • Meta

Archive for the ‘Lite Touch’ Category

OSD – Conditional disk layout (based on model)

Posted by Mikael Nystrom on February 10, 2017

A while back I did an online training for Penton Tech on Windows 10 OS Deployment. One of the attendees had a question (you know who you are).

– Is it possible to format and partition differently, based on what model I’m deploying?

Yes, you can have different disk layout/partitioning/volumes, based on anything, and that includes the model of the computer. I use this when deploying servers and client to have different partition schemas on virtual machines, I do not need to have the recovery partition in the end of the virtual disk, I don’t really “repair” a Virtual Machine the same way as i recover a physical machine, and you should not.

So, how do you do this?

Open your task sequence and modify the New Computer step like this.

The modified Task Sequence.

In this Task Sequence there are three different group’s, one for virtual machines, one for HP ZBook Studio G3 and the last one for everything else.

The modification starts under Validate, the first step after that sets DiskDone=NO, next step is the Group named Virtual Machine with the following conditions set:

Conditions on the group Virtual Machine.

The the group is executed if the Model is ‘Virtual Machine’ and DiskDone is NOT set to YES, so basically if it is a Virtual Machine it will partition/format according to the steps in the group. In the end of the group it will set DiskDone to YES, that way we know the disks are done and we can use that to prevent the following partitioning steps from running. Let us check the next step:

Conditions on the group HP ZBook Studio G3.

This step is the same as the step for Virtual Machine with one difference, in this case it only runs when the Model is a HP ZBook Studio G3. Let us check the last step:

Conditions on the group All others.

The last groups executes on any device, as long as DiskDone is NOT set to YES.

The Result.

Here is the result when running this in a Virtual Machine:


Here is the result when running this on a HP:


Here is a plain vanilla install:


Have fun!


Posted in Lite Touch, MDT, OS Deployment, OSD | Tagged: , , , | Leave a Comment »

OSD – Add information to the Computer during OSD using a Custom Tattoo Step

Posted by Mikael Nystrom on December 2, 2016

When using an MDT (integrated in ConfigMgr or standalone) there is a step called Tattoo, this step will write information to the registry as well as to the WMI repository.

Let us see what it looks by default:

Get-WMIObject –Class Microsoft_BDD_Info


Get-Item -Path ‘HKLM:\SOFTWARE\Microsoft\Deployment 4’


Cool, but I need my own stuff?

We have done this for various  reasons and many customers, it could be used for making sure the computer ends up in certain ConfigMgr Collections, or that applications behave in a certain way, or that the asset management tools does the job differently, or that the correct support team can know what the computer was configured for, or what task sequence that was used, or…. As you see the are some valid reasons for this, no doubt.

The question is of course, should you modify the existing ZTITatto.wsf and corresponding .MOF file?, No, you should not do that, instead you should create new files and use them instead.

So, here is the download :

To make the work in a task sequence you need to add the files to you Scripts folder, update the CustomSettings.ini if you are using Custom Properties and add a step in the Task Sequence.

Here is a sample of CustomSettings.ini


I have added 4 new properties, added them to a MacAddress, so first step is to verify that the ZTIGather process reads this correct, let us verify this by running:

cscript \\redepl01\mdtproduction$\Scripts\ZTIGather.wsf /inifile:c:\Temp\CustomSettings.ini

Result after running the following command to perform the inventory.

Now, lets run the custom tattoo script:

cscript \\redepl01\mdtproduction$\Scripts\ViaMonstraTatoo.wsf

That looks great!

Now, let us verify that we get the correct data from WMI and Registry:

First, get the WMI repository:

Get-WmiObject -Class ViaMonstra_Info

The WMI repository was updated.

Let us check the Registry:

Get-Item -Path ‘HKLM:\SOFTWARE\ViaMonstra\OSD’

The Registry was updated.

At LabCenter

The Customer LabCenter deploys computer for hands-on labs and they wanted each computer to be tattooed with information regarding the LAB and one thing they use it for is to be able to display the information directly in the screen using BGinfo, but they also use it for other purposes. BGInfo reads the Registry values, or WMI


How to change my own stuff then?

Download the files from: and edit the scripts, (.wsf and .mof) by replacing the values that are in use, like

  • ViaMonstra
  • ViaRole
  • ViaClass
  • ViaOwner
  • ViaTag

Save, and verify


Posted in ConfigMgr, Lite Touch, MDT, OSD, Zero Touch | Tagged: , , , , | 5 Comments »

OSD – Export drivers using a task sequence in Lite Touch and some PowerShell

Posted by Mikael Nystrom on May 18, 2016

Yesterday i did a demo of a Task Sequence I use to extract drivers from a computer that already have all drivers correctly installed, could be a system that I need to reinstall, or a new machine with fairly new drivers installed. The Task Sequence basically grabs information from the computer, such as Operating System, Architecture and Model or Modelalias, grabs the drivers and copy them to the deployment share. I can then import the drivers to a ConfigMgr package or use them in LiteTouch for deployment.

The script is fairly simple and easy to change to fit in your environment.

The Task Sequence

It contains 3 steps, a gather step to get the inventory of the machine correctly, a set finish action to avoid reboot if your are using finish action in customsettings.ini and the application that grabs the drivers. Since it is a application this task sequence works only when Windows is running, not in WinPE.

The Task Sequence.

The Application

The Script runs as an application, so you need to download the script to a folder and then import it as an application with following settings:

PowerShell.exe -ExecutionPolicy Bypass -File ExportDrivers.ps1

The Extract Drivers Application in Deployment Workbench.

The Script

The PowerShell script is a generic script I use a s “wrapper”, so it does have functions that is not really needed in this scenario, so it is possible to make it shorter if you for any reason want that. The script detects if it has been invoked from a task sequence or not, if it has, it will create a path based on deployment root, Operating System, Architecture and ModelAlias (If you don’t use ModelAlias UserExit, start to do that or change to Model in the script), otherwise it will export the drivers to C:\ExportedDrivers

The active part of the script looks like this:

The active part of the script.

Note that it will delete all drivers that begins with PRN. That is printer drivers and I usually do not want them.


 Install Wrapper 1.0
 Author: Mikael Nystrom 
Function Invoke-Exe{
    if($Arguments -eq "")
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
Function Get-OSVersion([ref]$OSv){
    $OS = Get-WmiObject -class Win32_OperatingSystem
    Switch -Regex ($OS.Version)
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 7 SP1"}
            {$OSv.value = "Windows Server 2008 R2"}
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8"}
            {$OSv.value = "Windows Server 2012"}
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8.1"}
            {$OSv.value = "Windows Server 2012 R2"}
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 10"}
            {$OSv.value = "Windows Server 2016"}
    DEFAULT { "Version not listed" }
Function Import-SMSTSENV{
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    if ($MDTIntegration -eq "YES"){
        $Logpath = $tsenv.Value("LogPath")
        $LogFile = $Logpath + "\" + "$ScriptName.log"
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$ScriptName.txt"
Function Start-Logging{
    start-transcript -path $LogFile -Force
Function Stop-Logging{
# Set Vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$LANG = (Get-Culture).Name
$OSV = $Null
#Try to Import SMSTSEnv
#Start Transcript Logging
. Start-Logging
#Detect current OS Version
. Get-OSVersion -osv ([ref]$osv) 
#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - OS Name: $OSV"
Write-Output "$ScriptName - OS Architecture: $ARCHITECTURE"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"
if($MDTIntegration -eq "YES"){
    $RootFolder = $tsenv.Value("Deployroot")
    $Arch = $tsenv.Value("Architecture")
    $Model = $tsenv.Value("ModelAlias")
    $Path = $RootFolder + "\Drivers\" + $OSV + "\" + $Arch + "\" + $Model
    $Path = "C:\ExportedDrivers"

Write-Output "$ScriptName - Driver export path: $Path"

#Export Drivers
Export-WindowsDriver -Destination $Path -Online -Verbose

#Get Printer Drivers
Get-ChildItem -Path $Path -Filter PRN* -Directory | Remove-Item -Force -Recurse

. Stop-Logging


Posted in Lite Touch, MDT, OS Deployment, OSD | Tagged: , , , | 6 Comments »

Inside the Task Sequence – Generate Application Migration File

Posted by Mikael Nystrom on March 3, 2016

Today during class we worked on Refresh and Replace scenarios. We touched based on a tiny step in the Task Sequence that is actually really cool. In the Task Sequence for Lite Touch (MDT Standalone) there is one step that does not exist in Zero Touch and that is the “Generate Application Migration File” step.

That little step will do a really smart thing, it will basically make sure that registered file types that can be open with an application will automatically be saved by USMT. It does that by grabbing all non-default file types and then check if there is a corresponding application that can open the file by examining the registry.

The “Generate Application Migration File” step.

So, what’s cool about that step?

If you open the file it states:

‘ // Purpose:   Generate an XML file for automatically capturing user data
‘ //            (documents) associated with installed applications.

And if you continue looking in the file you will see the flow, like this:

‘ Determine the version of USMT to use

‘ Create the file and write the standard header

‘ Get the list of all registry keys in HKCR

‘ Look at all file extensions to see if they map to an application

‘ Read the default value to see what app is associated with this extension

‘ See if the file can be opened (has a shell\open\command handler)

‘ Add it to the XML file

‘ Write the rest of the XML file

‘ Make sure the ZTIUserState.wsf script knows to use this script

‘ Cleanup and Exit

So, that is why you don’t need to spend a whole lot of time on USMT when doing Lite Touch.

Try It out

If you would like to see what it actually collects, you can run this interactive, that way it will generate a XML file. If you open it up you will then see what it would have migrated and not.

Open an elevated Command Prompt and execute the following:

cscript \\MDTSERVER\MDTSHARE\Scripts\ZTIAppXmlGen.wsf /capture

You will get an output that looks like this:


If you then open the XML (It is going to be located in C:\MININT\SMSOSD\OSDLOGS and named ZTIAppXmlGen.xml its going to look something like this



Posted in Lite Touch, MDT, OS Deployment, OSD | Tagged: , , , | 6 Comments »

Nice to Know – Yes, it is possible to copy items between to Task Sequences as well as copy items between 2 different deployment shares

Posted by Mikael Nystrom on November 11, 2014

This is NOT a new feature, I cant even remember how long this has been working, but this morning I saw a Tweet when someone was happy about the possibility to copy items between deployment shares in MDT, so for thoose that knows all this, you do not need to read more, for the rest of you.

Yes, you can copy items between Task Sequences

(it also works copy items within a Task Sequence)

This works in both MDT as well as in ConfigMgr.




Yes, you can copy items between Deployment Shares (Only for MDT, Lite Touch)

In this case I have 3 deployment shares in the Deployment Workbench and it is possible to copy all kind of items between these 3 deployment shares


Let us copy some application from one deployment share to another.

Select Application, right click and select Copy.


Browse to new location, right-click, select Paste.


The application has been copied to the new deployment share.



Posted in ConfigMgr, Lite Touch, MDT, OSD, Zero Touch | Tagged: , , , , , , | 3 Comments »

OSD – Using PowerShell Commands in UserExit VB script to extend the ZTIGather process during OSD

Posted by Mikael Nystrom on November 11, 2014

During todays session I realized that I have done a lot of OSD stuff, but never published it (shame on me), so time to work. First up is how to run PowerShell CommandLets inside a UserExit script. A UserExit script is an extension to the ZTIGather process, giving you the opportunity to extend the gather process with information that the Gather process does not cover. That has been possible for a long time, but VBscript is not really the easiest script language in the world, so I asked my self if it would be possible to use PowerShell inside the VBscript and of course it is!

The idea

The basic idea is to run the UserExit script from customsettings.ini as usual and then do a jump out into PowerShell, execute the PowerShell CMDLets, terminate and return the value into the VBscript, which then will be a value connected to a Custom Property in the gather process, which then can be consumed by customsettings.ini and/or the task sequence. you can download everything from here:


The Boot Image

The boot image must have support for PowerShell and you can get that by adding .NET and PowerShell

Lite Touch.

Zero Touch.

The Customsettings.ini file

The customsettings.ini file will direct ZTIGather to process the section called UserExits, which will execute the UserExit.vbs script, call the function called RunningPSCommand and return the value from that function into the property called PSCommand.

This is a sample of how the customsettings.ini file should look like to call the UserExit script.

The UserExit Script that runs PowerShell commands

The script is rather simple, basically the PowerShell command is a string, executed by PowerShell.exe and using Executor.StdIn.Close to close the window and then using Executor.StdOut.ReadAll to grab whatever you have in the window and put that in the RunningPSCommand, which then is returned back to the ZTIGather process as a value for the Property RunningPSCommand.


The result of running the ZTIGather


As you can see the PowerShell command was running and returned the value “Virtual Machine” and now the Property PSCommand is equal to Virtual Machine and can be used elsewhere in CustomSettings.ini or in the Task Sequence


Posted in ConfigMgr, Lite Touch, MDT, OSD, Zero Touch | Tagged: , , , , | 2 Comments »

PowerShell is King – Testing OS Deployment Web Services using PowerShell

Posted by Mikael Nystrom on November 2, 2014

Recently I was setting up Maik Kosters OS Deployment Web Services for a customer and I need to test them, sure, you can do that interactively directly by running them, but I wanted the “PowerShell” way to do it.

You can get the Web Services from Maik Koster here:

Testing a Web Services the Non PowerShell Way.

Browsing to the Web Services

Select the DoesComputerExists

Type in a value and Invoke.

Testing a Web Services the PowerShell Way.

Since PowerShell has the function built-in it is very much a no-brainer.

To connect and get all members from the Web Services execute this:

$ADWebS = New-WebServiceProxy -Uri http://MDT01/OSD/ad.asmx?WSDL
$ADWebS | Get-Member -Type Method

That will give you something like this back


To connect and get one member with some detail execute this:

$ADWebS = New-WebServiceProxy -Uri http://MDT01/OSD/ad.asmx?WSDL
$ADWebS | Get-Member -Name DoesComputerExist -Type Method | Format-List

That will give you something like this back


So, to test the DoesComputerExists with a value you can now execute the following:

$CompuerNameToTest = "MDT01"
$ADWebS = New-WebServiceProxy -Uri http://MDT01/OSD/ad.asmx?WSDL
$ComputerExistsInAd = $ADWebS.DoesComputerExist("$CompuerNameToTest")

Write-Host "The Computer $CompuerNameToTest exists in Active Directory: $ComputerExistsInAd"

So if the Computer Exists in Active Directory you should get something like this back



Posted in Lite Touch, MDT, OS Deployment, Zero Touch | Tagged: , , , , , , | Leave a Comment »

Nice to Know–Presenting applications in the MDT Wizard based on location

Posted by Mikael Nystrom on July 8, 2014

A friend (You know how you are…) asked me today “I need to have different application bundles in the MDT Wizard based on location, any ideas?” and since I cant refuse to help a friend, here is a solution.

Use WizardSelectionProfile, Selection Profile and Default Gateway

So here is a step by step, kind of.

Configure CustomSettings.ini

You need to add DefaultGateway to the customsettings.ini to match your environment. So it should look something like this:



WizardSelectionProfile=Wizard – HQ

WizardSelectionProfile=Wizard – BO

Create the Application folder

In the Deployment Workbench, create a Application folder, where you can store the applications that should be available at the BO site, something like this.


Create your WizardSelectionProfile’s

In the Deployment Workbench, Advanced Settings, Selection Profiles – Create a Selection Profile called “Wizard – HQ”. It should contain everything that should be selectable at the HQ site. In this case the folder is not available at HQ.


In the Deployment Workbench, Advanced Settings, Selection Profiles – Create a Selection Profile called “Wizard – BO”. It should contain everything that should be selectable at the BO site. In this case all folders are available.


Test and verify.

That should be it, so the net result would be something like this:

Running the Wizard at the BO

Apps at the BO

and running at HQ will give you this.

Apps at the HQ


Posted in Lite Touch, MDT | Tagged: , | 4 Comments »

Nice to Know–Combine multiple application for multiple OS versions into one Bundle

Posted by Mikael Nystrom on June 18, 2014

A customer asked me:

“Mike, I’m deploying Windows 7 and Windows 8.1 and in some cases there is different versions of applications for different versions of the OS, but I would like to use Mandatory Applications in customsettings.ini based that is tied to model?”

That is a scenario that is rather easy to fix, however it can be fix in many different ways. Scripting is one, rerunning the gather step and use conditions based on other way, using OSVersionNumber is another. It could also be the situation that you for a reason is running Windows 7 x86 and Windows 8.1 x64 as your two different operating system and therefor you have different applications, but you would like to be able to have only “one” application. That way you can still use rules to deploy the application or you would make it easier for the technician that performs the deployment of the client. But here is one other trick:

Using Bundles with conditions

Let us assume that you are deploying Windows 7 and Windows 8.1 to a certain hardware model and that hardware requires a certain software and that the software comes in two different versions then you can do the following:

  • Import the Windows 7 and Windows 8 application.

    My two applications imported into Deployment Workbench.

  • Set the conditions for each application

    Conditions for the Windows 7 x86 application.

    Conditions for the Windows 8.1 x64 application.

  • Hide the Applications

    The “Install – Software for Model X – Windows 8.1 x64” has been hidden, repeat for the Windows 7 x86 application.

  • Create a bundle application
  • Add the both applications as dependences.

    Both applications have been added to the bundle.

If you install the bundle only one of the applications will be installed, since the dependences have conditions that does not overlap.

Using Customsettings.ini and MandatoryApplications to install each application for the correct operating system.

If you modify the rules in LiteTouch (customsettings.ini) you can now based on model use the bundle GUID instead of having to use two applications

Using MandatoryApplications001 with the GUID from the Bundle and installing it based on Model.


Posted in Deployment, Lite Touch, MDT | Tagged: | 2 Comments »

OSD–Using ZTISendMail to send email in a LTI/ZTI task sequence

Posted by Mikael Nystrom on June 13, 2014

Long time ago I had a need to send email an email in the end of the task sequence to notify the technician that the OS deployment was done, therefore creating a script which then ended up as a blog post at Deployment Research about two years ago. This week I’m running a Mastering Windows 7 and 8.1 OS Deployment using Lite Touch and Zero Touch in Minnesota and there where some requests on the subject so I decided to create a new version of the script and this time it is a PowerShell script instead. One of the request was to be able to send and email to the administrator that does the deployment (in Lite Touch) using the login name, so that need to to be taken under considerations to.

The script is tested in MDT 2013 but should work perfect in MDT 2012 Update 1 as well and it works when deploying Windows 8 and above.

Lite Touch

First you need to download the script and sample customsettings.ini  from here and store the PowerShell it in the MDT Scripts folder.

Option Number One: Using the UserID directly

Update the CustomSettings like this. (you can copy and paste from the sample customsettings.ini files)

The name used to login to the LTI Wizard is defined as UserID and that is then used as a part of the email address to send it to.


Option Number Two: Using the UserID with translation.

In this case we create a section for every user account that should have an email an can logon. As an example, if you login as Administrator (don’t use that account!) an email would be sent to, but you can have any other setting for that userID if you liketo.

Update the CustomSettings like this. (you can copy and paste from the sample customsettings.ini files)


Add a step in the TaskSequence.


Zero Touch

First you need to download the script and sample customsettings.ini  from here and store the PowerShell it in the MDT Package Scripts folder.

In the ZTI we don’t really have a UserID and therefore we just send the email to a predefined email address and cc to an other.

Update the CustomSettings like this. (you can copy and paste from the sample customsettings.ini files)


Add a step in the Task Sequence like this.


Update the settings package and the MDT Package.

If you need a SMTP server to test against, read this



Posted in ConfigMgr, Deployment, Lite Touch, MDT, OS Deployment, OSD, SCCM, Zero Touch | Tagged: , , , , | 21 Comments »