web-dev-qa-db-de.com

Wie erkennt man die Windows 64-Bit-Plattform mit .NET?

In einer C # -Anwendung von .NET 2.0 verwende ich den folgenden Code, um die Betriebssystemplattform zu ermitteln:

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

Dies gibt "Win32NT" zurück. Das Problem ist, dass "Win32NT" auch unter Windows Vista 64-Bit zurückgegeben wird.

Gibt es eine andere Methode, um die richtige Plattform (32 oder 64 Bit) zu kennen?

Beachten Sie, dass es auch 64-Bit erkennen sollte, wenn es unter Windows 64-Bit als 32-Bit-Anwendung ausgeführt wird.

249
Marc

IntPtr.Size gibt nicht den korrekten Wert zurück, wenn in 32-Bit-.NET Framework 2.0 unter 64-Bit-Windows ausgeführt wird (dies würde 32-Bit zurückgeben).

Wie von Raymond Raymond Chen beschrieben, müssen Sie zunächst prüfen, ob in einem 64-Bit-Prozess ausgeführt wird (ich denke, in .NET können Sie dies tun, indem Sie IntPtr.Size überprüfen). Wenn Sie in einem 32-Bit-Prozess arbeiten, sind Sie trotzdem dabei muss die Win-API-Funktion IsWow64Process aufrufen. Wenn dies true zurückgibt, werden Sie in einem 32-Bit-Prozess unter 64-Bit-Windows ausgeführt.

Raymond Chen von Microsoft: Wie können Sie programmgesteuert feststellen, ob Sie unter 64-Bit-Windows laufen

Meine Lösung:

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;
    }
}
191
Stefan Schultze

.NET 4 verfügt in der Environment-Klasse über zwei neue Eigenschaften: Is64BitProcess und Is64BitOperatingSystem . Wenn Sie Reflector verwenden, können Sie feststellen, dass sie in den 32-Bit- und 64-Bit-Versionen von mscorlib unterschiedlich implementiert sind. Die 32-Bit-Version gibt false für Is64BitProcess zurück und ruft IsWow64Process über P/Invoke für Is64BitOperatingSystem auf. Die 64-Bit-Version gibt für beide nur true zurück.

228
Phil Devaney

Wenn Sie .NET Framework 4.0 verwenden, ist das einfach:

Environment.Is64BitOperatingSystem

Siehe Environment.Is64BitOperatingSystem-Eigenschaft (MSDN).

Dies ist nur eine Implementierung der obigen Vorschläge von Bruno Lopez, funktioniert jedoch auf Win2k + allen WinXP Service Packs. Ich dachte nur, ich würde es posten, damit andere Leute es nicht mit der Hand rollen konnten. (hätte als Kommentar gepostet, aber ich bin ein neuer Benutzer!)

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

Die vollständige Antwort lautet (aus der Antwort von stefan-mg, ripper234 und 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;
    } 

Prüfen Sie zunächst, ob Sie sich in einem 64-Bit-Prozess befinden. Ist dies nicht der Fall, prüfen Sie, ob der 32-Bit-Prozess ein Wow64-Prozess ist.

49
Bruno Lopes

Microsoft hat hierfür ein Codebeispiel bereitgestellt:

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

Es sieht aus wie das:

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

Es gibt auch eine WMI-Version (zum Testen von Remote-Computern).

41
synhershko

Sie können auch nach der Umgebungsvariable PROCESSOR_ARCHITECTURE suchen.

Es ist entweder nicht vorhanden oder unter 32-Bit-Windows auf "x86" gesetzt.

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

Aus dem Chriz Yuen Blog

C # .NET 4.0 Zwei neue Umgebungseigenschaften eingeführt Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;

Seien Sie bitte vorsichtig, wenn Sie diese beiden Eigenschaften nutzen. Testen Sie auf einem Windows 7-Computer mit 64 Bit 

//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
12
electricalbah

Versuche dies:

Environment.Is64BitOperatingSystem

Environment.Is64BitProcess
11
user2235582

Schnellster Weg:

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

Hinweis:das ist sehr direkt.

9
BobbyShaftoe

@foobar: Du hast recht, es ist zu einfach;)

In 99% der Fälle wissen Entwickler mit einem schwachen Systemadministrator-Hintergrund letztendlich nicht, welche Möglichkeiten Microsoft für die Auflistung von Windows bietet.

Systemadministratoren schreiben immer besseren und einfacheren Code, wenn es zu einem solchen Punkt kommt.

Beachten Sie jedoch, dass die Build-Konfiguration AnyCPU sein muss, damit diese Umgebungsvariable die korrekten Werte auf den richtigen Systemen zurückgibt:

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

Dies gibt "X86" unter 32-Bit-Windows und "AMD64" unter 64-Bit-Windows zurück.

9
SomeSysadmin

Mithilfe von dotPeek können Sie sehen, wie das Framework dies tatsächlich tut. In diesem Sinne habe ich folgendes:

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

Verwendungsbeispiel:

EnvironmentHelper.Is64BitOperatingSystem();
6
Alexandru

Verwenden Sie diese beiden Umgebungsvariablen (Pseudocode):

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
        }

Siehe den Blogbeitrag HOWTO: Prozessnachweis erkennen.

6
Santhosh

Ich habe diese Prüfung erfolgreich auf vielen Betriebssystemen verwendet:

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

Dieser Ordner hat immer den Namen "SysWOW64", unabhängig von der Sprache des Betriebssystems. Dies funktioniert für .NET Framework 1.1 oder höher.

4
Alexandru Dicu

Ich muss das tun, aber ich muss auch in der Lage sein, es als Administrator aus der Ferne zu tun. In beiden Fällen scheint das für mich ganz gut zu funktionieren:

    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
Julian Hall

Dies ist eine Lösung basierend auf Microsofts Code unter http://1code.codeplex.com/SourceControl/changeset/view/39074#842775 . Es verwendet Erweiterungsmethoden zur einfachen Wiederverwendung von Code.

Einige mögliche Verwendung wird unten gezeigt:

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
dmihailescu

Hier ist der direkte Ansatz in C # mit DllImport von dieser Seite .

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

Ich verwende den folgenden Code. Hinweis: Es ist für ein beliebiges CPU-Projekt gemacht.

    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
blez

Ich habe festgestellt, dass dies die beste Möglichkeit ist, die Plattform des Systems und den Prozess zu überprüfen:

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

Die erste Eigenschaft gibt true für 64-Bit-Systeme und false für 32-Bit zurück .. .. Die zweite Eigenschaft gibt true für 64-Bit-Prozesse und false für 32-Bit zurück.

Diese beiden Eigenschaften werden benötigt, weil Sie 32-Bit-Prozesse auf einem 64-Bit-System ausführen können. Daher müssen Sie sowohl das System als auch den Prozess überprüfen.

2
OmarElsherif

Alles in Ordnung, aber das sollte auch von env funktionieren:

PROCESSOR_ARCHITECTURE=x86

..

PROCESSOR_ARCHITECTURE=AMD64

Zu einfach, vielleicht ;-)

2
foobar

Hier ein Ansatz von 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's 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:
2
user1054695

Fügen Sie folgenden Code in eine Klasse Ihres Projekts ein:

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

Verwenden Sie es wie folgt:

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

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

Verwenden Sie dies, um die installierte Windows-Architektur abzurufen:

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

Die akzeptierte Antwort ist sehr komplex. Es gibt einfachere Wege. Meins ist eine Variation von alexandrudicus Anaswer ..__ Da 64-Bit-Fenster 32-Bit-Anwendungen in Programmdateien (x86) installieren, können Sie anhand von Umgebungsvariablen prüfen, ob der Ordner vorhanden ist.

z.B. 

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

Dies ist für mich schneller und einfacher. Angenommen, ich möchte auch auf einen bestimmten Pfad in diesem Ordner zugreifen, der auf der Betriebssystemversion basiert. 

0
John Demetriou