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

时间:2015-08-31 16:00:41

标签: c# winapi process pinvoke

我尝试使用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);
}

我已经尝试使用Google搜索错误,但不确定这里可能出现的问题。如果你能让我知道什么是错的,那就太好了。谢谢!

更新 正如我所说,它似乎只适用于循环中的第一个进程。但我非常怀疑它实际上甚至不适用于那种情况,因为从我看到procHandle保持与proc.Handle 完全不同的值,除非 < / strong> OpenProcess返回的句柄是句柄的另一种,与proc.Handle不一样(如果是这样,它真的很奇怪)。因此,如果我目前怀疑的是真的,那意味着OpenProcess完全不起作用。在这种情况下,它根本没用,但仍不确定我们可以在哪种情况下使用它。

1 个答案:

答案 0 :(得分:3)

您的错误检查已损坏。 OpenProcess返回非零值表示成功。错误代码仅在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);
    }
}