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: http://1drv.ms/1u41Yj2
How-To
The Boot Image
The boot image must have support for PowerShell and you can get that by adding .NET and PowerShell
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
/mike
Categories: ConfigMgr, Lite Touch, MDT, OSD, Zero Touch
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?
BillsReturnValue=#RunningPSCommand()#
The Execution is really just a VBScript Shelling out to PowerShell doing something and returning a Value
Yes, it could be anything as long as you in this case add the BillsReturnValue as a property
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)
Executor.StdIn.Close
RunningPSCommand = Executor.StdOut.ReadAll
oLogging.CreateEntry “UserExit: RunningPSCommand is ” & RunningPSCommand, LogTypeInfo
oLogging.CreateEntry “UserExit: Departing…”, LogTypeInfo
End Function
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
$hostname
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, “”)