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

C# OpenProcess无法通过id打开现有进程(上次错误代码:1008)?,c#,winapi,process,pinvoke,C#,Winapi,Process,Pinvoke,我正试图使用OpenProcess通过进程ID打开所有现有进程。但不知何故,它仅在第一次调用时起作用,而在下一次调用中显示,它在报告为1008的错误代码下不起作用(试图引用不存在的令牌) 代码如下: [DllImport("kernel32.dll", SetLastError=true)] public static extern IntPtr OpenProcess(ProcessAccessFlags access, bool inheritHandle, int procId); [Dl

我正试图使用
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);
}
我试着用谷歌搜索错误,但不确定这里可能出了什么问题。如果你能告诉我出了什么问题,那就太好了。谢谢大家!

更新:
正如我所说,它似乎只适用于循环中的第一个过程。但我高度怀疑它实际上甚至对这种情况也不起作用,因为从我所看到的
prochHandle
proc.Handle
保持一个完全不同的值,除非
OpenProcess
返回的句柄是另一种句柄,与
proc.Handle
(如果是这样,那真的很奇怪)因此,如果我目前所怀疑的是真的,那就意味着
OpenProcess
完全不起作用。在这种情况下,它毫无用处,而且仍然不确定我们可以在哪个上下文中使用它。

您的错误检查被破坏。成功通过
OpenProcess
返回一个非零值来表示。错误代码只有在时才有意义de>OpenProcess失败,即
OpenProcess
返回零

因此,您只能在函数调用失败时请求错误代码,如返回值所示。您检查错误代码时没有检查返回值,这是一个错误。您的代码应该更像这样:

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

这似乎很正常。您有两个不同的PID。毫不奇怪,您可以使用其中一个而不是另一个来执行操作。FWIW,您没有
hwnd
。这将是一个窗口句柄。
OpenProcess
返回一个进程句柄。这是一个完全不同的野兽。如果您查看
proc.ProcessName
它失败了什么进程ng on?如果该属性没有提供任何信息,PID是否对应于系统上的有效进程?@DavidHeffernan我不理解你的解释。你说
OpenProcess
返回一个进程句柄,我显然将
hwnd
设置为返回值。那么为什么你还说
hwnd
将是一个进程句柄window?@b foreach循环工作正常,我可以看到不同的进程依次出现。正如我所解释的,它在第二个进程中失败了。在这种情况下,
ProcessName
并不重要。进程名称并不重要,除非它可以帮助您找到错误,如果它指向无效的进程,或者您已经找到的进程没有访问权限,或最近终止的进程,或任何其他事项……此外,
GetLastError
仅在返回句柄为
NULL
(又称
IntPtr.Zero
)时包含扩展错误.返回的句柄是否为空?我在手机上键入时,错误地得到了逻辑。代码现在是准确的。现在它实际上与我尝试的非常接近。事实上,我刚刚再次尝试了它。
OpenProcess
的返回值几乎不是IntPtr.Zero(你可以阅读我在问题下方发布的一些评论)。仅在最后2-3个循环中,它返回
0
,但有时不返回。您可以尝试代码以查看它的运行情况。顺便说一句,我当前的应用目标是32位。不。这里的代码与问题中的代码非常不同。您当然可以看到。它不同,但我以前尝试过,现在又尝试过。目前没有打印结果d(我试着打印
eCode
),因为
prochhandle
从来都不是
IntPtr.Zero
。你应该自己试试。
OpenProcess
可能也有问题,因为有人经历过这一点,当
OpenProcess
返回一个非零值时,在第二条评论中发布了它成功了。