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

It was probably automatically generated to close it every return path. Not even C programmers were stupid enough to free resources on every path, they use a goto-based cleanup idiom instead.

Of course,

compile against ntdll functions not exposted in the API

probably indicates that the code uses internal NT API functions, which are bound to change and break your code for lolsies at any time in the future.

于 2012-06-02T23:47:11.173 に答える