views:

12506

answers:

14

In a .net 2.0 C# application I use the following code to detect the operating system platform:

string os_platform = System.Environment.OSVersion.Platform.ToString();

This returns "Win32NT". The problem is that it returns "Win32NT" even when running on Windows Vista 64bit.

Is there any other method to know the correct platform (32 or 64bit)?

Note that it should also detect 64bit when run as 32bit app on Windows 64bit.

+5  A: 

Quickest way:

if(IntPtr.Size == 8) 
{
// 64 bit machine
} 
else if(IntPtr.Size == 4) 
{
// 32 bit machine
}

Note, this is very direct.

BobbyShaftoe
Now I feel like stupid... I could have come up with that as well ;-)Thank you very much.
Marc
This won't work - if running in 32-bit .NET Framework 2.0 on 64-bit Windows, it will return 32-bit.
Stefan Schultze
Right I forgot this situation. I've edited the question to mention this as well. Thanks stefan-mg.
Marc
+32  A: 

IntPtr.Size won't return the correct value if running in 32-bit .NET Framework 2.0 on 64-bit Windows (it would return 32-bit).

As Microsoft's Raymond Chen describes, you have to first check if running in a 64-bit process (I think in .NET you can do so by checking IntPtr.Size), and if you are running in a 32-bit process, you still have to call the Win API function IsWow64Process. If this returns true, you are running in a 32-bit process on 64-bit Windows.

Microsoft's Raymond Chen: How to detect programmatically whether you are running on 64-bit Windows

My solution:

bool is64BitProcess = (IntPtr.Size == 8);
bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64();

[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process(
    [In] IntPtr hProcess,
    [Out] out bool wow64Process
);

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool InternalCheckIsWow64()
{
    if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
        Environment.OSVersion.Version.Major >= 6)
    {
        using (Process p = Process.GetCurrentProcess())
        {
            bool retVal;
            if (!IsWow64Process(p.Handle, out retVal))
            {
                return false;
            }
            return retVal;
        }
    }
    else
    {
        return false;
    }
}
Stefan Schultze
+2  A: 

Here is the direct approach in C# using DllImport from this page.

[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo); 

public static bool Is64Bit() 
{ 
    bool retVal; 

    IsWow64Process(Process.GetCurrentProcess().Handle, out retVal); 

    return retVal; 
}
ripper234
You still need to check pointer size first, otherwise it just checks if it's a 32 bit process on a 64 bit system
Bruno Lopes
+23  A: 

The full answer is this (taken from both stefan-mg, ripper234 and BobbyShaftoe's answer):

    [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);

    private bool Is64Bit()
    {
        if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private bool Is32BitProcessOn64BitProcessor()
    {
        bool retVal;

        IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);

        return retVal;
    }

First check if you're in a 64 bit process. If you're not, check if the 32 bit process is a Wow64Process.

Bruno Lopes
This will fail under Win2000 and WinXP SP1 and earlier. You need to check if the IsWow64Process() function exists before you call it, because it was only introduced in XP SP2 and Vista/Win7.
user9876
+3  A: 

You can also check for the PROCESSOR_ARCHITECTURE environment variable.

It either doesn't exist or is set to "x86" on 32-bit Windows.

private int GetOSArchitecture()
{
    string pa = 
        Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
    return ((String.IsNullOrEmpty(pa) || 
             String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64);
}
Andrew
+1  A: 

all fine, but what about:

PROCESSOR_ARCHITECTURE=x86 .. PROCESSOR_ARCHITECTURE=AMD64

from env?

too easy maybe ;-)

+6  A: 

This is just an implementation of what's suggested above by Bruno Lopez, but works on Win2k + all WinXP service packs. Just figured I'd post it so other people didn't have roll it by hand. (would have posted as a comment, but I'm a new user!)

[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
public extern static IntPtr LoadLibrary(string libraryName);

[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName);

private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process);

public static bool IsOS64Bit()
{
    if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
    {
        return true;
    }
    else
    {
        return false;
    }
}

private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate()
{
  IntPtr handle = LoadLibrary("kernel32");

  if ( handle != IntPtr.Zero)
  {
    IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process");

    if (fnPtr != IntPtr.Zero)
    {
      return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate));
    }
  }

  return null;
}

private static bool Is32BitProcessOn64BitProcessor()
{
  IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate();

  if (fnDelegate == null)
  {
    return false;
  }

  bool isWow64;
  bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64);

  if (retVal == false)
  {
    return false;
  }

  return isWow64;
}
dwhiteho
+8  A: 

.NET 4 has two new properties in the Environment class, Is64BitProcess and Is64BitOperatingSystem. Interestingly, if you use Reflector you can see they are implemented differently in the 32-bit & 64-bit versions of mscorlib. The 32-bit version returns false for Is64BitProcess and calls IsWow64Process via P/Invoke for Is64BitOperatingSystem. The 64-bit version just returns true for both.

Phil Devaney
+1  A: 

How about using these 2 environment variables?

if (PROCESSOR_ARCHITECTURE=x86 && isDefined(PROCESSOR_ARCHITEW6432) && PROCESSOR_ARCHITEW6432=AMD64 ) { //64 bit OS}
else if (PROCESSOR_ARCHITECTURE=AMD64 ) {//64 bit OS}
else if (PROCESSOR_ARCHITECTURE=x86 ) {//32 bit OS }

just pseudo code..

refer : http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx

Santhosh
A: 

OSInfo.Bits

using System;
namespace CSharp411
{
    class Program
    {
        static void Main( string[] args )
        {
           Console.WriteLine( "Operation System Information" );
           Console.WriteLine( "----------------------------" );
           Console.WriteLine( "Name = {0}", OSInfo.Name );
           Console.WriteLine( "Edition = {0}", OSInfo.Edition );
           Console.WriteLine( "Service Pack = {0}", OSInfo.ServicePack );
           Console.WriteLine( "Version = {0}", OSInfo.VersionString );
           Console.WriteLine( "Bits = {0}", OSInfo.Bits );
           Console.ReadLine();
        }
    }
}
Greg
That's all nice, but this class is from Microsoft.UpdateServices.Administration namespace which is Microsoft WSUS. I don't like to include this reference just to know the platform bits.
Marc
A: 

Hi,

thank you for all these contributions thanks to the which I could prepare a post on the topic regarding ASP .Net and SharePoint 2010. I took the code of Bruno Lopes of the Mar 25 '09 at 13:18 and I don't care if WOW64 is not used in the old OS version since we are with SharePoint at least upon Windows server 2003.

http://mosshowto.blogspot.com/2010/06/sharepoint-2010-dll-migration.html

+3  A: 

Microsoft has put a code sample for this:

http://1code.codeplex.com/SourceControl/changeset/view/39074#842775

It looks like this:

    /// <summary>
    /// The function determines whether the current operating system is a 
    /// 64-bit operating system.
    /// </summary>
    /// <returns>
    /// The function returns true if the operating system is 64-bit; 
    /// otherwise, it returns false.
    /// </returns>
    public static bool Is64BitOperatingSystem()
    {
        if (IntPtr.Size == 8)  // 64-bit programs run only on Win64
        {
            return true;
        }
        else  // 32-bit programs run on both 32-bit and 64-bit Windows
        {
            // Detect whether the current process is a 32-bit process 
            // running on a 64-bit system.
            bool flag;
            return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") &&
                IsWow64Process(GetCurrentProcess(), out flag)) && flag);
        }
    }

    /// <summary>
    /// The function determins whether a method exists in the export 
    /// table of a certain module.
    /// </summary>
    /// <param name="moduleName">The name of the module</param>
    /// <param name="methodName">The name of the method</param>
    /// <returns>
    /// The function returns true if the method specified by methodName 
    /// exists in the export table of the module specified by moduleName.
    /// </returns>
    static bool DoesWin32MethodExist(string moduleName, string methodName)
    {
        IntPtr moduleHandle = GetModuleHandle(moduleName);
        if (moduleHandle == IntPtr.Zero)
        {
            return false;
        }
        return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentProcess();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr GetModuleHandle(string moduleName);

    [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr GetProcAddress(IntPtr hModule,
        [MarshalAs(UnmanagedType.LPStr)]string procName);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);

There is a WMI version available as well (for testing remote machines).

synhershko
A: 

Why not just see if the "c:\program files (x86)" exists? If not, then you are on a 32 bit OS. If it does, then the OS is 64 bit (VISTA or Win7). Seems simple enough...

John
Make sure you retrieve the correct localised directory name from the Win32 API instead of hardcoding it.
Christian Hayter
A: 

I use a version of the following:

    public static bool Is64BitSystem()
    {
        if (Directory.Exists(Environment.GetEnvironmentVariable("ProgramFiles(x86)"))) return true;
        else return false;
    }
Josh