Easily Identify Windows To Go In Your Scripts

Updated Powershell and vbscript Functions 8/16/2015

When Windows 8 was released into the wild this new supported feature “Windows To Go” was released with it. Now that Windows 8.1 is here the “To Go” OS was upgraded and released just the same.

From a scripting perspective, being able to differentiate between an internal OS drive and an external “To Go” configuration may be desired. Luckily with Windows 8 and up, Microsoft added a property to the Win32_OperatingSystem WMI Class to make this easier.

vbScript: (Updated 8/16/2015)

Function IsPortableOS(ComputerName)
   Dim SWBemlocator, objWMIProc
   Dim objOS, colOS, strOSVer, bIsPortableOS

   ' Create connection objects
   Set SWBemlocator = CreateObject("WbemScripting.SWbemLocator")
   Set objWMIProc = SWBemlocator.ConnectServer(ComputerName, "root\CIMV2")
   Set colOS = objWMIProc.ExecQuery("Select * from Win32_OperatingSystem")

   For Each objOS In colOS
      strOSVer = Left(objOS.Version,3)
      

      If ((strOSVer > "6.1") OR (LEFT(strOSVer,2) = "10"))Then
         ' Only return a value if Win8 or above.
         IsPortableOS = objOS.PortableOperatingSystem
      Else
      	' Property doesn't exist in Win7 and before
      	IsPortableOS = False
      End If
   Next
End Function

Powershell: (Updated 8/16/2015)

function Get-OperatingSystemInformation()
{
   [cmdletbinding()]
   param(
      [Parameter(Mandatory=$true)]
      [string] $ComputerName
   )

   try
   {
      $wmiObjOperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
   }
   catch
   {
      Write-Verbose -Message "Unable to get Operating System from WMI for computer $computer"
      return [HashTable]::new($null)
   }
	
   # Cast the version property to type System.Version
   [System.Version]$vOsVersion = $wmiObjOperatingSystem.Version

   # We do a try here because with Windows 7 This property does not exist.
   try
   {
      if ($wmiOsObject.PortableOperatingSystem)
      {
         $boolIsPortableOs = $true
      }
      else
      {
         $boolIsPortableOs = $false
      }
   }
   catch
   {
      $boolIsPortableOs = $false
   }

   return $htOs = @{
      'caption'=$wmiObjOperatingSystem.Caption;
      'fullversion'=$wmiObjOperatingSystem.Version;
      'osarchitecture'=$wmiObjOperatingSystem.OSArchitecture;
      'versionMajor'=$vOsVersion.Major;
      'versionMinor'=$vOsVersion.Minor;
      'versionBuild'=$vOsVersion.Build;
      'isPortableOS'=$boolIsPortableOs
   }
}

One important detail to note is that we need to do an OS version evaluation before checking the PortableOperatingSystem property. Until Windows 8 this property didn’t exist. You could put “$wmiOperatingSystem.PortableOperatingSystem” in a try/catch if you wanted to as well.

Now its not that often that you’ll have to detect or identify a Windows To Go configuration but if you’re like me and you manage a TPM BitLocker configuration for standard laptops those policies and the To Go sticks will not play nicely. You can simply create a Group Policy WMI filter for portable operating systems:

Select * from Win32_OperatingSystem where PortableOperatingSystem = "True"

Enjoy!
-NDS

Powershell: Check if a Computer is Online

Fairly simple solution but this often comes up with others at work…Say you’ve got a piece of masterful automation with Powershell and need an easy way to check if a computer is online and execute code specifically for that. Well with the Test-Connection cmdlet and a few parameters we’re there.

In this example we’ll use a pre-populated array and run with it:

# Array of computers
$computerList = @("Computer1","Computer2","Computer3","Server1")# Foreach loop to test each connection

foreach ($computer in $computerList)
{
   If (Test-Connection -ComputerName $computer -Count 1 -Quiet)
   {
      Write-Host "$computer is Online"
      # Do some stuff....
   } else {
      Write-Host "$computer is offline"
      # No soup for you...
   }
}

The “-Count” parameter can of course be changed if more than one attempt may be necessary. The “-Quiet” parameter is used to suppress messages on the console. Technet article on Test-Connection.

You can take this a step futher and have the script import computers from a csv, database, or whatever else you feel.

-NDS