Cover Story
В принципе меня все устраивает, но если не сложно посмотрите пожалуйста скрипт, может его можно будет как-нибудь оптимизировать?
Перед тем как начинать оптимизировать нужно убедиться, что все правильно работает. С программированием на Python'е это мало связано, но тем не мене….
Поиск процесса по имени. Положим у Вас запущены пара десятков python-скриптов и Вы ищите процесс с именем Python, что Вы найдете?
Завершение работы процесса. Вы тупо прибиваете процесс, совершенно не заботясь при этом о дочерних процессах, об используемых ресурсах и т.д. и т.п. Думаю перед тем как прибить процесс, можно было бы хотя бы попытаться корректно завершить его работу
прикрепить файл так и не получается, поэтому, да простят меня модераторы, положу код здесь.
поиска по имени у меня нет, потому как задачи такой не было, процесс я сам запускал и, соответственно ID процесса всегда был под рукой
import os, sys
import threading
import win32process
import win32file, win32con, win32api
import pywintypes
from ctypes import windll, Structure, sizeof, byref
from ctypes import c_int, c_ulong, c_char
from ctypes import POINTER, WINFUNCTYPE
from time import sleep
#####################################################################################
TH32CS_SNAPHEAPLIST = 0x01L
TH32CS_SNAPPROCESS = 0x02L
TH32CS_SNAPTHREAD = 0x04L
TH32CS_SNAPMODULE = 0x08L
TH32CS_SNAPMODULE32 = 0x10L
TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST|TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)
TH32CS_INHERIT = 0x80000000
INVALID_HANDLE_VALUE = 0
ERROR_SUCCESS = 0
#####################################################################################
thelp_sema = threading.Semaphore()
#####################################################################################
## декларируем используемые функции WinAPI
CreateToolhelp32Snapshot = windll.kernel32.CreateToolhelp32Snapshot
Process32First = windll.kernel32.Process32First
Process32Next = windll.kernel32.Process32Next
GetCurrentProcessId = windll.kernel32.GetCurrentProcessId
OpenProcess = windll.kernel32.OpenProcess
TerminateProcess = windll.kernel32.TerminateProcess
WaitForSingleObject = windll.kernel32.WaitForSingleObject
EnumWindows = windll.user32.EnumWindows
IsWindowVisible = windll.user32.IsWindowVisible
GetDesktopWindow = windll.user32.GetDesktopWindow
PostMessage = windll.user32.PostMessageA
SendMessageTimeout = windll.user32.SendMessageTimeoutA
#####################################################################################
class PROCESSENTRY32 (Structure) :
_fields_ = [("dwSize", c_ulong),
("cntUsage", c_ulong),
("th32ProcessID", c_ulong),
("th32DefaultHeapID", c_ulong),
("th32ModuleID", c_ulong),
("cntThreads", c_ulong),
("th32ParentProcessID", c_ulong),
("pcPriClassBase", c_ulong),
("dwFlags", c_ulong),
("szexeFile", c_char * 260)]
class CSEARCH (Structure) :
_fields_ = [("pid", c_ulong),
("wnd", c_ulong)]
def GetProcessList () :
""" Возвращает список кортежей (Имя exe'шника, ID процесса, число потоков) """
pe32 = PROCESSENTRY32()
pe32.dwSize = sizeof(PROCESSENTRY32)
result = []
thelp_sema.acquire()
try :
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
flag = Process32First(snapshot, byref(pe32))
while flag :
result.append((pe32.szexeFile, pe32.th32ProcessID, pe32.cntThreads))
flag = Process32Next(snapshot, byref(pe32))
win32file.CloseHandle(snapshot)
finally :
thelp_sema.release()
return result
def StartProcess (path, params, work_dir, wait=0) :
""" запуск процесса, думаю имена параметров говорят сами за себя
wait - пауза перед запуском в секундах """
if wait : sleep(wait)
si = win32process.STARTUPINFO()
sa = pywintypes.SECURITY_ATTRIBUTES()
si.wShowWindow = win32con.SW_SHOWNORMAL
try :
hProcess, hThread, dwProcessId, dwThreadId = win32process.CreateProcess(
None, len(params) > 0 and path + " " + params or path,
sa, sa, True, win32con.NORMAL_PRIORITY_CLASS, None,
work_dir, si
)
except pywintypes.error, why :
raise Exception(why[2])
else :
win32file.CloseHandle(hProcess)
win32file.CloseHandle(hThread)
return dwProcessId
def __kill_process (pid) :
hProcess = OpenProcess(win32con.PROCESS_TERMINATE, False, pid)
result = TerminateProcess(hProcess, -1)
if result :
result = ERROR_SUCCESS
else :
result = win32api.GetLastError()
win32file.CloseHandle(hProcess)
return result
def __kill_process_tree (pid) :
pe32 = PROCESSENTRY32()
pe32.dwSize = sizeof(PROCESSENTRY32)
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
flag = Process32First(snapshot, byref(pe32))
while flag :
if pe32.th32ParentProcessID == pid :
__kill_process_tree(pe32.th32ProcessID)
pe32.dwSize = sizeof(PROCESSENTRY32)
flag = Process32Next(snapshot, byref(pe32))
win32file.CloseHandle(snapshot)
return __kill_process(pid)
def KillProcess (pid) :
""" тупое 'убийство' процесса и всех его дочерних процессов """
dwError = -1
thelp_sema.acquire()
try :
dwError = __kill_process_tree(pid)
finally :
thelp_sema.release()
if dwError == ERROR_SUCCESS :
return True, ""
else :
return False, win32api.FormatMessage(dwError)
def IsMainWindow (wnd) :
""" по хендлу окна определяем, является ли оно главным окном приложения """
parent = win32api.GetWindowLong(wnd, win32con.GWL_HWNDPARENT)
style = win32api.GetWindowLong(wnd, win32con.GWL_EXSTYLE)
return (parent == 0 or parent == GetDesktopWindow()) and \
((style & win32con.WS_EX_TOOLWINDOW) == 0 or (style & win32con.WS_EX_APPWINDOW) != 0)
def GetMainWndFromPid (pid) :
""" ищем главное окно по ID процесса"""
def enum_windows (wnd, sr) :
tid, pid = win32process.GetWindowThreadProcessId(wnd)
if pid == sr.contents.pid and IsMainWindow(wnd) :
sr.contents.wnd = wnd
return False
else : return True
CBF = WINFUNCTYPE(c_int, c_ulong, POINTER(CSEARCH))
EnumWindowsProc = CBF(enum_windows)
sr = CSEARCH()
sr.pid = pid
sr.wnd = 0
EnumWindows(EnumWindowsProc, byref(sr))
return sr.wnd
def IsWindowResponding (wnd, timeout) :
""" примитивная проверка "живучести" процесса """
result = c_ulong(0)
return SendMessageTimeout(wnd, win32con.WM_NULL, 0, 0,
win32con.SMTO_ABORTIFHUNG, timeout, byref(result)) != 0
def TerminateApplication (pid, timeout) :
""" Завершение работы процесса.
пытаемся корректно завершить работу, если не получается, тупо прибиваем """
def enum_windows (wnd, ppid) :
tid, pid = win32process.GetWindowThreadProcessId(wnd)
if pid == ppid :
PostMessage(wnd, win32con.WM_CLOSE, 0, 0)
return True
if pid == GetCurrentProcessId() : return False
result = False
hProcess = OpenProcess(win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE, False, pid)
if hProcess :
CBF = WINFUNCTYPE(c_int, c_ulong, c_ulong)
EnumWindowsProc = CBF(enum_windows)
try :
EnumWindows(EnumWindowsProc, pid)
except :
win32file.CloseHandle(hProcess)
return False
if WaitForSingleObject(hProcess, timeout) == win32con.WAIT_OBJECT_0 :
result = True
win32file.CloseHandle(hProcess)
if not result :
result, msg = KillProcess(pid)
return result