HOWTO: Detect Process Bitness


In an ideal world, everything runs as native bitness (64bit program on 64bit OS, 32bit program on 32bit OS) and life goes on. However, sometimes you need to run that legacy 32bit program on a 64bit OS and need to configure things a little differently as a result. How can you detect this WOW64 case (32bit program on 64bit OS) and act appropriately?


Detection Matrix


The general idea is to check the following environment variables:



  • PROCESSOR_ARCHITECTURE – reports the native processor architecture EXCEPT for WOW64, where it reports x86.
  • PROCESSOR_ARCHITEW6432 – not used EXCEPT for WOW64, where it reports the original native processor architecture.

Visually, it looks like:


















Environment Variable \ Program Bitness 32bit Native 64bit Native WOW64
PROCESSOR_ARCHITECTURE x86 AMD64 x86
PROCESSOR_ARCHITEW6432 undefined undefined AMD64


  • WOW64 = 32bit Program on 64bit OS
  • Replace AMD64 with IA64 for Itaniums

Detection Logic


The logic that I use from a program to detect whether the OS is 32bit or 64bit looks like this:

IF PROCESSOR_ARCHITECTURE == amd64 OR
PROCESSOR_ARCHITEW6432 == amd64 THEN
// OS is 64bit
ELSE
// OS is 32bit
END IF

Another way to test for the same thing is:

IF PROCESSOR_ARCHITECTURE == x86 AND
PROCESSOR_ARCHITEW6432 NOT DEFINED THEN
// OS is 32bit
ELSE
// OS is 64bit
END IF

While detection for whether a process is in WOW64 mode is to simply check for the presence of the PROCESSOR_ARCHITEW6432 environment variable.


In Closing…


Now, WHEN would one have to do this? Oh… how about when you are a 32bit application and need to:



  • Turn off WOW64 FileSystem Redirection to reach into System32 directory to launch a 64bit process

  • Turn off WOW64 Registry Redirection to read the real HKLM\Software or HKCU\Software values

Of course, you should realize that WOW64 is just a compatibility shim and NOT an architecture to build/rely upon, so I would keep these sorts of manipulations to a minimum. Sometimes, it is a good idea to not disturb the man behind the curtain…


//David

Comments (28)

  1. Pavel Lebedinsky says:

    You can also check sizeof(PVOID). If you get 8 you’re a 64 bit process. If you get 4 then call IsWow64Process to see if you’re running in wow64.

    This way your code doesn’t depend on environment variables (which can be changed by the parent process) and will continue to work if Windows supports new architectures in the future.

  2. David.Wang says:

    Pavel – There are two reasons I chose to express bitness detection using environment variables:

    1. Environment variable is pretty universal and natively available to Batch, Windows Script Host, ASP/ASP.Net/PHP, C/C++, etc.

    2. I want my code to have an easily accessible external knob to tweak. I like the environment variable approach precisely *because* the parent process can do this alteration.

    Ultimately, it comes down to who has control – the developer of the code or the administrator using the code. I prefer that the developer control all the defaults but allowing the knowledgeable administrator to tweak for extraordinary circumstances.

    Your approach is comparable to my alternate way to test –

    IF PROCESSOR_ARCHITECTURE==x86 AND

       PROCESSOR_ARCHITEW6432 NOT DEFINED

    //David

  3. Igor says:

    What would be correct way to invoke ml.exe or ml64.exe to compile one source file where that source file has directives to compile differently under ml and ml64?

    I can’t figure it out for the life of me.

  4. Satish says:

    Hi,

    Thanks for the Post. I stuck up with the Problem where a 32 bit App on 64 bit read the environment variable  "PROCESSOR_ARCHITECTURE" and returned x86 even though the Processor Arch is AMD64. Now i tried your solution and it gave me original arch. Thank you very much for this valuable Post.

  5. Vikram says:

    Thx a lot for this valuable post.

  6. Mr. Chimes says:

    The easiest way to check for OS bitness is to P/Invoke GetSystemWow64Directory, if it returns a value you are on a 64-bit OS, if the returned buffer is 0 you are 32-bit.

           [DllImport("kernel32.dll")]

           private static extern uint GetSystemWow64Directory(StringBuilder lpBuffer, uint uSize);

           internal static byte GetOSBitness()

           {

               StringBuilder lpBuffer = new StringBuilder(260);

               uint uSize = GetSystemWow64Directory(lpBuffer, 260);

               if (uSize > 0) return 1; //64-bit

               return 0; //32-bit

           }

  7. David.Wang says:

    Mr. Chimes – I think reading the PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 environment variables is way easier in all languages, managed code or native code, on any Windows version going back to Windows 9x.

    No pInvoke required. No chance of mismatched binding on OS that does not even have GetSystemWow64Directory export.

    //David

  8. olivier says:

    Note :  The x64 processor architecture is sometimes referred to as "AMD64", "x86-64", "AMD x86-64" or "Intel64".

    http://msdn.microsoft.com/en-us/library/cc267757.aspx

  9. Udi says:

    Just to make sure I understand this correctly:

    In case I’m compiling my application to 64 bit, the PROCESSOR_ARCHITEW6432 isn’t relevant for me, and I only need to consider the PROCESSOR_ARCHITECTURE variable, correct?

    What are the optional values of PROCESSOR_ARCHITECTURE?

    Can I assume that if it is not "x86" then I’m running on 64 bit processor? (Again, my process was compiled for 64 bit)

    Thanks!

    Udi.

  10. Udi says:

    Two more things please if I may:

    1. I assume PROCESSOR_ARCHITECTURE i.e. HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironmentPROCESSOR_ARCHITECTURE.

    2. Do you know maybe where does its value come from? Is it a WMI class? If so, which class is it?

    Again, I really apreciate the help!

    Udi.

  11. David.Wang says:

    Udi – if your EXE is compiled for 64bit, then it will only run on 64bit Windows OS and have no assumptions to make. In general, you should not mess around with bitness representations because it only hacks an existing compatibility shim — double yuck.

    //David

  12. Udi says:

    I’m sorry David for not explaining myself correctly and fully:

    I have have an installation process that checks this reg key to determine which version of my application to install (the 32 or 64 bit).

    I’m asking what kind of values may appear in this key, who’s responsible for these values (WMI?), and if it is correct to assume that any value different than "x86" means we’re running on a 64 bit machine?

    Thanks again and sorry for the nag.

    Udi.

  13. David.Wang says:

    Udi – I recommend against writing one installer that installs different bitness on the fly. It makes handling bitness more complicated than it needs to be. Just make a 32bit x86 installer and a 64bit x64 installer.

    For example, if I launch your installer on a 64bit OS while under a WOW64 cmd-shell, should your installer install 32bit, 64bit, both, or neither? And what is the user intention in this scenario? This will remain the classic problem on 64bit OS for many years to come.

    The answer is trivial with pure 32bit and pure 64bit installer. When you start adding logic, it can backfire.

    //David

  14. Udi says:

    I understand, but when the process should be done automatically – what can you do?

    Indeed we have two different installation files and one that consists them both which tries to figure out which one to launch according to this key. The user should not be involved in the process.

    Please let me know in case I missed anything, and if you have an answer to the questions above I’ll appreciate it 🙂

    Thanks,

    Udi.

  15. David.Wang says:

    Udi – I am pointing out the classic problems that people miss.

    You will have to provide your own answer because it depends on what you want to do.

    I am just saying that the problem exists only if you have one installer that tries to figure things out. If you have one 32bit and one 64bit installer, it is a non-issue.

    If you cannot come up with your own answer then you should stick with separate 32bit and 64bit installers. MSI-based installers easily detect bitness and do the right things, so trying to bake it all into one installer means you have to know what you are doing.

    I just think it is weird for a 32bit SYSWOW process to install 64bit code because it breaks compatibility.

    //David

  16. Jeff says:

    Can the PROCESSOR_ARCHITEW6432 environment variable be queried from a batch script?  If so, how?

    I have an unattended O/S install DVD that I use to install both 32bit and 64bit Windows 2003 servers.  The DVD contains both 32bit and 64bit versions of applications like the HP hardware drivers, our antivirus software, etc…

    My batch file looks like this:

    <snip>

    echo %processor_architecture >> C:tempinstall.log

    if /i %processor_architecture%==x86 GOTO x86

    if /i %processor_architecture%==EM64T GOTO x64

    if /i %processor_architecture%==AMD64 GOTO x64

    :x86

    …Run the x86 installer

    GOTO END

    :x64

    ….Run the x64 installer

    :END

    <snip>

    If I run the batch script from a command prompt on a 64bit system, this works, but when running in batch as part of the unattended install, the command processor seems to be perpetually stuck in WOW mode as it consistently reports x86 as the value for %processor_architecture% even when running on a 64bit O/S.

    I need to resolve this as the registry redirection is driving me nuts when trying to update registry keys (like removing the autoadminlogon) and having it redirected to the Wow6432Node subkey where it has no effect.

  17. David.Wang says:

    Jeff –  All of the redirections on 64bit Windows are actually very rational once you understand what it is doing and work with it instead of against it. It only feels frustrating until you know what you are truly doing.

    The core of your problem is that your batch file is launched by a 32bit command interpreter on 64bit OS which causes you to go down the WOW path when you want to go down the native 64bit path. You have to figure out what is wrong with your unattend install command which kicks it off.

    I do lots of OS automation/unattend installation using both CScript and Batch files, and they always kick off with the bitness I intend, so your unintended 32bitness issue is most definitely specific with what you are doing. I don’t know what exactly you mean by "running in batch as part of the unattend install". Is this from the GUIRunOnce or something else?

    //David

  18. Robert says:

    Unfortunately this doesn’t work correctly when 64-bit cmd.exe is executed inside a 32-bit process (e.g. Total Commander does this). This is because environment of a 32-bit program is passed to a 64-bit child process and the detected architecture is x64 running in WOW64 mode. This may cause a lot of confusion. For example, %SystemRoot%Sysnative is not a valid path for 64-bit processes, while it is the only way to reach actual %SystemRoot%System32 on an x64 in WOW64.

  19. Robert says:

    I believe that the only reliable way to tell x86 and AMD64 apart is to check whether %SystemRoot%SysWOW64 folder or alternatively HKLMSoftwareWOW6432Node branch exist.

  20. Neelima Rustagi says:

    David,

    thanks for the valuable post.

  21. Robert 9 Jan 2010:

    > or alternatively HKLMSoftwareWOW6432Node branch exist

    Not good. That key CAN exist on 32-bit Windows, as a symbolic link to the 32-bit hive.

    msdn.microsoft.com/…/ms724072(v=vs.85).aspx

  22. Thank you very much, that help me a lot.

    How I need a batch script and don't know how use AND, OR I needed make some changes, here works fine, please take a look and tell me if exist some wrong.

    @ECHO OFF

    IF /I %PROCESSOR_ARCHITECTURE% == x86 GOTO x86

    ECHO your 64bit Native code here …

    GOTO END

    :AMD64

    ECHO your WOW64 code here …

    GOTO END

    :x86

    IF DEFINED PROCESSOR_ARCHITEW6432 GOTO AMD64

    ECHO your 32bit Native code here …

    :END

    pause

    ———————————————————————————

    If in your application amd64 = wow64 is fine you can more simple:

    @ECHO OFF

    IF /I %PROCESSOR_ARCHITECTURE% == x86 GOTO x86

    :AMD64

    ECHO your 64bit Native and WOW64 code here …

    GOTO END

    :x86

    IF DEFINED PROCESSOR_ARCHITEW6432 GOTO AMD64

    ECHO your 32bit Native code here …

    :END

    pause

  23. In my system (Windows 7 x64 SP 1) in certain circumstances PROCESSOR_ARCHITECTURE == AMD64 and at the same time PROCESSOR_ARCHITEW6432 == AMD64. According to this article, it isn't expected behavior. And so I have troubles with running MinGW.

    Steps to reproduce:

    Command line environment is started as "cmd.exe" from 32'bit Total Commander. Actual architecture of started cmd is x86.

    When I run cmd.exe by usual ways, environment variables work as expected.

    Can somebody explain this?

  24. Yan L. says:

    Under Windows 7 x64; if you're running cmd from syswow64 folder, it will report as x86, and from system32, as amd64.

  25. A.C says:

    Here is the complete vbScript based on the above article 😀

    'To Check the System For 32 bit OS or 64 Bit OS

    On Error Resume Next

    Dim ProcessArchitectureX86

    Dim ProcessArchitectureW6432

    Set wshShell = CreateObject("WScript.Shell")

    ProcessArchitectureX86 = wshShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")

    if wshShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITEW6432%") = "%PROCESSOR_ARCHITEW6432%" Then

    ProcessArchitectureW6432 = "Not Defined"

    End If

    if ProcessArchitectureX86 = "x86" And ProcessArchitectureW6432 = "Not Defined" Then

    ' For windows 32 bit

    Else

    ' For Windows 64 bit

    End If

  26. omegastripes says:

    I found on my Win7x64 system:

    msgbox wscript.createobject("wscript.shell").environment("system").item("processor_architecture") ' always "AMD64"

    msgbox wscript.createobject("wscript.shell").environment("process").item("processor_architecture") ' "AMD64" if launched via System32, "x86" if launched via SysWOW64

  27. dominic says:

    Here is a one-liner for batch file that uses David's logic to determine bitness:

    REM Set WINBIT as 32-bit (x86) or 64-bit (x64)

    SET WINBIT=x86&&IF "%PROCESSOR_ARCHITECTURE%" == "AMD64" (SET WINBIT=x64) ELSE IF "%PROCESSOR_ARCHITEW6432%" == "AMD64" SET WINBIT=x64

  28. Paweł says:

    try this : wmic OS Get OSArchitecture | find "-"

    or

    wmic cpu get AddressWidth /value

    maybe this help