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

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


5 replies »

  1. This is cool…however for clarity…I’m already pretty sure of this “PSCommand” is just a standard TS Variable so it could be any name at all? Yes?


    The Execution is really just a VBScript Shelling out to PowerShell doing something and returning a Value

  2. Ugh. Finally figured out how run a powershell script, finding the right execution policy and script directory. I thought there would be a “scriptroot” environment variable.

    Function RunningPSCommand()
    oLogging.CreateEntry “UserExit: Running function RunningPSCommand”, LogTypeInfo
    Dim sPSCommand
    Dim sCmd
    Dim sScriptPath
    Dim sScriptFolderPath

    Set ObjShell = CreateObject(“WScript.Shell”)

    deployroot = oEnvironment.Item(“deployroot”)
    sCmd = “powershell.exe -noprofile -executionpolicy bypass -file ” & deployroot & “\scripts\script.ps1”
    oLogging.CreateEntry “UserExit: Command to run ” & sCmd, LogTypeInfo

    Set Executor = ObjShell.Exec(sCmd)
    RunningPSCommand = Executor.StdOut.ReadAll

    oLogging.CreateEntry “UserExit: RunningPSCommand is ” & RunningPSCommand, LogTypeInfo
    oLogging.CreateEntry “UserExit: Departing…”, LogTypeInfo
    End Function

  3. This is a little convoluted, but this powershell script does nslookup on the ipaddress and sets the computername to the result. I copied nslookup.exe to the deployment share.

    # script.ps1
    $ip = (-split (ipconfig | where { $_ -match ‘ipv4 address’ } ))[-1] # -1 is last element of array
    $hostname = (-split (& $env:deployroot\nslookup.exe $ip | select -index 3))[-1]
    $hostname = ($hostname -replace ‘\..*’).toupper() # hostname in uppercase with no subdomain
    if (-not $hostname) { $hostname = $ip -replace ‘\.’,’-‘ } # if fail, return ipaddress with dashes

  4. There’s actually a huge flaw in that vbscript code that runs powershell. Executor.Stdout.Readall returns a string with a literal carraige return at the end, and that gets stored in an MDT variable. If that were used as the computername in the unatend.xml file, Windows setup would fail. At the end, this would fix it:

    RunningPSCommand = Replace(RunningPSCommand, vbCrLf, “”)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.