如何以编程方式确定特定进程是32位还是64位

113
我的C#应用程序如何检查特定应用程序/进程(注意:不是当前进程)是以32位还是64位模式运行的?
例如,我可能想通过名称查询特定进程,比如`abc.exe`,或者根据进程ID号查询。

请始终将语言作为标记输入;我现在会更改此帖子上的标记 :-) - Dean J
3
请说明您是想知道当前进程是否为64位,还是查询另一个进程? - Mehrdad Afshari
重复:https://dev59.com/zHVC5IYBdhLWcg3whRgw - Redwood
7个回答

196

我见过的比较有趣的方法之一是这样的:

if (IntPtr.Size == 4)
{
    // 32-bit
}
else if (IntPtr.Size == 8)
{
    // 64-bit
}
else
{
    // The future is now!
}

要查找是否有其他进程在64位模拟器(WOW64)中运行,请使用以下代码:

namespace Is64Bit
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Runtime.InteropServices;

    internal static class Program
    {
        private static void Main()
        {
            foreach (var p in Process.GetProcesses())
            {
                try
                {
                    Console.WriteLine(p.ProcessName + " is " + (p.IsWin64Emulator() ? string.Empty : "not ") + "32-bit");
                }
                catch (Win32Exception ex)
                {
                    if (ex.NativeErrorCode != 0x00000005)
                    {
                        throw;
                    }
                }
            }

            Console.ReadLine();
        }

        private static bool IsWin64Emulator(this Process process)
        {
            if ((Environment.OSVersion.Version.Major > 5)
                || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1)))
            {
                bool retVal;

                return NativeMethods.IsWow64Process(process.Handle, out retVal) && retVal;
            }

            return false; // not on 64-bit Windows Emulator
        }
    }

    internal static class NativeMethods
    {
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process);
    }
}

8
这就是为什么微软不得不创建版本兼容性层来解决像这样的代码中存在的缺陷。当Windows Vista(6.0)推出时会发生什么?当人们因为微软将Windows 7版本号命名为6.1而不是7.0时对其进行诋毁,实际上这修复了许多应用程序兼容性问题。 (Environment.OSVersion.Version.Major >= 5 && Environment.OSVersion.Version.Minor >= 1) - Ian Boyd
4
函数名IsWin64有点误导人,我认为。如果是在x64操作系统下运行32位进程,它会返回true。 - Denis The Menace
2
为什么要使用 processHandle = Process.GetProcessById(process.Id).Handle; 而不是只使用 processHandle = process.Handle; - Jonathon Reinhart
1
@JonathonReinhart 这不是一个好问题吗。我不知道。这一定是从以前某种做事方式切换过来时保留下来的。感谢你发现了这个问题! - Jesse C. Slicer
2
这个答案是错误的;在出现错误的情况下返回false而不是引发异常是非常糟糕的设计。 - user626528
显示剩余3条评论

155

如果您使用的是 .Net 4.0,则对于当前进程来说,这只需要一行代码:

Environment.Is64BitProcess

参见 Environment.Is64BitProcessProperty(MSDN)。


2
你能发一下 Is64BitProcess 的代码吗?也许我可以借鉴它的功能来判断当前进程是否为 64 位。 - Ian Boyd
1
@Ian,我怀疑Sam在这个论坛上发布微软代码是否合法。我不确定他们参考许可证的确切内容,但我相当确定它禁止在任何地方复制代码。 - ProfK
3
@Ian,有人已经为您做了这项工作:https://dev59.com/z3RC5IYBdhLWcg3wUvQS#1913908 - Robert MacLean
5
OP明确要求查询“另一个”进程,而不是当前进程。 - Harry Johnston
1
请注意,微软确实发布了Is64BitProcess的代码(https://referencesource.microsoft.com/#mscorlib/system/environment.cs)。但是,它只是一个由编译符号控制的硬编码返回语句。 - Brian

24

选择的答案是不正确的,因为它没有完成所要求的操作。它检查一个进程是否是在x64操作系统上运行的x86进程;所以对于在x64操作系统上运行的x64进程,它将返回“false”。 此外,它没有正确处理错误。

这里有一个更正确的方法:

internal static class NativeMethods
{
    // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx
    public static bool Is64Bit(Process process)
    {
        if (!Environment.Is64BitOperatingSystem)
            return false;
        // if this method is not available in your version of .NET, use GetNativeSystemInfo via P/Invoke instead

        bool isWow64;
        if (!IsWow64Process(process.Handle, out isWow64))
            throw new Win32Exception();
        return !isWow64;
    }

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

1
如果是32位进程,Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") == "x86"将始终返回true。如果.NET4受支持,最好使用System.Environment.Is64BitOperatingSystem - Aizzat Suhardi

11

你可以检查指针的大小来确定它是32位还是64位。

int bits = IntPtr.Size * 8;
Console.WriteLine( "{0}-bit", bits );
Console.ReadLine();

6
当这个回答第一次发布的时候,不太清楚,但是OP想知道如何查询另一个进程而不是当前进程。 - Harry Johnston

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

6
OP明确要求查询“另一个”进程,而不是当前进程。 - Harry Johnston
@HarryJohnston 那段代码是有效的,只需要稍作修改即可获取“其他”进程而不是当前进程,例如 Process.GetProcessesByName("otherprocess.exe").First().Handle,但使用 kernel32 中的 IsWow64Process 是这里的重要部分! - psulek

2

以下是一行简易的检测。

bool is64Bit = IntPtr.Size == 8;

6
楼主特别询问如何查询“另一个”进程,而不是当前进程。 - Harry Johnston

0

我喜欢使用这个:

string e = Environment.Is64BitOperatingSystem

这样,如果我需要定位或验证文件,我可以轻松地编写:

string e = Environment.Is64BitOperatingSystem

       // If 64 bit locate the 32 bit folder
       ? @"C:\Program Files (x86)\"

       // Else 32 bit
       : @"C:\Program Files\";

13
64位操作系统上的32位进程怎么样? - Kiquenet
4
使用 Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) 而不是硬编码 C:\Program Files\ 真的那么难吗? - Luaan
4
永远不要在程序中硬编码“program files”,因为它是一个可本地化的字符串。例如:Αρχεία Εφαρμογών、Arquivos de Programas等。 - stevieg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接