如何使用ctypes通过名称查找并终止进程?

5
在Windows系统中,我想通过ctypes而非其他第三方模块查找名称为'exename.exe'的进程并将其终止。

2
调用EnumProcesses,然后终止进程。 - David Heffernan
你了解ctypes吗?在我尝试编写能够实现此功能的代码之前,我想先了解一下你对它的了解程度。 - David Heffernan
@David Heffernan -- 抱歉,我只了解一些关于ctypes的知识,但我几乎不知道如何使用ctypes来调用高级Windows API。希望您能指导我如何使用ctypes。谢谢。 - Synapse
2个回答

9

试试这个:

import sys, os.path, ctypes, ctypes.wintypes

Psapi = ctypes.WinDLL('Psapi.dll')
EnumProcesses = Psapi.EnumProcesses
EnumProcesses.restype = ctypes.wintypes.BOOL
GetProcessImageFileName = Psapi.GetProcessImageFileNameA
GetProcessImageFileName.restype = ctypes.wintypes.DWORD

Kernel32 = ctypes.WinDLL('kernel32.dll')
OpenProcess = Kernel32.OpenProcess
OpenProcess.restype = ctypes.wintypes.HANDLE
TerminateProcess = Kernel32.TerminateProcess
TerminateProcess.restype = ctypes.wintypes.BOOL
CloseHandle = Kernel32.CloseHandle

MAX_PATH = 260
PROCESS_TERMINATE = 0x0001
PROCESS_QUERY_INFORMATION = 0x0400

count = 32
while True:
    ProcessIds = (ctypes.wintypes.DWORD*count)()
    cb = ctypes.sizeof(ProcessIds)
    BytesReturned = ctypes.wintypes.DWORD()
    if EnumProcesses(ctypes.byref(ProcessIds), cb, ctypes.byref(BytesReturned)):
        if BytesReturned.value<cb:
            break
        else:
            count *= 2
    else:
        sys.exit("Call to EnumProcesses failed")

for index in range(BytesReturned.value / ctypes.sizeof(ctypes.wintypes.DWORD)):
    ProcessId = ProcessIds[index]
    hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, False, ProcessId)
    if hProcess:
        ImageFileName = (ctypes.c_char*MAX_PATH)()
        if GetProcessImageFileName(hProcess, ImageFileName, MAX_PATH)>0:
            filename = os.path.basename(ImageFileName.value)
            if filename == 'notepad.exe':
                TerminateProcess(hProcess, 1)
        CloseHandle(hProcess)

1
顺便问一下,你能推荐我一些关于ctypes和Python的书籍或项目吗?这样我就可以深入学习并提高我的编程水平。我是一名大一新生,刚开始学习Python,我发现它非常有趣。 - Synapse
我最喜欢学习Python的书是Learning Python。我认为你不会找到任何关于ctypes的印刷材料,因为它是如此专业的主题。 - David Heffernan

9
这可能算作弊,但即使没有涉及ctypes也可以运行。
import subprocess
subprocess.call("taskkill /IM exename.exe")

taskkill 是 Windows 命令;这里只是通过 Python 调用它。


这是一个超级优雅的解决方案!人们往往会忘记你可以从Python内部运行任意进程。+1 - Chinmay Kanchi
2
我当然不排斥这样做,但这与优雅相反!ctypes代码很丑陋,但它直接调用操作系统例程而不是构建/解析/运行/拆除另一个程序来完成此操作。 - Gringo Suave
这是关于编程的内容,翻译成中文如下:这更加优雅,因为ctypes代码依赖于比其他东西(命令行应用程序)更容易改变的东西(内部),而Windows通常会保持稳定以便将其集成到PowerShell中。 - Erik Aronesty
请注意:
  • 不带 /f(强制)的 taskkill 命令将请求关闭而非终止进程,因此可能无法真正终止该进程
  • taskkill 命令还会输出到 stdout,这可能不是您想要的
  • 如果进程未运行或无法杀死进程,则它会报告非零错误代码
  • 在任一情况下,退出代码相同,但错误消息可能因用户语言环境而异。
- Nick Desjardins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接