Как определить Windows 64-битную платформу с .NET? - PullRequest
252 голосов
/ 03 декабря 2008

В приложении .NET 2.0 C # я использую следующий код для определения платформы операционной системы:

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

Возвращает "Win32NT". Проблема в том, что он возвращает «Win32NT» даже при работе в 64-разрядной версии Windows Vista.

Есть ли другой способ узнать правильную платформу (32 или 64 бит)?

Обратите внимание, что он также должен обнаруживать 64-разрядную версию при запуске как 32-разрядное приложение в 64-разрядной среде Windows.

Ответы [ 29 ]

9 голосов
/ 28 марта 2012

@ foobar: Вы правы, это слишком просто;)

В 99% случаев разработчики со слабым опытом работы с системными администраторами в конечном итоге не понимают, что Microsoft всегда позволяла перечислять Windows всем.

Системные администраторы всегда будут писать более качественный и простой код, когда дело доходит до такой точки.

Тем не менее, стоит отметить, что конфигурация сборки должна быть AnyCPU , чтобы эта переменная среды возвращала правильные значения в правильных системах:

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

Это вернет «X86» в 32-битной Windows и «AMD64» в 64-битной Windows.

6 голосов
/ 13 января 2010

Используйте эти две переменные среды (псевдокод):

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
        }

См. Сообщение в блоге HOWTO: Обнаружение битности процесса .

6 голосов
/ 05 марта 2015

Использование dotPeek помогает увидеть, как на самом деле это делает фреймворк. Имея это в виду, вот что я придумал:

public static class EnvironmentHelper
{
    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentProcess();

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

    [DllImport("kernel32")]
    static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll")]
    static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);

    public static bool Is64BitOperatingSystem()
    {
        // Check if this process is natively an x64 process. If it is, it will only run on x64 environments, thus, the environment must be x64.
        if (IntPtr.Size == 8)
            return true;
        // Check if this process is an x86 process running on an x64 environment.
        IntPtr moduleHandle = GetModuleHandle("kernel32");
        if (moduleHandle != IntPtr.Zero)
        {
            IntPtr processAddress = GetProcAddress(moduleHandle, "IsWow64Process");
            if (processAddress != IntPtr.Zero)
            {
                bool result;
                if (IsWow64Process(GetCurrentProcess(), out result) && result)
                    return true;
            }
        }
        // The environment must be an x86 environment.
        return false;
    }
}

Пример использования:

EnvironmentHelper.Is64BitOperatingSystem();
4 голосов
/ 02 февраля 2011

Это решение основано на коде Microsoft http://1code.codeplex.com/SourceControl/changeset/view/39074#842775.. Оно использует методы расширения для простого повторного использования кода.

Некоторое возможное использование показано ниже:

bool bIs64BitOS = System.Environment.OSVersion.IsWin64BitOS();

bool bIs64BitProc = System.Diagnostics.Process.GetCurrentProcess().Is64BitProc();

//Hosts the extension methods  
public static class OSHelperTools  
{  
    /// <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 IsWin64BitOS(this OperatingSystem os)  
    {  
        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.               
            return Process.GetCurrentProcess().Is64BitProc();  
        }  
    }  

    /// <summary>  
    /// Checks if the process is 64 bit  
    /// </summary>  
    /// <param name="os"></param>  
    /// <returns>  
    /// The function returns true if the process is 64-bit;        
    /// otherwise, it returns false.  
    /// </returns>    
    public static bool Is64BitProc(this System.Diagnostics.Process p)  
    {  
        // 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 result;  
        return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(p.Handle, out result)) && result);  
    }  

    /// <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);  
}
4 голосов
/ 30 сентября 2011

Мне нужно сделать это, но я также должен быть в состоянии как администратор сделать это удаленно, в любом случае, мне кажется, что это работает довольно хорошо:

    public static bool is64bit(String host)
    {
        using (var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, host))
        using (var key = reg.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\"))
        {
            return key.GetValue("ProgramFilesDir (x86)") !=null;
        }
    }
4 голосов
/ 29 ноября 2016

Я успешно использовал эту проверку во многих операционных системах:

private bool Is64BitSystem
{
   get
   {
      return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%windir%\SysWOW64"));
   }
}

Эта папка всегда называется «SysWOW64», независимо от языка операционной системы. Это работает для .NET Framework 1.1 или выше.

3 голосов
/ 24 декабря 2011

Я использую следующий код. Примечание: это сделано для проекта AnyCPU.

    public static bool Is32bitProcess(Process proc) {
        if (!IsThis64bitProcess()) return true; // We're in 32-bit mode, so all are 32-bit.

        foreach (ProcessModule module in proc.Modules) {
            try {
                string fname = Path.GetFileName(module.FileName).ToLowerInvariant();
                if (fname.Contains("wow64")) {
                    return true;
                }
            } catch {
                // What on earth is going on here?
            }
        }
        return false;
    }

    public static bool Is64bitProcess(Process proc) {
        return !Is32bitProcess(proc);
    }

    public static bool IsThis64bitProcess() {
        return (IntPtr.Size == 8);
    }
3 голосов
/ 15 января 2009

Вот прямой подход в C # с использованием DllImport из этой страницы .

[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; 
} 
2 голосов
/ 30 июня 2009

Все хорошо, но это также должно работать с env:

PROCESSOR_ARCHITECTURE=x86

..

PROCESSOR_ARCHITECTURE=AMD64

Слишком просто, может быть; -)

2 голосов
/ 06 октября 2012

Я считаю, что это лучший способ проверить платформу системы и процесс:

bool 64BitSystem = Environment.Is64BitOperatingSystem;
bool 64BitProcess = Environment.Is64BitProcess;

Первое свойство возвращает true для 64-битной системы и false для 32-битной. Второе свойство возвращает true для 64-битного процесса и false для 32-битного.

Необходимость этих двух свойств заключается в том, что вы можете запускать 32-разрядные процессы в 64-разрядной системе, поэтому вам нужно будет проверить и систему, и процесс.

...