At work I recently had to find a way to determine whether an application was running on a 32-bit or a 64-bit version of Windows. Stupidly, neither the My.Computer.Info nor the System.Environment classes contain details on whether or not the OS is 32 or 64 bit, though they contain other information describing the OS.
I did a lot of searching on the web, but found the results quite lacking. Many people recommended I simply check the length of an IntPtr:
If IntPtr.Size = 8 Then ' 64 bit machine ElseIf IntPtr.Size = 4 Then ' 32 bit machine End If
This works fine…but only if your application is compiled for “AnyCPU” as the target CPU. If you compile your assembly with the target CPU “x86”, for example, IntPtr.Size will always be 4 bytes, regardless of the OS architecture.
Others recommended searching the file system for the existence of a “C:\Program Files (x86)” folder. Ugh. Not only does that mean accessing the slooooooow hard drive, but it’s also accessing data that the user can modify himself. That’s just not right.
A third recommendation had to do with searching for the existence of particular environment variables, but those, too, are editable by the user and not guaranteed to exist.
A fourth recommendation I came across involved using Windows Management Instrumentation. WMI is a Windows OS infrastructure which provides information about the OS and available resources (RAM, hard drives, database servers, etc.). I couldn’t find any proper code example for what I needed, so I came up with one myself. Here is a method you can use in your VB.NET assemblies to determine whether or not the assembly is executing in a 32-bit or 64-bit OS:
''' <summary> ''' Returns a string describing whether the OS is 32-bit or 64-bit. ''' </summary> ''' <returns>A String value (e.g. "32-bit").</returns> ''' <remarks>If an error occurs, the result will be an empty string. ''' <para>Requires a reference to System.Management.</para></remarks> Public Function GetOSArchitecture() As String ' More Info on WMI available here: ' ' http://msdn.microsoft.com/En-US/library/aa394239.aspx Dim osClass As System.Management.ManagementClass = Nothing Dim result As String = "32-bit" ' Default to 32-bit for OSes which don't support the OSArchitecture property of the Win32_OperatingSystem WMI class. Try ' Get the singleton Win32_OperatingSystem WMI class so we can access properties about the OS. osClass = New System.Management.ManagementClass("Win32_OperatingSystem") ' Loop thru all properties of the single instance of the Win32_OperatingSystem class and look for the property which will tell us if ' the OS is 32-bit or 64-bit. If the property is not found, the OS is assumed to be 32-bit. ' NOTE: I'm not 100% sure if this detects 64-bit versions of XP. See above MSDN link for more information. For Each mgo As System.Management.ManagementObject In osClass.GetInstances For Each prop As System.Management.PropertyData In mgo.Properties If prop.Name = "OSArchitecture" Then result = prop.Value.ToString Exit For End If Next Next Catch ex As Exception result = String.Empty Finally ' Clean up If osClass IsNot Nothing Then osClass.Dispose() End Try Return result End Function
This code was written in VS.NET 2005 (.NET 2.0). You’ll need to add a reference to System.Management to your assembly for this method to work.
So, if you’re looking for a simple function that will reliably return whether or not the OS your assembly is running in is 32-bit or 64-bit, use this. This method *will* return “64-bit” if your OS is 64-bit and your assembly was compiled using the target CPU “x86”. The only caveats are:
- I don’t know if this works under Windows XP 64-bit. The OSArchitecture property of the Win32_OperatingSystem WMI class is said to not be present for Windows XP, so it probably doesn’t.
- If you’re running your assembly from within an emulator, I don’t know if this returns the architecture of the emulated OS or the host OS. I’m guessing it would return the architecture of the emulated OS.
So, there you go. Enjoy.