The undocumented SetupCl.exe
utility, which is part of the Windows setup tooling that cleans up the system image as one step of the generalization process that runs when the new Windows system boots, normally does such things as generate new disk identifiers, fix up reparse points and replace references to the default system root (usually X:\
) with whatever is appropriate for your target system (usually C:\
), in all registry keys and possibly configuration files. This utility is invoked by the Windows setup process on first boot, and is controlled by the SYSTEM\Setup\SetupCl\PendingRequest
registry key. The DWORD value OperationFlags
in this key is a bit field that specifies which transformations the utility will perform.
In addition to the transformations mentioned above, SetupCl
can replace an existing machine SID with a new one. This transformation is requested by setting bit 2 (0x4
) in OperationFlags
in the SYSTEM\Setup\SetupCl\PendingRequest
key. Two optional binary values SidAccountDomainOld
and SidAccountDomainNew
in the same key supply the source and target machine SIDs. If the source SID is omitted, SetupCl
takes it from the running system. If the target SID is omitted, SetupCl
generates a new one. These values contain the machine SID in binary form and are 24 bytes long (the 8-byte fixed length header and 4 32-bit sub-authorities). To make SetupCl
assign a specific machine SID, set bit 2 in OperationFlags
and create the SidAccountDomainNew
value containing the SID.
There are a couple of complications with this procedure:
It works on images prepared by sysprep /generalize
, but fails on Windows images freshly deployed by DISM or Expand-WindowsImage
cmdlet. Fresh images are also in a generalized state, with a pending SetupCl
request set up in the SYSTEM
hive to run on first boot, but this request does not have bit 2 set. Setting it in the offline image results in an image that fails to deploy. To work around this limitation, one has to perform an extra round of generalize/specialize. One way to do this is with chained unattend files: the first unattend file specifies a single Microsoft-Windows-Setup-Shell/FirstLogonCommands
command to execute sysprep /generalize /oobe /unattend:<second unattend file> /shutdown
.
Adding the SidAccountDomainNew
value online, before or after sysprep /generalize
, does not work, most likely because sysprep
schedules some final steps to be performed at system shutdown. Mount the offline Windows image after sysprep /generalize
finishes and the system shuts down, load the SYSTEM
hive, and add it at that point.
sysprep /generalize
fails if there is a pending reboot from installing software. Reboot the system before generalizing, or perform the extra generalize/specialize step before installing software to the image.