Thursday, 23 May 2013

Duplicate SIDs with deployed images \ Sysprep error

Had a quick but interesting issue this week with sysprep in our vCloud environment.

A new windows customized image had been created by one of the engineers, by deploying the standard Windows image and adding some basic software. He then created an image of this by adding it to the ‘Catalog’.

This VM was deployed several times, and the developers started using their VMs. They were getting weird issues though, which  (google?) led them to suspect that all the VMs in the vApp had the same computer SID.

I checked with psgetsid (http://live.sysinternals.com/psgetsid) and they were right!

“No problem” I thought, “the image was probably added to the Catalog as an exact backup, instead of a deployable image. I’ll just create a new SID”.

I powered off the VM in the vCloud console and ticked “Change SID” under Guest Customisation, then chose “Power on and force recustomisation”.

However this didn’t reset the SID!

Next I tried using ‘good old’ sysprep (newsid.exe is now very frowned-upon and not available from Microsoft) selecting “generalise” – and got the below error;

“A fatal error occurred while trying to sysprep the machine”

Checking the log file \windows\system32\sysprep\panther\setuperr.txt showed up an interesting message;

“Failure occurred while executing c:\windows\system32\slc.dll,SLRearmWindows”

This made me think that maybe the maximum number of rearms (which I knew was 3) had been reached?

I leveraged a wider knowledge base (i.e. googled) to find out how to determine the rearm value – this led me to run “slmgr.vbs –dlv”, and the output “rearms remaining = 0”.

After that I realised that I needed to reset the rearm value before sysprep (or vCloud’s “change sid” mechanism”) would work – google offered these instructions;

  • Change this registry key’s value to 7;

HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\SysprepStatus\GeneralizationState\

  • Start -> Run : msdtc -uninstall (wait few seconds)
  • Start -> Run : msdtc -install (wait few seconds)
  • Restart the machine

This fixed it!

Lesson – unless you have just installed Windows ‘fresh’, I recommend running “slmgr.vbs –dlv” before imaging a windows VM, and ensuring the remaining arm value is not 0. If it is, the deployed VMs will have the same SID!

Friday, 3 May 2013

IF statement and error handling with Get-winevent


Today I had to come up with a way of looking for a certain eventID in the event logs of our VDI estate, using get-winevent.
I had a few challenges which I managed to work around;
 
Challenge 1
When a given PC had multiple results, referencing the first record as $logonevents[0] was fine.
When a given PC had only one result, referencing the first (only) record as $logonevents[0] caused an error, as it wanted to be referenced as $logonevents.
 
Short of forcing the datatype into an array (which I couldn’t work out how to do and wasn’t sure would do the trick), I used an IF statement to check if $logonevents[0] existed, and use $logonevents if it didn’t;
if ($logonevents.timecreated) {$info.lastlogin = $logonevents.timecreated} else {$info.lastlogin = $logonevents[0].timecreated}
 
Challenge 2
My script didn’t provide a value for “last logon event” if there wasn’t one to find, but of course this value was also blank if the query failed (i.e. the VM was off or not working correctly).
I wanted a way to set the result to “None found” if the error was “Get-WinEvent : No events were found that match the specified selection criteria.” – I had 90% of the thinking for this but needed my ex-colleague and powershell guru Stephen Spike to force me to look at it a bit harder. The resulting code was;
 
#resets $error variable to nothing
$error.clear()
#looks for event
$logonevents = Get-WinEvent -computername $hostname -FilterHashtable @{logname="system"; id="7001"; providername="microsoft-windows-winlogon"}
#sets result to “None found” if appropriate
if ("$Error[0]".Contains("No events were found")) {$info.lastlogin = "No logon events found"}