Jak programowo określić, czy dany proces jest 32-bitowy czy 64-bitowy

102

Jak moja aplikacja C # może sprawdzić, czy dana aplikacja / proces (uwaga: nie bieżący proces) działa w trybie 32-bitowym lub 64-bitowym?

Na przykład, mógłbym chcieć zapytać o konkretny proces według nazwy, np. „Abc.exe”, lub na podstawie numeru ID procesu.

satya
źródło
Proszę zawsze umieszczać język jako tag; Zmienię to teraz w tym poście. :-)
Dean J
3
Proszę wyjaśnić, czy chcesz wiedzieć, że bieżący proces jest 64-bitowy, czy też szukasz innego procesu?
Mehrdad Afshari
Dupelicate: stackoverflow.com/questions/266082/…
Lawrence Johnston,

Odpowiedzi:

178

Jednym z bardziej interesujących sposobów, jakie widziałem, jest:

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

Aby dowiedzieć się, czy INNE procesy działają w emulatorze 64-bitowym (WOW64), użyj tego kodu:

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);
    }
}
Jesse C. Slicer
źródło
8
(Environment.OSVersion.Version.Major >= 5 && Environment.OSVersion.Version.Minor >= 1) I dlatego Microsoft musi stworzyć podkładki pod kątem zgodności wersji - aby obejść takie błędy w kodzie. Co się stanie, gdy pojawi się system Windows Vista (6.0)? A potem ludzie robią złe usta Microsoftowi za stworzenie Windows 7 w wersji 6.1 zamiast 7.0, naprawia tak wiele błędów kompatybilnych z aplikacjami.
Ian Boyd
4
Myślę, że nazwa funkcji IsWin64 jest nieco myląca. Zwraca prawdę, jeśli proces 32-bitowy działa w systemie operacyjnym x64.
Denis The Menace
2
Po co używać processHandle = Process.GetProcessById(process.Id).Handle;zamiast po prostu processHandle = process.Handle;?
Jonathon Reinhart
1
@JonathonReinhart to nie tylko dobre pytanie. Nie mam pojęcia. Musiało to być śladami zamiany robienia rzeczy w jedną stronę. Dzięki za znalezienie tego!
Jesse C. Slicer
1
Ta odpowiedź jest po prostu niepoprawna; a zwracanie fałszu zamiast zgłaszania wyjątku w przypadku błędu to bardzo zły projekt.
user626528
141

Jeśli używasz .Net 4.0, jest to jedna linijka dla obecnego procesu:

Environment.Is64BitProcess

Zobacz Environment.Is64BitProcessProperty (MSDN).

Sam
źródło
2
Czy możesz wysłać kod Is64BitProcess? Być może będę mógł użyć tego, co robi, aby dowiedzieć się, czy pracuję jako proces 64-bitowy.
Ian Boyd,
1
@Ian, wątpię, czy Sam byłby legalnie upoważniony do publikowania kodu MS na tym forum. Nie jestem pewien dokładnej treści ich licencji referencyjnej, ale jestem prawie pewien, że zabrania powielania kodu w dowolnym miejscu.
ProfK
3
@Ian ktoś wykonał tę pracę za Ciebie: stackoverflow.com/questions/336633/…
Robert MacLean
4
Program operacyjny specjalnie poprosił o zapytanie innego procesu, a nie bieżącego procesu.
Harry Johnston,
1
Należy zauważyć, że Microsoft nie pisać kod Is64BitProcess( referencesource.microsoft.com/#mscorlib/system/environment.cs ). Jednak jest to tylko zakodowana na stałe instrukcja return, kontrolowana przez symbol kompilacji.
Brian
20

Wybrana odpowiedź jest nieprawidłowa, ponieważ nie spełnia tego, o co pytano. Sprawdza, czy proces jest procesem x86 działającym w systemie operacyjnym x64; więc zwróci wartość „false” dla procesu x64 w systemie operacyjnym x64 lub procesu x86 działającego w systemie operacyjnym x86.
Ponadto nie obsługuje poprawnie błędów.

Oto bardziej poprawna metoda:

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);
}
user626528
źródło
1
Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") == "x86"zawsze zwróci wartość true dla procesu 32-bitowego. Lepiej używać, System.Environment.Is64BitOperatingSystemjeśli .NET4 jest obsługiwany
Aizzat Suhardi
10

Możesz sprawdzić rozmiar wskaźnika, aby określić, czy ma 32 bity czy 64 bity.

int bits = IntPtr.Size * 8;
Console.WriteLine( "{0}-bit", bits );
Console.ReadLine();
Darwyn
źródło
6
W czasie, gdy ta odpowiedź została opublikowana po raz pierwszy, nie była zbyt jasna, ale OP chciał wiedzieć, jak zapytać o inny proces, a nie o bieżący.
Harry Johnston,
3
[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;
}
Praveen MB
źródło
5
Program operacyjny zapytał konkretnie, jak zapytać o inny proces, a nie o bieżący proces.
Harry Johnston,
1

Oto sprawdzenie jednej linii.

bool is64Bit = IntPtr.Size == 8;
Vikram Bose
źródło
6
Program operacyjny zapytał konkretnie, jak zapytać o inny proces, a nie o bieżący proces.
Harry Johnston,
0

Lubię tego używać:

string e = Environment.Is64BitOperatingSystem

W ten sposób, jeśli muszę zlokalizować lub zweryfikować plik, mogę łatwo napisać:

string e = Environment.Is64BitOperatingSystem

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

       // Else 32 bit
       : @"C:\Program Files\";
user1351333
źródło
13
co z procesem 32-bitowym w maszynie z 64-bitowym systemem operacyjnym?
Kiquenet
3
Czy naprawdę tak trudno jest używać go Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)zamiast na stałe zakodować `C: \ Program Files`?
Luaan
2
Nigdy nie zakoduj „plików programu” na stałe, ponieważ jest to ciąg, który można zlokalizować. Αρχεία Εφαρμογών, Arquivos de Programas, etc.
stevieg