0

我正在尝试使用 ctypes 重新创建在 psutil 项目(https://code.google.com/p/psutil/)上找到的一些功能。使用 psutil 对于我想要的东西来说太过分了,这只是检查给定的 pid 当前是否正在运行。

我试图重新创建的代码片段是pid_is_running 函数

int
pid_is_running(DWORD pid)
{
    HANDLE hProcess;
    DWORD exitCode;

    // Special case for PID 0 System Idle Process
    if (pid == 0) {
        return 1;
    }

    if (pid < 0) {
        return 0;
    }

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                           FALSE, pid);
    if (NULL == hProcess) {
        // invalid parameter is no such process
        if (GetLastError() == ERROR_INVALID_PARAMETER) {
            CloseHandle(hProcess);
            return 0;
        }

        // access denied obviously means there's a process to deny access to...
        if (GetLastError() == ERROR_ACCESS_DENIED) {
            CloseHandle(hProcess);
            return 1;
        }

        CloseHandle(hProcess);
        PyErr_SetFromWindowsErr(0);
        return -1;
    }

    if (GetExitCodeProcess(hProcess, &exitCode)) {
        CloseHandle(hProcess);
        return (exitCode == STILL_ACTIVE);
    }

    // access denied means there's a process there so we'll assume it's running
    if (GetLastError() == ERROR_ACCESS_DENIED) {
        CloseHandle(hProcess);
        return 1;
    }

    PyErr_SetFromWindowsErr(0);
    CloseHandle(hProcess);
    return -1;
}

我不明白为什么代码要关闭 NULL 句柄。这真的有必要吗?它是错误的还是可能导致错误?

我也很感激任何关于我到目前为止能想出的意见

import os
import shlex
import subprocess
import ctypes as c
import ctypes.wintypes as w

PROCESS_QUERY_INFORMATION   = 0x0400L
PROCESS_VM_READ             = 0x0010L             
ERROR_INVALID_PARAMETER     = 0x57L
ERROR_ACCESS_DENIED         = 0x5L
STILL_ACTIVE                = 0x103L
FALSE                       = 0L

def start(cmd):
    l = shlex.split(cmd)
    return subprocess.Popen(l).pid

def get_pid(hProcess):
    pid = w.DWORD()
    return c.windll.kernel32.GetProcessId(hProcess);

def pid_is_running(pid):
    # adapted from psutil library 
    # http://code.google.com/searchframe#Dnjw9wRLlM4/trunk/psutil/arch/mswindows/process_info.c&q=pid_is_running%20package:psutil\.googlecode\.com&l=150

    pid         = w.DWORD(pid)
    hProcess    = w.HANDLE()

    if pid.value == 0L:
        return True

    if pid.value < 0L:
        return False

    flags = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
    hProcess = c.windll.kernel32.OpenProcess(flags, FALSE, pid)
    try:
        if 0 == hProcess:
            # invalid parameter is no such process
            last_error = c.windll.kernel32.GetLastError()
            if last_error == ERROR_INVALID_PARAMETER:
                return False

            # access denied obviously means there's a process to deny access to...
            if last_error == ERROR_ACCESS_DENIED:
                return True
            #return -1 #  Error? Should I throw an exception
            raise Exception('Could not find process and an error occurred')
        else:
            exitCode = w.DWORD()    
            if c.windll.kernel32.GetExitCodeProcess(hProcess, c.byref(exitCode)):
                return exitCode.value == STILL_ACTIVE

            # access denied means there's a process there so we'll assume it's running
            if c.windll.kernel32.GetLastError() == ERROR_ACCESS_DENIED:
                return True
            #return -1 #  Error? Should I throw an exception
            raise Exception('Process found and an error occurred')
    finally:
        if hProcess != 0:
            c.windll.kernel32.CloseHandle(hProcess)
4

1 回答 1

1

它可能是自动生成的,以在每个返回路径上关闭它。甚至 C 程序员也不会愚蠢到在每条路径上释放资源,而是使用基于 goto 的清理习惯用法。

当然,

针对 API 中未公开的 ntdll 函数进行编译

可能表明该代码使用了内部 NT API 函数,这些函数必然会在将来的任何时候更改和破坏您的代码。

于 2012-06-02T23:47:11.173 回答