NAnt – Detect 64-bit or 32-bit OS
I was working with Cody Collins and we ran into a problem recently with detecting whether the OS running was 32-bit or 64-bit from within NAnt. We’re trying to automate the installation of some software that has separate installers for 32-bit and 64-bit and we need to determine which installer to run from NAnt.
The problem begins with NAnt being compiled for 32-bit mode only which means all 64-bit functionality is transparent to it. If it weren’t for that, then we could simply depend on the PROCESSOR_ARCHITECTURE environment variable. So if you try to ask the OS if it’s 64-bit, it will tell you that it isn’t. Luckily there is an IsWow64Process WinAPI call that you can make to determine if you are running in WoW64. From these two pieces of information, you can infer whether or not the OS is 64-bit.
Cody and I were able to come up with the following scripts to determine this.
Note: This runs unmanaged code and does not protect you from crashes there – this could be better but this should get you 90% of the way there. This has been tested on Windows XP (32-bit), Windows 2003 (64-bit), Windows Vista (32-bit and 64-bit), Windows 2008 (32-bit), and Windows 7 RC (64-bit). Not an exhaustive test but it covers many of the bases.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <property name="Is64BitOperatingSystem" value="false" /> <property name="Is64BitProcess" value="false" /> <property name="IsWow64Process" value="false" /> <target name="DetectOperatingSystemArchitecture" depends="DetectIfWow64Process,DetectIf64BitProcess"> <description> This will detect whether the current Operating System is running as a 32-bit or 64-bit Operating System regardless of whether this is a 32-bit or 64-bit process. </description> <property name="Is64BitOperatingSystem" value="${IsWow64Process or Is64BitProcess}" /> <choose> <when test="${Is64BitOperatingSystem}"> <echo message="The operating system you are running is 64-bit." /> </when> <otherwise> <echo message="The operating system you are running is 32-bit." /> </otherwise> </choose> </target> <script language="C#" prefix="MyWin32Calls"> < code> < ![CDATA[ [System.Runtime.InteropServices.DllImport("kernel32.dll")] public static extern bool IsWow64Process(System.IntPtr hProcess, out bool lpSystemInfo); [Function("IsWow64Process")] public bool IsWow64Process() { bool retVal = false; IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, out retVal); return retVal; } ]]> < /code> </script> <target name="DetectIfWow64Process"> <description> Detects whether we are currently in a WoW64 process or not. </description> <property name="IsWow64Process" value="${MyWin32Calls::IsWow64Process()}" /> <echo message="Setting the [IsWow64Process] property to ${IsWow64Process}." /> </target> <target name="DetectIf64BitProcess"> <description> Detects whether we are currently in a 32-bit or 64-bit process (not necessarily what the OS is running). Note that as of the time of this writing, this will ALWAYS return false because NAnt is compiled to run in 32-bit mode only. </description> <!-- This can return x86, x64, AMD64, or IA64 as of the time of this writing. This works for a 32-bit process in a 64-bit OS because the OS makes the 64-bitness transparent to the process in this environment variable. --> <property name="Is64BitProcess" value="${environment::get-variable('PROCESSOR_ARCHITECTURE')!='x86'}" /> <echo message="Setting the [Is64BitProcess] property to ${Is64BitProcess}." /> </target> |
On a 64-bit OS, it has the following output:
D:\bin\deleteme\nanttest>build DetectOperatingSystemArchitecture NAnt 0.85 (Build 0.85.2344.0; rc4; 6/2/2006) Copyright (C) 2001-2006 Gerry Shaw http://nant.sourceforge.net Buildfile: file:///D:/bin/deleteme/nanttest/test.build Target framework: Microsoft .NET Framework 2.0 Target(s) specified: DetectOperatingSystemArchitecture [script] Scanning assembly "lsbw4oxa" for extensions. DetectIfWow64Process: [echo] Setting the [IsWow64Process] property to True. DetectIf64BitProcess: [echo] Setting the [Is64BitProcess] property to False. DetectOperatingSystemArchitecture: [echo] The operating system you are running is 64-bit. BUILD SUCCEEDED Total time: 0.2 seconds. D:\bin\deleteme\nanttest>
Happy NAnting!!!
*heads off to the IndyALT.NET meeting on Continuous Integration now…*
I’m getting this error on my Windows 7 64bit w/ .NET framework 4.0:
Compilation failed:
c:\Users\joseph\AppData\Local\Temp\r7m0eqss.0.cs(31,39) : error CS0234: The type or namespace name ‘Process’ does not exist in the namespace ‘System.Diagnostics
‘ (are you missing an assembly reference?)
//——————————————————————————
//
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//——————————————————————————
using NAnt.Core;
using NAnt.Core.Attributes;
using System;
using System.Collections;
using System.IO;
using System.Text;
[FunctionSet("MyWin32Calls", "MyWin32Calls")]
public class nant23f3bc35e8124e1f98591b0f08c9e8c5 : NAnt.Core.FunctionSetBase {
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
public static extern bool IsWow64Process(System.IntPtr hProcess, out bool lpSystemInfo);
[Function("IsWow64Process")]
public bool IsWow64Process()
{
bool retVal = false;
IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, out retVal);
return retVal;
}
public nant23f3bc35e8124e1f98591b0f08c9e8c5(NAnt.Core.Project project, NAnt.Core.PropertyDictionary propDict) :
base(project, propDict) {
}
}