OpenProcess 无法通过 id 打开现有进程(上一个错误代码:1008)?

OpenProcess failed to open existing process via id (Last Error code: 1008)?

我正在尝试使用 OpenProcess 通过进程 ID 打开所有现有进程。但不知何故,它只在第一次调用时起作用,而下一次调用表明它不适用于报告为 1008 的错误代码(试图引用不存在的令牌).

代码如下:

[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags access, bool inheritHandle, int procId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VirtualMemoryOperation = 0x00000008,
    VirtualMemoryRead = 0x00000010,
    VirtualMemoryWrite = 0x00000020,
    DuplicateHandle = 0x00000040,
    CreateProcess = 0x000000080,
    SetQuota = 0x00000100,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    QueryLimitedInformation = 0x00001000,
    Synchronize = 0x00100000
}

foreach (var proc in Process.GetProcesses()) {
    var procHandle = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryOperation, false, proc.Id);
    var eCode = Marshal.GetLastWin32Error(); 
    //checking the last error code using Marshal.GetLastWin32Error() 
    //shows that it succeeds the first time with error code of 0
    //Then all the next calls show error code of `1008`.
    if(procHandle != IntPtr.Zero) CloseHandle(procHandle);
}

我已经尝试用谷歌搜索错误,但不确定这里有什么问题。如果你能让我知道哪里出了问题,那就太好了。谢谢!

更新: 正如我所说,它似乎只适用于循环中的第一个进程。但我非常怀疑即使在那种情况下它实际上也不起作用,因为据我所知,procHandleproc.Handle 保持完全不同的值,除非 OpenProcess返回的handle是另一种的handle,和proc.Handle不一样(如果是真的很奇怪) .因此,如果我目前怀疑的是真的,那就意味着 OpenProcess 完全不起作用。它在这种情况下根本没用,仍然不确定我们可以在哪种情况下使用它。

您的错误检查被破坏了。 OpenProcess return 一个非零值表示成功。错误代码仅在 OpenProcess 失败时才有意义,即如果 OpenProcess return 为零。

因此,您必须仅在函数调用失败时询问错误代码,如其 return 值所示。您检查错误代码而不检查 return 值,这是一个错误。您的代码应该更像这样:

foreach (var proc in Process.GetProcesses())
{
    var procHandle = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryOperation, false, proc.Id);
    if (procHandle == IntPtr.Zero)
    {
        // api call failed, can read error code
        var eCode = Marshal.GetLastWin32Error();
    }
    else
    {
        // api call succeeded, do stuff with handle
        CloseHandle(procHandle);
    }
}