[C#] .NET으로 Windows 64 비트 플랫폼을 감지하는 방법?

A의 .NET 2.0 C # 응용 프로그램 I는 운영 체제 플랫폼을 감지하기 위해 다음 코드를 사용 :

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

“Win32NT”를 반환합니다. 문제는 Windows Vista 64 비트에서 실행될 때 “Win32NT”를 반환한다는 것입니다.

올바른 플랫폼 (32 또는 64 비트)을 알 수있는 다른 방법이 있습니까?

Windows 64 비트에서 32 비트 응용 프로그램으로 실행될 때 64 비트도 감지해야합니다.



답변

64 비트 Windows에서 32 비트 .NET Framework 2.0을 실행하면 IntPtr.Size가 올바른 값을 반환하지 않습니다 (32 비트를 반환 함).

Microsoft의 Raymond Chen이 설명했듯이 먼저 64 비트 프로세스에서 실행 중인지 확인해야합니다 (.NET에서는 IntPtr.Size를 확인하여 수행 할 수 있다고 생각합니다) .32 비트 프로세스에서 실행중인 경우 여전히 Win API 함수 IsWow64Process를 호출해야합니다. 이것이 true를 반환하면 64 비트 Windows에서 32 비트 프로세스로 실행중인 것입니다.

Microsoft의 Raymond Chen :
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;
    }
}


답변

.NET 4에는 Environment 클래스에 Is64BitProcessIs64BitOperatingSystem 의 두 가지 새로운 속성이 있습니다. 흥미롭게도, Reflector를 사용하면 32 비트 및 64 비트 버전의 mscorlib에서 다르게 구현되는 것을 볼 수 있습니다. 32 비트 버전은 Is64BitProcess에 대해 false를 반환하고 Is64BitOperatingSystem에 대한 P / Invoke를 통해 IsWow64Process를 호출합니다. 64 비트 버전은 둘 다 true를 반환합니다.


답변

.NET Framework 4.0을 사용하는 경우 쉽습니다.

Environment.Is64BitOperatingSystem

Environment.Is64BitOperatingSystem 속성 (MSDN)을 참조하십시오 .


답변

이것은 Bruno Lopez가 위에서 제안한 것의 구현 일 뿐이지 만 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;
}


답변

전체 답변은 다음과 같습니다 (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인지 확인하십시오.


답변

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 버전도 있습니다.


답변

당신은 또한 확인할 수 있습니다 PROCESSOR_ARCHITECTURE환경 변수를 .

존재하지 않거나 32 비트 Windows에서 “x86″으로 설정되어 있습니다.

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