Tech Off Thread

18 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

C# Detect 32 bit or 64 bit OS

Back to Forum: Tech Off
  • User profile image
    tgraupmann6​48

    Is there a way to detect whether the OS is 32 bit or 64 bit?

    I was thinking I could check for the registry node:
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node

    But there could be an easier way...

    Thoughts?

  • User profile image
    Sven Groot

    If you C# app has the "Platform target" setting on the build page of the project settings set to "Any CPU", it will execute as a native 64 bit application on 64 bit operating systems (this setting is the default and should only be changed if you use libraries that are not compatible with 64 bit).

    In that case you can check IntPtr.Size, which will be 4 on 32 bit and 8 on 64 bit.

  • User profile image
    Matthew van Eerde

    You could also use P/Invoke to call GetNativeSystemInfo and get a SystemInfo structure.

  • User profile image
    Matthew van Eerde

    Matthew van Eerde said:
    You could also use P/Invoke to call GetNativeSystemInfo and get a SystemInfo structure.
    Sample code:

    http://www.koders.com/csharp/fid495E7D0ED07BA35F5F0CE0EEFE87D7375BF1CF55.aspx

  • User profile image
    figuerres

    Matthew van Eerde said:
    this is some related info:

    http://www.pinvoke.net/search.aspx?search=GetSystemInfo&namespace=[All]

    http://www.pinvoke.net/default.aspx/kernel32/IsWow64Process.html

    Pinvoke.Net is a good place to find the .net stubbs for native stuff.

  • User profile image
    evildictait​or

    figuerres said:
    Matthew van Eerde said:
    *snip*
    this is some related info:

    http://www.pinvoke.net/search.aspx?search=GetSystemInfo&namespace=[All]

    http://www.pinvoke.net/default.aspx/kernel32/IsWow64Process.html

    Pinvoke.Net is a good place to find the .net stubbs for native stuff.
    IntPtr.Size returns the size (in bytes) of a pointer. So the bit-ness of your machine is simply (IntPtr.Size *Eye Rolling.

  • User profile image
    figuerres

    evildictaitor said:
    figuerres said:
    *snip*
    IntPtr.Size returns the size (in bytes) of a pointer. So the bit-ness of your machine is simply (IntPtr.Size *Eye Rolling.
    In native Code I would agree 100%


    but with .Net what if your app has some dependancy on a 32 bit system call or native 32 bit DLL ??
    what does the .net runtime do then ??

    I am not sure but I think it might use the 32 bit runtime to run your app so that it works right.
    in which case your managed code would not know that it was on a 64 bit capable system.

    granted this is a bit of an "edge case" but I think it's a valid point to look at.

  • User profile image
    littleguru

    figuerres said:
    evildictaitor said:
    *snip*
    In native Code I would agree 100%


    but with .Net what if your app has some dependancy on a 32 bit system call or native 32 bit DLL ??
    what does the .net runtime do then ??

    I am not sure but I think it might use the 32 bit runtime to run your app so that it works right.
    in which case your managed code would not know that it was on a 64 bit capable system.

    granted this is a bit of an "edge case" but I think it's a valid point to look at.
    The documentation says:

    The size of a pointer or handle on this platform, measured in bytes. The value of this property is 4 on a 32-bit platform, and 8 on a 64-bit platform.

    Seems like it is really platform dependent and giving you a good approximation where the application runs on.

  • User profile image
    Sven Groot

    figuerres said:
    evildictaitor said:
    *snip*
    In native Code I would agree 100%


    but with .Net what if your app has some dependancy on a 32 bit system call or native 32 bit DLL ??
    what does the .net runtime do then ??

    I am not sure but I think it might use the 32 bit runtime to run your app so that it works right.
    in which case your managed code would not know that it was on a 64 bit capable system.

    granted this is a bit of an "edge case" but I think it's a valid point to look at.

    What version of the CLR is used to load your app depends solely on the "Platform target" setting of the entry point assembly. If this is set to x86, it will always use the 32 bit runtime (and the assembly will fail to load on ia64 systems). If it is set to x64, it will always use the 64 bit runtime (and fail on x86 and ia64 systems). If it is set to Itanium, it will use the 64 bit runtime (and fail on x86 and x64). If it is set to "Any CPU" (the default), it will use the 32 bit runtime on x86 and the 64 bit runtime on x64 and ia64.

    Now here's the crunch: if your assembly is marked as Any CPU and it references another assembly that is marked as x86, or it uses a 32 bit native DLL, what happens if it is executed on x64? Answer: the 64 bit runtime is used, and at the point the relevant assembly or DLL is loaded it will crash with a BadImageFormatException.

    So if your application is using such an assembly or DLL, and you want people who have Windows x64 to be actually able to use it, please remember to set your Platform target to x86 in the project properties. An example of where this is a problem is any application that uses Managed DirectX or XNA; these libraries are x86 only, so any assembly marked as Any CPU that tries to load them will crash on x64. Also note that the C++/CLI compiler cannot produce assemblies marked with "Any CPU", even when using /clr:pure.

    The value returned by IntPtr.Size does depend on the runtime used. Which is why I said, in my initial post, that if you use the Any CPU setting, you can use IntPtr.Size. Otherwise you can't.

    If your app is being executed as a 32 bit process on a 64 bit system, GetNativeSystemInfo is the only way to get the real information (GetSystemInfo will pretend it's a 32 bit system). Note that GetNativeSystemInfo does not exist prior to Windows XP, so if you want to run on Windows 2000 don't call it without checking the system version first.

  • User profile image
    benjaminW

    The method I prefer to use, in both applications and shell scripts, is to check for the existence of the "ProgramFiles(x86)" environment variable. Most of the time the only reason I care if my code is running on 64bit OS or not is when locating the Program Files folder.

    C# example:

    public bool Is64bitOS
    {
        get { return (Environment.GetEnvironmentVariable("ProgramFiles(x86)") != null); }
    }

    public string ProgramFilesX86
    {
        get
        {
            string programFiles = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
            if (programFiles == null)
            {
                programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
            }

            return programFiles;
        }
    }

  • User profile image
    littleguru

    benjaminW said:
    The method I prefer to use, in both applications and shell scripts, is to check for the existence of the "ProgramFiles(x86)" environment variable. Most of the time the only reason I care if my code is running on 64bit OS or not is when locating the Program Files folder.

    C# example:

    public bool Is64bitOS
    {
        get { return (Environment.GetEnvironmentVariable("ProgramFiles(x86)") != null); }
    }

    public string ProgramFilesX86
    {
        get
        {
            string programFiles = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
            if (programFiles == null)
            {
                programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
            }

            return programFiles;
        }
    }
    Holy crap. That's a hack. You search for a variable that represents the old 32 bit programs' folder to understand that this is 64 bit...

  • User profile image
    Dflat

    Why not use the environment variable that was created for this purpose?

    Environment

     

    .GetEnvironmentVariable("PROCESSOR_ARCHITECTURE").ToString()

     

  • User profile image
    SlackmasterK

    bool isX64 = System.IO.Directory.GetDirectories(@"c:\Program Files (X86)\").Count > 0;

     

    Smiley

  • User profile image
    AndyC

    SlackmasterK said:

    bool isX64 = System.IO.Directory.GetDirectories(@"c:\Program Files (X86)\").Count > 0;

     

    Smiley

    That fails on localized versions of Windows.

    As mentioned above, use GetNativeSystemInfo, that is what is there for and it will always return the correct result which messing around making random guesses may well not.

  • User profile image
    W3bbo

    AndyC said:
    SlackmasterK said:
    *snip*

    That fails on localized versions of Windows.

    As mentioned above, use GetNativeSystemInfo, that is what is there for and it will always return the correct result which messing around making random guesses may well not.

    Except the function doesn't exist prior to NT5.2 so you have to do GetProcAddress which slightly complicates things.

  • User profile image
    AndyC

    W3bbo said:
    AndyC said:
    *snip*

    Except the function doesn't exist prior to NT5.2 so you have to do GetProcAddress which slightly complicates things.

    It is available in XP and above, so you only need to mess around with GetProcAddress if you're running on Windows 2000 or below. And, to be brutally honest, there is little point supporting those unless you have a specific customer requirement to do so. And then, you're so far into legacy system support you might just as well compile for 32-bit only and not worry about such things at all.

  • User profile image
    Sven Groot

    W3bbo said:
    AndyC said:
    *snip*

    Except the function doesn't exist prior to NT5.2 so you have to do GetProcAddress which slightly complicates things.

    You don't need to use GetProcAddress anyway when using .Net; PInvoke uses GetProcAddress under the hood, and it doesn't try to find the function until you call it. So declaring a function with [DllImport] and calling it wrapped in a simple "if( Environment.OSVersion.Version >= new Version(5, 1, 2600, 0) )" is perfectly safe. Alternatively, you could just call it and catch the EntryPointNotFoundException.

  • User profile image
    AndyC

    Sven Groot said:
    W3bbo said:
    *snip*

    You don't need to use GetProcAddress anyway when using .Net; PInvoke uses GetProcAddress under the hood, and it doesn't try to find the function until you call it. So declaring a function with [DllImport] and calling it wrapped in a simple "if( Environment.OSVersion.Version >= new Version(5, 1, 2600, 0) )" is perfectly safe. Alternatively, you could just call it and catch the EntryPointNotFoundException.

    Now that is a handy thing to know. I'll shall file that snippit away. Cheers Sven. Smiley

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.