Here’s the scenario: a machine just came back in from the field and it needs a reload. You kick off OSD, check your email for a few seconds, look back up, and you see a message that OSD has failed.
You’ve seen this before. You check the logs to be sure, but you already know what it is. The TPM needs to be cleared.
The fix is easy enough–the machine is rebooted, the TPM is cleared, and OSD kicks off again–this time completing successfully. Unfortunately this is a time-consuming process. Let’s automate it!
I want to build a solution that tells the OSD technician that the TPM isn’t cleared, and that everything’s going to be taken care of for them. It should be a non-event (or as close as possible) for them.
This solution uses a couple components:
- UI++ (Already in use to collect information about how the machine should be configured, I also use it to determine the TPM ownership status)
- Invoke-TpmPhysicalPresenceRequest.ps1 (The script which performs the TPM operations)
I have this bit of code at the end of my UI++ XML file:
Target OU: %OSDDomainOUName%
This code runs a final preflight check validating that UEFI and Secure Boot are enabled. It also checks to make sure the TPM is available and activated.
I used to have a TPM ownership check here, but it’s been moved to the
TSVar line. If I detect that the TPM is owned the variable
XCMTpmNotice is populated with a little message. (This message adds the note about “you may need to restart OSD” because I had one older machine that cleared the TPM fine but didn’t resume OSD as expected. All my other machines worked OK. Perhaps it was just a fluke, but I leave it in here as a just-in-case.)
Finally, I have a “Ready to Build!” page that covers some quick details about the pending installation. If the TPM needs to be cleared, we’ll show our message at the end.
Task Sequence Logic
In our task sequence, we need just a couple steps (and a group) –
- Shortly after your UI++ step, add a new group (I named mine “TPM Preparation”). Add a condition that the group/step will run if Task Sequence Variable
- UI++ creates this variable for us, so you don’t need an MDT “Gather” step for this 🙂
- In your new group, add a Run PowerShell Script step (I named mine “TPM Physical Presence Request”).
- The Script Name is
Invoke-TpmPhysicalPresenceRequest.ps1and the Parameters I use are
- There are many different operations you can perform here. The whole list can be found at the Windows Dev Center.
- Set the PowerShell execution policy to
- The Script Name is
- Finally, add a Restart Computer step. It should run the boot image assigned to the task sequence after restart. I notify the user for 5 seconds with a message saying “A TPM presence operation has completed. The computer must now reboot.” just so technicians know why the computer is rebooting.
The End Result
Lights, Camera, Action! Now that we have all the pieces in place, here’s how OSD will flow:
- If the TPM is not owned: nothing changes!
- If the TPM is owned:
- A message is added to the end of our UI++ prompt letting technicians know a reboot is coming soon
- Our script runs, requesting that the physical presence of the TPM is changed (a log file is written out as well, and is shipped off if you collect logs at the end of OSD)
- The computer reboots to complete the TPM request
- OSD resumes from where it left off, and the machine builds successfully!
Now you’re automating for awesome!