Как обнаружить 64-битную платформу Windows с .NET?

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

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

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

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

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

Ответ 1

IntPtr.Size не вернет правильное значение при запуске в 32-разрядной .NET Framework 2.0 на 64-битной Windows (он вернет 32-разрядную версию).

Как описывает Microsoft Raymond Chen, вы должны сначала проверить, работает ли в 64-битном процессе (я думаю, что в .NET вы можете сделать это, проверив IntPtr.Size), и если вы работаете в 32-битном процессе, вам все равно придется вызывать функцию Win API IsWow64Process. Если это возвращает true, вы выполняете 32-разрядный процесс в 64-разрядной Windows.

Microsoft Раймонд Чен: Как программно определить, работаете ли вы в 64-разрядной Windows.

Мое решение:

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

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

public 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;
    }
}

Ответ 2

.NET 4 имеет два новых свойства в классе Environment, Is64BitProcess и Is64BitOperatingSystem. Интересно, что если вы используете Reflector, вы можете увидеть, что они реализованы по-разному в 32-битных и 64-битных версиях mscorlib. 32-разрядная версия возвращает false для Is64BitProcess и вызывает IsWow64Process через P/Invoke для Is64BitOperatingSystem. 64-разрядная версия просто возвращает true для обоих.

Ответ 4

Это всего лишь реализация того, что было предложено выше Бруно Лопесом, но работает над Win2k + всеми пакетами обновления WinXP. Просто подумал, что я бы опубликовал его, чтобы другие люди не бросили его вручную. (опубликовано как комментарий, но я новый пользователь!)

[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;
}

Ответ 5

Ответ на этот вопрос (взятый из обоих ответов stefan-mg, ripper234 и BobbyShaftoe):

    [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;
    } 

Сначала проверьте, есть ли у вас 64-битный процесс. Если вы этого не сделаете, проверьте, является ли 32-разрядный процесс Wow64Process.

Ответ 6

Microsoft разместила образец кода для этого:

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

Он выглядит следующим образом:

    /// <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);

Существует также версия WMI (для тестирования удаленных компьютеров).

Ответ 7

Вы также можете проверить переменную среды PROCESSOR_ARCHITECTURE.

Он либо не существует, либо установлен на "x86" в 32-разрядной 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);
}

Ответ 8

Из блога Chriz Yuen

С#.Net 4.0 Введено два новых свойства среды Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;

Будьте внимательны при использовании этих двух свойств. Тест на компьютере с Windows 7 64bits

//Workspace: Target Platform x86
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess False

//Workspace: Target Platform x64
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess True

//Workspace: Target Platform Any
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess True

Ответ 9

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

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

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

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

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

Это вернет "X86" в 32-разрядную Windows и "AMD64" в 64-разрядную Windows.

Ответ 10

Попробуйте следующее:

Environment.Is64BitOperatingSystem

Environment.Is64BitProcess

Ответ 11

Самый быстрый способ:

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

Примечание: это очень прямо.

Ответ 12

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

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: Обнаружение процесса Bitness.

Ответ 13

Использование 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();

Ответ 14

Это решение на основе кода 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);  
}

Ответ 15

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

    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;
        }
    }

Ответ 16

Вот прямой подход в С# с использованием 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; 
} 

Ответ 17

Я использую следующий код. Примечание. Это сделано для проекта 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);
    }

Ответ 18

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

PROCESSOR_ARCHITECTURE=x86

..

PROCESSOR_ARCHITECTURE=AMD64

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

Ответ 19

Здесь Подход Windows Management Instrumentation (WMI):

string _osVersion = "";
string _osServicePack = "";
string _osArchitecture = "";

ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_OperatingSystem");
ManagementObjectCollection collection = searcher.Get();

foreach (ManagementObject mbo in collection)
{
    _osVersion = mbo.GetPropertyValue("Caption").ToString();
    _osServicePack = string.Format("{0}.{1}", mbo.GetPropertyValue("ServicePackMajorVersion").ToString(), mbo.GetPropertyValue("ServicePackMinorVersion").ToString());

    try
    {
        _osArchitecture = mbo.GetPropertyValue("OSArchitecture").ToString();
    }
    catch
    {
        // OSArchitecture only supported on Windows 7/Windows Server 2008
    }
}

Console.WriteLine("osVersion     : " + _osVersion);
Console.WriteLine("osServicePack : " + _osServicePack);
Console.WriteLine("osArchitecture: " + _osArchitecture);

/////////////////////////////////////////
// Test on Windows 7 64-bit
//
// osVersion     : Microsoft Windows 7 Professional
// osservicePack : 1.0
// osArchitecture: 64-bit

/////////////////////////////////////////
// Test on Windows Server 2008 64-bit
//    --The extra r come from the registered trademark
//
// osVersion     : Microsoftr Windows Serverr 2008 Standard
// osServicePack : 1.0
// osArchitecture: 64-bit

/////////////////////////////////////////
// Test on Windows Server 2003 32-bit
//    --OSArchitecture property not supported on W2K3
//
// osVersion     : Microsoft(R) Windows(R) Server 2003, Standard Edition
// osServicePack : 2.0
// osArchitecture:

Ответ 20

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

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

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

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

Ответ 21

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();
        }
    }
}

Ответ 22

Используйте это, чтобы получить установленную архитектуру Windows:

string getOSArchitecture()
{
    string architectureStr;
    if (Directory.Exists(Environment.GetFolderPath(
                           Environment.SpecialFolder.ProgramFilesX86))) {
        architectureStr ="64-bit";
    }
    else {
        architectureStr = "32-bit";
    }
    return architectureStr;
}

Ответ 23

Включите следующий код в класс вашего проекта:

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

    public static int GetBit()
    {
        int MethodResult = "";
        try
        {
            int Architecture = 32;

            if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6)
            {
                using (Process p = Process.GetCurrentProcess())
                {
                    bool Is64Bit;

                    if (IsWow64Process(p.Handle, out Is64Bit))
                    {
                        if (Is64Bit)
                        {
                            Architecture = 64;

                        }

                    }

                }

            }

            MethodResult = Architecture;

        }
        catch //(Exception ex)
        {
            //ex.HandleException();
        }
        return MethodResult;
    }

Используйте его так:

string Architecture = "This is a " + GetBit() + "bit machine";

Ответ 24

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

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

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

Ответ 25

Учитывая, что принятый ответ очень сложный. Есть более простые способы. Мое - это вариация александрудского анасвера. Учитывая, что 64-битные окна устанавливают 32-разрядные приложения в Program Files (x86), вы можете проверить, существует ли эта папка, используя переменные среды (чтобы компенсировать разные локализации).

например.

private bool Is64BitSystem
{
   get
   {
      return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES(X86)%"));
   }
}

Это для меня быстрее и проще. Учитывая, что я также хочу получить доступ к определенному пути в этой папке на основе версии ОС.

Ответ 26

Просто проверьте, существует ли "C:\Program Files (x86)". Если нет, то вы находитесь на 32-битной ОС. Если это так, то ОС - 64 бит (Windows Vista или Windows 7). Это кажется достаточно простым...

Ответ 27

Наслаждайтесь; -)

Function Is64Bit() As Boolean

    Return My.Computer.FileSystem.SpecialDirectories.ProgramFiles.Contains("Program Files (x86)")

End Function

Ответ 28

Я использую:

Dim drivelet As String = Application.StartupPath.ToString
If Directory.Exists(drivelet(0) & ":\Program Files (x86)") Then
    MsgBox("64bit")
Else
    MsgBox("32bit")
End if

Это путь, по которому запускается ваше приложение, если оно установлено в разных местах на компьютере. Кроме того, вы можете просто сделать общий путь C:\, так как 99,9% компьютеров там установлены Windows в C:\.

Ответ 29

Я использую следующую версию:

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