Voting keypads and bluescreens

One of the more interesting problems I was given at RAC is the issue of Turning Point voting keypads causing computers to blue screen.

For those who don’t know, the keypads allow things like voting by an audience using little keypads.  The signal is sent wirelessly to a USB receiver plugged into a computer.  Following the roll-out of RAC’s new Managed Operating Environment (MOE), plugging in one of the receivers would cause the computer to blue screen.  I was tasked with fixing it.

The initial route I followed was to examine the blue screen dump files using the Windows Debugging tools.  Doing so pointed to the drivers for the receiver being the cause and after googling a bit, there did seem to be some supporting evidence that these style of devices didn’t play well on Windows 7.

The change in troubleshooting approach came from the fact that, if the device was plugged into a freshly un-boxed HP machine which hadn’t been re-imaged yet (that is, it was running the manufacturer image and drivers), it would work.  There was a date difference between the drivers, with the ones in the MOE being slightly older.

Going on the theory that one of the older drivers in the MOE was causing the blue screens in some way, I downloaded the latest drivers from HP and applied them one at a time, testing the receiver each time.  Eventually I hit a point where the blue screens stopped and the culprit was the fingerprint scanner’s driver.

I reproduced the fix on a few other machines with success, so there must’ve been some incompatibility between the MOE’s finger print scanner driver and the keypad receiver.

Getting serious about a home lab – Part 2 (The hardware arrives)

With my new lab, I ended up deciding on a two server approach to address the issues mentioned in part one – one server will purely be the “brains”, performing the virtualisation functions, while the other server will provide storage.  In line with that, I ended up getting the following parts:

Virtualisation Server

  • 1 x Intel i7 3930K
  • 1 x Intel DX79SI motherboard
  • 8 x Kingston 8GB RAM (64GB total)
  • 1 x Corsair 120GB SSD
  • 2 x Intel gigabit NICs
  • 1 x Fractal Design Define XL case

Storage Server

  • 1 x Intel i7 3820
  • 1 x Gigabyte GA-X79-UD3 motherboard
  • 1 x Kingston 8GB RAM
  • 1 x Corsair 180GB SSD
  • 9 x Hitachi Ultrastar A7K3000 (2TB) HDD
  • 2 x Intel gigabit NICs
  • 1 x Fractcal Design Define XL case

I also bought a Netgear gigabit switch and put an Adaptec RAID controller into the storage server.  The 2 additional NICs in each server are for iSCSI traffic with their own IP range.

Getting serious about a home lab – Part 1 (The high concept)

Back in November I posted about the implementation of what was essentially version 2 of my home lab on the VMWare ESX platform, moving an i3 with 8GB of RAM to an i7 with 16GB and proper storage on a RAID controller.  The problem with that environment is it only really served the needs of my “production” virtual machines and hasn’t allowed me to expand further as about 14GB of the 16GB total is allocated out (even with the VMs being under-provisioned in terms of RAM).

Running in parallel with this is my desire to get some traction on my certifications and having a good virtualisation platform that I can quickly set-up lab environments on is an important part of this.  Thus begins the project, to implement version 3 of my home lab environment.  The broad hardware bits of the “high concept” are:

  • Capable of supporting my current virtual environment with better performance (essentially meaning I can allocate more correct amounts of RAM to my current VMs)
  • Capable of scaling up to support multiple simple lab environments or singular complex lab environments
  • Address the storage issues with v2 of the home lab

In terms of software or process, the outcome I’m hoping for is fairly high levels of automation leveraging the feature set available to me in my current available software pool.  Similarly, in the future I could use this model for a testing environment at work, which again means leveraging technologies that may be licensed with (ie. standard vSphere, SCCM, etc) as opposed to the best solutions possible that they may not be licensed for (some of the automation-heavy vmware products come to mind).

Going forward I hope to document the process I’ll be going through in making the home lab, including research and testing to get the end result.

Windows 7 Remote Assist Wrapper Script

One of the functionality changes in Windows 7 was to Remote Assistance. In XP, you got a nice GUI to input the machine name or IP address of the target machine. In Windows 7, this was changed in a way where it was difficult to do this. You could do it via the command line. As an academic exercise I wanted to create a graphical wrapper for this that duplicated the XP Remote Assistance experience for service desk.

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

#endregion

#region Post-Constructor Custom Code

#endregion

#region Form Creation
#Warning: It is recommended that changes inside this region be handled using the ScriptForm Designer.
#When working with the ScriptForm designer this region and any changes within may be overwritten.
#~~< form1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$form1 = New-Object System.Windows.Forms.Form
$form1.Text = "ASG Remote Assistance"
#~~< btnStartRA >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$btnStartRA = New-Object System.Windows.Forms.Button
$btnStartRA.Location = New-Object System.Drawing.Point(13, 219)
$btnStartRA.Size = New-Object System.Drawing.Size(230, 23)
$btnStartRA.TabIndex = 4
$btnStartRA.Text = "Start Remote Assistance"
$btnStartRA.UseVisualStyleBackColor = $true
$btnStartRA.Enabled = $false
$btnStartRA.Add_Click({ StartRA })
#~~< lstCompInfo >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$lstCompInfo = New-Object System.Windows.Forms.ListBox
$lstCompInfo.FormattingEnabled = $true
$lstCompInfo.Location = New-Object System.Drawing.Point(13, 86)
$lstCompInfo.SelectedIndex = -1
$lstCompInfo.Size = New-Object System.Drawing.Size(259, 108)
$lstCompInfo.TabIndex = 3
#$lstCompInfo.Text = ""
#~~< btnConnect >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$btnConnect = New-Object System.Windows.Forms.Button
$btnConnect.Location = New-Object System.Drawing.Point(197, 37)
$btnConnect.Size = New-Object System.Drawing.Size(75, 23)
$btnConnect.TabIndex = 2
$btnConnect.Text = "Connect"
$btnConnect.UseVisualStyleBackColor = $true
#$btnConnect.Add_Click({ $lstCompInfo.Items.Add("This is a test") })
$btnConnect.Add_Click({ GetDetails })
#~~< txtCompName >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$txtCompName = New-Object System.Windows.Forms.TextBox
$txtCompName.Location = New-Object System.Drawing.Point(13, 39)
$txtCompName.Size = New-Object System.Drawing.Size(168, 20)
$txtCompName.TabIndex = 1
$txtCompName.Text = ""
#~~< Label1 >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Location = New-Object System.Drawing.Point(13, 13)
$Label1.Size = New-Object System.Drawing.Size(215, 23)
$Label1.TabIndex = 0
$Label1.Text = "Enter Computer Name or IP Address:"
$form1.Controls.Add($btnStartRA)
$form1.Controls.Add($lstCompInfo)
$form1.Controls.Add($btnConnect)
$form1.Controls.Add($txtCompName)
$form1.Controls.Add($Label1)

#endregion

#region Custom Code

#endregion

#region Event Loop

function Main{
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form1)
}

function GetDetails
{
$strComputer = $txtCompName.Text
$strConnStatus = test-connection -computername $strComputer -quiet

if ($strConnStatus -eq $true)
{
# connection worked, continue script
$lstCompInfo.Items.Add("Connection successful...")
$objUsername = gwmi -computer $strComputer Win32_ComputerSystem | select username, model
$strUserName = $objUsername.Username
$strModelName = $objUsername.Model
$lstCompInfo.Items.Add("Current User is $strUserName")
$lstCompInfo.Items.Add("The target computer is a $strModelName")
$btnStartRA.Enabled = $true
$btnStartRA.Text = "Start Remote Assistance for $strComputer"

}
else
{
# connection failed
#Write-Host "Connection failed with status "
$lstCompInfo.Items.Add("Connection failed.")
$btnStartRA.Enabled = $false
#$strConnStatus | select *
}

}
function StartRA
{
$RAconName = $txtCompName.Text
$lstCompInfo.Items.Add("Attempting to connect to $RAconName" )
cmd /c msra /offerRA $RAconName
}

#endregion

#endregion

#region Event Handlers

Main #This call must remain below all other event functions

#endregion

Some of the lines are note are:

  • Line 24 – The Add_Click will call the function that performs the Remote Assistance connection
  • Line 76 – The script performs a test to see if the system name is responding
  • Line 87 – As part of the IF…THEN statement, if the connection status is true, the connect button is enabled by this line.
  • Line 106 – This line performs the command line version of the Remote Assistance connection, using the supplied computer name in the command

Windows 7 SOE – Reset Computer Groups Script

The application deployment setup in SCCM 2007 means you have to tend towards application deployment based on a user’s computer rather than the user’s account. One method of doing this is to have the computer in security groups that relate to collections to deploy the applications. For example, you may have a security group called “SCCM_Viso2010” to deploy Visio 2010. Where this becomes an issue is when you reimage the machine, you need a method of resetting the machine back to a default state so it doesn’t recieve those extra apps again. The script below was designed to achieve this.

add-pssnapin quest.activeroles.admanagement

write-host "Getting SID, GUID and DN for $env:computername"
$strComputer = get-qadcomputer $env:computername | select sid,guid,dn

write-host "Getting groups for $env:computername"
$strComputerGroups = get-qadmemberof $strComputer.SID

foreach ($obj in $strComputerGroups) {
if ($obj.Name -eq "Domain Computers")
{
write-host "This is the default group, do nothing"
}
else
{
write-host "The group $obj is a non-standard group"
remove-qadgroupmember -identity $obj -member $strComputer.SID
}
}

# Removing Quest AD snapin
remove-pssnapin quest.activeroles.admanagement

The behaviour of the script is to remove any group that isn’t the default group of “Domain Computers”. Like the OU move script, it utilises the Quest AD cmdlets.

Windows 7 SOE – Set Computer OU Script

One of the nice things about a Windows 7 SOE is it opens up the use of Powershell during the second phase of the OS installation.  Part of the SOE design for I worked on required some manipuation of items in Active Directory.  Doing this in VBScript is something I’ve found difficult, while it can be very easy in Powershell, especially if using the Quest AD cmdlets.

In this situation, the requirement was to move the computer account from the default location for the machine account creation (the Computers container) to an custom OU so the computer would fall under the influence of numerous group policies.  The script is detailed below:

add-pssnapin quest.activeroles.admanagement
$strComputer = $env:computername
$currDate = get-date -format g
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- Starting OU Check"

$strGetComputer = get-qadcomputer $strComputer | select sid,GUID
$strGetComputerSID = $strGetComputer.sid

$strParentDN = get-qadobject -identity $strComputer -type computer | select parentcontainerdn
$currDate = get-date -format g
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- Current OU is $strParentDN"
if ($strParentDN.ParentContainerDN -eq "OU=Windows7SOETesting,OU=SCCM Managed PCs,DC=asggroup,DC=com,DC=au" )
{
$currDate = get-date -format g
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- This computer is in the correct OU"
}
else
{
$currDate = get-date -format g
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- This computer is not in the correct OU"
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- Attempting to move this computer with SID $strGetComputerSID to the correct OU...."
move-qadobject -identity $strGetComputersid -NewParentContainer 'OU=Windows7SOETesting,OU=SCCM_Devices,DC=contoso,DC=com'
add-content -path c:windowstempASGMoveComputertoCorrectOU.log -value "$currDate --- Move operation completed."
}
remove-pssnapin quest.activeroles.admanagement

A lot of the code is taken up with various setup code, but the key line is 22, which moves the machine account to the Windows 7 SOE OU.

Windows 7 SOE – Computer Naming and Space Characters

One of the frustrating road blocks I’ve run into with this Windows 7 SOE was related to the machine name.  Under the Windows XP SOE task sequence, there was a simple script that extracted the asset tag field from the BIOS and used that as the basis for the computer name.  One would think this would work without issue for Windows 7.  As it turns out, I was wrong.

After much hair pulling, I decided to check for non-visible characters by checking the length of the string.  Normally there is 9 characters.  When performing this check under the Windows 7 SOE, it returned 10 characters.  It seems the Windows 7 installer doesn’t like having a space in the machine name.  Once I added some code to remove these sort of characters, the problem went away.

[cc lang=”powershell” line_numbers=”true”]
strAssetTagNew = trim(strAssetTagNew)
[/cc]

Windows 7 SOE Design Outline

I’ve been working on a Windows 7 SOE for ASG for a couple of months now.  One of the things driving how the SOE is structured is to address issues with the old Windows XP SOE.  The XP SOE used what I call a “monolithic” process, by using a captured reference image that included all the SOE applications.  This is similar to how Ghost works and I don’t really like it as it doesn’t offer flexibility.  The Windows 7 SOE will use a modular approach where the task seequence will have several discreet tasks:

  • OS Deployment
  • SOE Application Deployment
  • Driver Installation

The rationale behind this is, should the need arise, these individual modules can be updated independently without having  an effect on other modules.

VM Server #2 Upgrade – Attempt 2

The Gigabyte board in VM server 2, it seems, supports 16GB of RAM.  So I’ve decided to do a second upgrade on it.  Components will be:

  • Intel i7 870
  • 4 x Kingston 4GB memory sticks (16GB in total)
  • 4 x Western Digital Caviar Black hard drives

This should make that server a pretty beefy one for virtualisation and hopefully make it more stable than it was before.

Hyper-V, undersizing your boot partition and swap file fun

I have a bad habit of making the boot drives for my virtal machines quite small, usually around 16GB. My Exchange 2010 server is virtualised and has this sort of configuration, a 16-gigabyte C: drive which just the OS, and a D: drive with Exchange and the databases on it. At some point, Windows decided to increase the swapfile to a point where I was uncomforable with the amount of free space on C: drive. No problems I thought, I’ll put it on D: drive. It would refuse to take it and would recreate the swap file on C: as a temporary swap file leading to bad performance.

After a fair amount of hair pulling and bad performance, I found out the issue. As detailed here, you can’t boot a Hyper-V machine from a SCSI Virtual Disk (that is, a virtual hard disk created and attached to the VM’s SCSI controller), not can you create a swapfile on it. This is apparently caused by the nature of the SCSI disk and controller and can be fixed by using an IDE virtual hard disk instead. So now the Exchange server has a 3rd drive, S: drive which is a 32-gigabyte IDE virtual disk that happily stores the swap file. Performance is much improved as a result.