PowerShell Form Input Field; GUI

email me

From our previous form example, we learned that GUI components can be created using PowerShell. Now, we add an input field, perform some logic on the input, and center our form on the screen.

What the form looks like

The pop up with data

The pop up without data

 

The Code

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$Form1 = New-Object System.Windows.Forms.Form
$Form1.Text = "Data Form"
$Form1.Size = New-Object System.Drawing.Size(300,200)
$Form1.StartPosition = "CenterScreen"
# Icon
$Form1.Icon = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$Form1.AcceptButton = $OKButton
$Form1.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$Form1.CancelButton = $CancelButton
$Form1.Controls.Add($CancelButton)

$Label1 = New-Object System.Windows.Forms.Label
$Label1.Location = New-Object System.Drawing.Point(10,20)
$Label1.Size = New-Object System.Drawing.Size(280,20)
$Label1.Text = "Enter data here:"
$Form1.Controls.Add($Label1)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
$Form1.Controls.Add($textBox)

$Form1.Topmost = $True

$Form1.Add_Shown({$textBox.Select()})
$result = $Form1.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $textBox.Text
$x

if ($x -eq "") {[System.Windows.Forms.MessageBox]::Show("You didn't enter anything!", "Test Title")}
else {[System.Windows.Forms.MessageBox]::Show($x, "Test Title")}}

PowerShell Form; GUI

email me

For all those that would like to extend their PowerShell scripting beyond the console and beyond just text-based scripts, you can add GUI components, such as things like buttons, drop down lists, radio buttons, etc. And, hey, no expensive software necessary; I did this in Notepad++.

In the example below, I have created a Form using only PowerShell, with an action behind the button.

What the form looks like

What the pop up looks like

 

The Code


function CreateForm {

# Import Assemblies
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null

$Form1 = New-Object System.Windows.Forms.Form
$Button1 = New-Object System.Windows.Forms.Button
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState

$handler_Button1_Click=
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.MessageBox]::Show("Pop up." , "Test Title")

# Example with Yes and No
# [System.Windows.Forms.MessageBox]::Show("We are proceeding with next step." , "Status" , 4)
# $OUTPUT= [System.Windows.Forms.MessageBox]::Show("We are proceeding with next step." , "Status" , 4)
# if ($OUTPUT -eq "YES" )
# {
# ..do something
#
# }
# else
# {
# ..do something else
# }

# Types of message boxes
# 0: OK
# 1: OK Cancel
# 2: Abort Retry Ignore
# 3: Yes No Cancel
# 4: Yes No
# 5: Retry Cancel
}

$OnLoadForm_StateCorrection=
{
$Form1.WindowState = $InitialFormWindowState
}
# Form Code
$Form1.Text = "Test Form Text 1"
$Form1.Name = "Test Form Text 2"

$Form1.MaximizeBox = $false #lock form
$Form1.FormBorderStyle = 'Fixed3D'
# None,FixedDialog,FixedSingle,FixedToolWindow,Sizable,SizableToolWindow

# Icon
$Form1.Icon = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)
#$NotifyIcon.Icon = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)

$Form1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 265
$System_Drawing_Size.Height = 55
$Form1.ClientSize = $System_Drawing_Size

$Button1.TabIndex = 0
$Button1.Name = "Button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 240
$System_Drawing_Size.Height = 23
$Button1.Size = $System_Drawing_Size
$Button1.UseVisualStyleBackColor = $True

$Button1.Text = "Button Text Here"

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 13
$Button1.Location = $System_Drawing_Point
$Button1.DataBindings.DefaultDataSourceUpdateMode = 0
$Button1.add_Click($handler_Button1_Click)

$Form1.Controls.Add($Button1)

$InitialFormWindowState = $Form1.WindowState
$Form1.add_Load($OnLoadForm_StateCorrection)

# Show Form
$Form1.ShowDialog()| Out-Null

}

# Call Function
CreateForm

References

https://msdn.microsoft.com/en-us/library/system.windows.forms.form.formborderstyle%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

https://msdn.microsoft.com/en-us/library/hw8kes41(v=vs.110).aspx

PowerShell – Install Pester

email me

Pester provides a framework for running unit tests to execute and validate PowerShell commands from within PowerShell. Pester consists of a simple set of functions that expose a testing domain-specific language (DSL) for isolating, running, evaluating and reporting the results of PowerShell commands.

Pester tests can execute any command or script that is accessible to a Pester test file. This can include functions, cmdlets, modules and scripts. Pester can be run in ad-hoc style in a console or it can be integrated into the build scripts of a continuous integration (CI) system.

Pester also contains a powerful set of mocking functions in which tests mimic any command functionality within the tested PowerShell code.

You can download the latest Pester version from GitHub and copy it to a folder in $env:PSModulePath – but it’s more convenient to use a packaging solution like PSGet or Chocolatey.

Here is an example how you can install Chocolatey, a software management solution (in case you haven’t done it yet – line 1), and then install Pester (line 2).

iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
choco install pester -y

 

Notes

Pester Framework

Chocolatey – Software Management for Windows

PowerShellGet Module


Upgrade Pester

Install-Module -Name Pester -Force

 

Upgrade Chocolately

choco upgrade all -y

PowerShell – Write to Computer Object Description

email me

This is how you write to the description field for a computer object in Active Directory.

Remember, set the Execution PolicySet-ExecutionPolicy RemoteSigned

Import-module ActiveDirectory
$strComputer = 'PC_Name1'
$strDescription = "The Description Here"
Set-ADComputer $strComputer -Description $strDescription

 

If you want to import data from a CSV

Import-module ActiveDirectory  
Import-CSV "C:\PowerShell\Data.csv" | % { 
$strComputer = $_.Computer 
$strDescription = $_.Description 
Set-ADComputer $strComputer -Description $strDescription
}

 

What the data.csv looks like

Computer,Description
PC_Name1,testing1
PC_Name2,testing2
PC_Name3,testing3

VBScript – Return IP and Gateway Addresses; Raw formats

email me

A simple way to return IP information is to use WMI.

On error resume next
'set computer name; uses local machine name
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration Where IPEnabled = True")
For Each objItem In colItems
  IPAddress = Join(objItem.IPAddress, ",")
  GatewayAddress = Join(objItem.GatewayAddress, ",")
  'output information
  MsgBox "IP Address = " & IPAddress & vbCrLf & "Gateway Address = " & GatewayAddress
Next

VBScript – Return Gateway Address; Site-Aware

email me

This script returns the user’s gateway IP address, locates address in a text file, which then ties it to a location code or name. This is great for making site-aware scripts and packages.

ON ERROR RESUME NEXT

CONST ForReading = 1 

DIM lineInput, IP_Address, workingLine, IPGateway, SiteLocation
DIM objFSO, objFile, objOutput, dataLine, RegCommand, objShell

SET objShell = CreateObject("Wscript.Shell")
SET objFSO = createobject("Scripting.FileSystemObject")

'SETS CURRENT DIRECTORY TO VARIABLE
strCurrentDirectory = objShell.CurrentDirectory

'CLEAR SESSION
dataLine = "" 

'READ FROM GATEWAYS FILE. 
'opens gateways file for reading
SET objFile = objFSO.openTextFile(strCurrentDirectory & "\Gateways.txt", ForReading) 
'Example of text file: gateway address,site code or name
'0.0.0.0,VPN
'11.11.11.254,991
'12.11.11.254,992
'13.11.11.254,Florida

'RETURN GATEWAY ADDRESS USING A FUNCTION
IP_Address = ReturnGateway()

'RETURN LOCATION NUMBER
DO UNTIL objFile.atEndOfStream 	
ON ERROR RESUME NEXT
	dataLine = objFile.readLine & vbCrLf
	IF inStr(dataLine, IP_Address) THEN
	   lineInput = Split(dataLine, ",")
	   workingLine = dataLine	   
	   IPGateway = lineInput(0)	   
	   SiteLocation = lineInput(1)     	   
	   EXIT DO
	 END IF	 
LOOP
'close file for reading
objFile.Close


'IMPORT LOCATION INTO REG KEY
'Location
IF SiteLocation = "" THEN  SiteLocation = "Unknown"
RegCommand = "reg add hkcu\SOFTWARE\MYINFO /v SiteLocation /t REG_SZ /d " & SiteLocation & " /f /reg:64"
objShell.Run RegCommand,0,TRUE'applies reg key

'IP FUNCTION - WILL RETURN GATEWAY ADDRESS
FUNCTION ReturnGateway()
  ON ERROR RESUME NEXT
  DIM ws : SET ws = CreateObject("WScript.Shell")
  DIM fso : SET fso = CreateObject("Scripting.FileSystemObject")
  DIM TmpFile : TmpFile = fso.GetSpecialFolder(2) & "/ip.txt"
  DIM gatewayLine, IP, ReturnIPAddress
  IF ws.Environment("SYSTEM")("OS") <> "" THEN     
    ws.run "%comspec% /c ipconfig > " & TmpFile, 0, True
  END IF
  WITH fso.GetFile(TmpFile).OpenAsTextStream
    DO WHILE NOT .AtEndOfStream
      gatewayLine = .ReadLine
      IF InStr(gatewayLine, "Default Gateway") <> 0 THEN  IP = Mid(gatewayLine, InStr(gatewayLine, ":") + 2)
	  IF IP  <> "" THEN  
	     ReturnGateway = IP
		 EXIT FUNCTION'forces exit upon finding first gateway
	  END IF
    Loop
    .Close
  End WITH
  IF IP <> "::" Then
    IF Asc(Right(IP, 1)) = 13 THEN  IP = Left(IP, Len(IP) - 1)
  END IF
  ReturnGateway = IP  
  fso.GetFile(TmpFile).Delete  
  SET fso = Nothing
  SET ws = Nothing
End Function

Wscript.Quit(0)

Copy Reg Keys from HKCU to HKLM

email me

I wrote this script to copy registry keys from a current user registry hive to the local machine registry hive. I was using this with desktop management software.

ON ERROR RESUME NEXT

CONST HKEY_CURRENT_USER   = &H80000001  
CONST HKEY_LOCAL_MACHINE  = &H80000002
CONST REG_SZ = 1
CONST REG_DWORD = 4
  
'USE LOCAL COMPUTER NAME
strComputer = "."
SET StdOut = WScript.StdOut  
  
'CONNECT TO REGISTRY
SET objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")  
  
'REG KEY IMPORT FROM HKCU TO HKLM
strKeySource = "SOFTWARE\MYINFO"''''FROM THE CURRENT USER HIVE
strKeyDestination = "SOFTWARE\MYINFO"''''TO THE LOCAL MACHINE HIVE
  
'CREATE THE DESTINATION KEY  
objRegistry.CreateKey HKEY_LOCAL_MACHINE,strKeyDestination
  
'ENUMERATE KEYS FROM CURRENT USER AND THEN APPLY VALUES TO HKLM
objRegistry.EnumValues HKEY_CURRENT_USER, strKeySource, arrValueNames, arrValueTypes
FOR i = LBound(arrValueNames) To UBound(arrValueNames)  
         objRegistry.GetStringValue HKEY_CURRENT_USER,strKeyDestination,arrValueNames(i),value
	 objRegistry.SetStringValue HKEY_LOCAL_MACHINE,strKeyDestination,arrValueNames(i),value
NEXT

WScript.Quit(0)

Write AD FIM Properties to Reg Keys; IP Range File.

email me

I created this to write Active Directory user properties to the registry, which would then been queried by desktop management software for reporting purposes.

This does have built-in site detection, so you may or may not need that. For me, I needed to determine a user’s site using a range of IP’s from a text file, as well as query FIM data from AD.

ON ERROR RESUME NEXT

CONST ForReading = 1

DIM Line_Input, StartIP_Input, EndIP_in, StartIP, PerfServIP, PrefServName, IPRange, OctetIncrement 
DIM  OctetCompare, IP_Address, objFSO, objFile, objOutput, workingData, IsMatchFound, ws, SiteName
DIM RegCommand1, RegCommand2, RegCommand3, RegCommand4, RegCommand5, RegCommand6
DIM RegCommand7, RegCommand8, RegCommand9

SET objShell = CreateObject("Wscript.Shell")

'SETS CURRENT DIRECTORY TO VARIABLE
strCurrentDirectory = objShell.CurrentDirectory

IsMatchFound = 0'set to False by default

SET objFSO = createobject("Scripting.FileSystemObject") 
'List containing IP ranges and site names
'example from text file: 11.80.00.1,11.80.40.254,11.80.40.60,MyFileServerName,Florida.
SET objFile = objFSO.openTextFile(strCurrentDirectory & "\AllSiteList.txt", ForReading) 
'used for testing
'example of output: Texas
SET objOutput = objFSO.CreateTextFile(strCurrentDirectory & "\site.txt")
workingData = ""

'RETURN IP ADDRESS USING A FUNCTION
IP_Address = ReturnIPAddress()

'RETURN SITE LOCATION
DO UNTIL objFile.atEndOfStream 
'READ LINE FROM FILE
workingData = objFile.readLine & vbCrLf

'SPLIT THE LINE INTO AN ARRAY
Line_Input = Split(workingData, ",")

'SPLIT THE STARTING IP INTO IT'S BASE OCTETS
StartIP_Input = Split(Line_Input(0), ".")

'SPLIT THE ENDING IP RANGE INTO IT'S BASE OCTETS
EndIP_in = Split(Line_Input(1), ".")

'USES THE STARTIP STRING AS THE FIRST OF TWO COMPARISONS TO FIND A MATCHING IP WITHIN THE RANGE
StartIP = StartIP_Input(0) & "." & StartIP_Input(1) & "." & StartIP_Input(2)

'PLACES SITE INFORMATION INTO VARIABLE
SiteName = LINE_INPUT(4)''''add the site location name

'CALCULATE THE NUMBER OF IP SUBNETS WE NEED TO INCREMENT THROUGH TO CHECK THE RANGE
IPRange = CINT(EndIP_in(2)) - CINT(StartIP_Input(2))

'INITIALIZE THE INCREMENT
OctetIncrement = CINT(StartIP_Input(2))

'COMPARE IP OCTETS WITH IP RANGES (YOU COULD ADD GATEWAYS AS WELL)
FOR i = 0 TO IPRange
IF InStr(IP_Address, StartIP) > 0 THEN
OctetCompare = Split(IP_Address, ".")
IF CINT(OctetCompare(2)) = OctetIncrement THEN
IsMatchFound = 1'found match 
'objOutput.Write SiteName'writes to file
'msgbox SiteName'displays in message box
RegCommand1 = "reg add hkcu\MYINFO /v SiteLocation /t REG_SZ /d " & SiteName & " /f /reg:64"
objOutput.Close
OctetIncrement = IPRange
i = IPRange
EXIT DO
END IF
END IF
'if not found, increment until found
OctetIncrement = OctetIncrement + 1
StartIP = StartIP_Input(0) & "." & StartIP_Input(1) & "." & CSTR(OctetIncrement) 
NEXT


LOOP 
objFile.Close


DIM objSysInfo,objUser,objShell,strUser
SET objSysInfo = CreateObject("ADSystemInfo")

'RETURN CURRENT USER
strUser = objSysInfo.UserName

'CREATE AD USER OBJECT
SET objUser = GetObject("LDAP://" & strUser)

'IMPORT PROPERTIES INTO REG KEYS
'Location
objShell.Run RegCommand1,0,true'applies reg key

'Display Name
RegCommand2 = "reg add hkcu\MYINFO /v DisplayName /t REG_SZ /d " & chr(34) & objUser.displayName & chr(34) & " /f /reg:64"
objShell.Run RegCommand2,0,true'applies reg key

'SAM Account Name 
RegCommand3 = "reg add hkcu\MYINFO /v AccountName /t REG_SZ /d " & chr(34) & objUser.sAMAccountName & chr(34) & " /f /reg:64"
objShell.Run RegCommand3,0,true'applies reg key

'Business Unit
RegCommand4 = "reg add hkcu\MYINFO /v BusinessUnit /t REG_SZ /d " & objUser.fimwpoBusinessUnit & " /f /reg:64"
objShell.Run RegCommand4,0,true'applies reg key

'Business Unit Description
RegCommand5 = "reg add hkcu\MYINFO /v BusinessUnitDescription /t REG_SZ /d " & chr(34) & objUser.fimwpoBusinessUnitDescription & chr(34) & " /f /reg:64"
objShell.Run RegCommand5,0,true'applies reg key

'Business Title
RegCommand6 = "reg add hkcu\MYINFO /v BusinessTitle /t REG_SZ /d " & chr(34) & objUser.fimwpoBusinessTitle & chr(34) & " /f /reg:64"
objShell.Run RegCommand6,0,true'applies reg key

'User email address
RegCommand7 = "reg add hkcu\MYINFO /v EmailAddress /t REG_SZ /d " & chr(34) & objUser.mail & chr(34) & " /f /reg:64"
objShell.Run RegCommand7,0,true'applies reg key

'Employee ID
RegCommand8 = "reg add hkcu\MYINFO /v EmployeeID /t REG_SZ /d " & chr(34) & objUser.employeeID & chr(34) & " /f /reg:64"
objShell.Run RegCommand8,0,true'applies reg key

'Department
RegCommand9 = "reg add hkcu\MYINFO /v Department /t REG_SZ /d " & chr(34) & objUser.department & chr(34) & " /f /reg:64"
objShell.Run RegCommand9,0,true'applies reg key


'IP FUNCTION - WILL RETURN CURRENT IP ADDRESS
FUNCTION ReturnIPAddress()
DIM ws : SET ws = CreateObject("WScript.Shell")
DIM fso : SET fso = CreateObject("Scripting.FileSystemObject")
DIM tempFile : tempFile = fso.GetSpecialFolder(2) & "/ip.txt"
DIM LineFromOutput, IP
IF ws.Environment("SYSTEM")("OS") = "" Then
ws.run "winipcfg /batch " & tempFile, 0, True
ELSE
ws.run "%comspec% /c ipconfig > " & tempFile, 0, True
END IF
WITH fso.GetFile(tempFile).OpenAsTextStream
DO WHILE NOT .AtEndOfStream
LineFromOutput = .ReadLine
IF InStr(LineFromOutput, "Address") <> 0 Then IP = Mid(LineFromOutput, InStr(LineFromOutput, ":") + 2)
Loop
.Close
End WITH
IF IP <> "" Then
IF Asc(Right(IP, 1)) = 13 Then IP = Left(IP, Len(IP) - 1)
END IF
ReturnIPAddress = IP
fso.GetFile(tempFile).Delete 
SET fso = Nothing
SET ws = Nothing
End Function

Could be used for LANDesk, SCCM, or other desktop management software to read the stored values in the registry.

Elevated Custom MDT Task Sequence

email me

This is an interesting way to launch a MDT process in an elevated manner. First, I did try using the built-in credentials option in the task sequence; that did not work for the particular thing I was trying to achieve.

What I wanted to do is have a client machine write back to the Active Directory computer description field (just some dynamic text). Note, the script I created did work on the client when manually executed using a MDT service account….but would not work correctly through the task sequence itself. Thus, to get around this problem, I employed the use of cpau (an elevation program) in the task sequence itself. See screenshot. Once I did that, the task sequence launched my script correctly and wrote back to the computer object description field.

Notes

A custom coded elevation tool could also be used. CPAU.exe is slowly losing functionality.

Common Data Types

email me

This is a C# console app I created in Visual Studio to demonstrate some common data types.

using System;

namespace TypeConversionApplication

{
class StringConversion
{
static void Main(string[] args)
{
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;
Console.WriteLine("int: " + i.ToString());
Console.WriteLine("float: " + f.ToString());
Console.WriteLine("double: " + d.ToString());
Console.WriteLine("boolean: " + b.ToString());
Console.ReadKey();
}
}
}

 

Data Types

int : An integer(eg, 3).
Can be a whole number between -2147483648 and 2147483647

float : A fractional(floating point) number(eg, 3.25907).
Can be a number between roughly 1.5 x 10^45 to 3.4 10^38, in floating point format.

String : A sequence of characters(eg, “Hello User 6555”)
(no specified maximum length)

boolean : A true/false value.
Can only contain either the value true or false.

 

Others

Data Type Range
byte 0 .. 255
sbyte -128 .. 127
short -32,768 .. 32,767
ushort 0 .. 65,535
int -2,147,483,648 .. 2,147,483,647
uint 0 .. 4,294,967,295
long -9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807
ulong 0 .. 18,446,744,073,709,551,615
float -3.402823e38 .. 3.402823e38
double -1.79769313486232e308 .. 1.79769313486232e308
decimal -79228162514264337593543950335 .. 79228162514264337593543950335
char A Unicode character.
string A string of Unicode characters.
bool True or False.
object An object.

 

Reference

http://www.tutorialspoint.com/csharp/csharp_data_types.htm

VBScript – Return AD Properties

email me

This is a script I put together that returns some specific user account properties from Active Directory.

Option Explicit

DIM objSysInfo,objUser,objShell,strUser

SET objSysInfo = CreateObject("ADSystemInfo")
SET objShell = CreateObject( "WScript.Shell" )

'RETURN CURRENT USER
strUser = objSysInfo.UserName

'CREATE AD USER OBJECT
SET objUser = GetObject("LDAP://" & strUser)

'TEST OUTPUT
msgbox objUser.displayName
msgbox objUser.sAMAccountName
msgbox objUser.fimwpoBusinessUnit
msgbox objUser.fimwpoBusinessUnitDescription
msgbox objUser.fimwpoBusinessTitle
msgbox objUser.mail
msgbox objUser.employeeID

'COULD WRITE TO REGISTRY HERE
'TO BE ADDED

'COULD WRITE DIRECTLY TO LD DB HERE
'TO BE ADDED

WScript.Quit(0)

MDT – Windows 10 Enable BitLocker

email me

Configure the Windows 10 task sequence to enable BitLocker

When configuring a task sequence to run any BitLocker tool, either directly or using a custom script, it is helpful if you also add some logic to detect whether the BIOS is already configured on the machine. In this task sequence, we are using a sample script (ZTICheckforTPM.wsf). In the following task sequence, there are five actions (pay attention to step 2):

(1) Check TPM Status. Runs the ZTICheckforTPM.wsf script to determine if TPM is enabled. Depending on the status, the script will set the TPMEnabled and TPMActivated properties to either true or false.

(2) Configure BIOS for TPM. Runs the vendor tools (in this case, HP, Dell, and Lenovo). To ensure this action is run only when necessary, add a condition so the action is run only when the TPM chip is not already activated. Use the properties from the ZTICheckforTPM.wsf.

Note

  • It is common for organizations wrapping these tools in scripts to get additional logging and error handling.

(3) Restart computer. Reboots the computer.

(4) Check TPM Status. Runs the ZTICheckforTPM.wsf script again.

(5) Enable BitLocker. Activates BitLocker.

 

So, what happens if this fails to work?

First, verify all aspects of the server setup are correct: Bitlocker How to Deploy Bitlocker  2  3  MDT.

Test again. If that still fails, you can create your own scripts to do the Bitlocker setup and management.

In the task sequence,

Add your own TPM enabler script

(1) May contain vendor specific tools to set BIOS PW (“C:\SetPW.exe” /npwdfile:”C:\password.bin”)

(2) Contains the Microsoft script to enable the TPM (“C:\enablebitlocker.vbs” /on:tpm /l:c:\bitlocker.log). Add Microsoft script into script folder on your MDT server. Add into task sequence as a Run Command.


Add a restart
Select a Restart from the task sequence options


Add your own Bitlocker enabler script

(1) C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Initialize-Tpm -AllowClear -AllowPhysicalPresence”

(2)  C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Initialize-Tpm”

(3) C:\windows\system32\manage-bde -protectors -add C: -tpm

(4) C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Enable-BitLocker -MountPoint “C:” -EncryptionMethod Aes256 -UsedSpaceOnly -RecoveryPasswordProtector”

If you want to import Bitlocker recovery info into AD,
(1) for /f “skip=4 tokens=2 delims=:” %%g in (‘”C:\Windows\System32\manage-bde.exe -protectors -get c:”‘) do set MyVar=%%g

(2) C:\Windows\System32\manage-bde.exe -protectors -adbackup c: -id%MyVar%