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)