Friday, July 15, 2011

When Is a String Not a String?

I came across a really difficult-to-troubleshoot bug today, a real brain-teaser.

A co-worker asked me to help him figure out why his PowerShell script was running a certain piece of code even though it shouldn't.  He had a piece of code to detect a bad Windows Installer exit code like this:

$result = InstallSomeSoftware
if ($result -eq "1603") {
  #do something...

The "do something part was being executed no matter what value he returned from the InstallSomeSoftware function.  To troubleshoot, he added some Write-Host statements to display the return value on the screen before returning it inside the function.  Sure enough, the expected value was printed on the screen, and it was not 1603.

We both scratched our heads for a while, stepped through the function, and still weren't getting anywhere, when I noticed a few random lines of output.  We realized that there were lines in his function that were returning values and not being captured by any variable or thrown away, so they were also being returned along with the expected value.

So that leaves one last piece of the puzzle.  Why would everything always evaluate to True when compared to the string "1603"?  After a little more digging we had the answer.  The first value being returned had the value True.  -eq, when attempting to determine equality, saw that the two object types weren't the same, so it did what it was supposed to do:  it cast the string "1603" as a System.Boolean and then checked to see if True was equal to  True (which is what the string "1603" evaluates to as a Boolean).

Many hairs were lost in this battle, but at least in the end we had our sanity.