我想通过
subprocess.Popen
创建一个以挂起状态启动的子进程,以便我可以让它准备好在以后运行。
我在here找到了适用于Linux的解决方案,但找不到适用于Windows的任何解决方案。有谁知道 Windows 上是否有与此等效的程序?
经过更多调查后,我设法创建了一个暂停的进程并稍后恢复它。幸运的是,使用 Popen 和 Windows 创建挂起进程非常简单。
首先,您需要通过运行安装 pywin32:
pip install pywin32
安装 pywin32 后,您可以使用
subprocess.Popen
创建一个挂起的进程:
from win32process import CREATE_SUSPENDED
from subprocess import Popen
pipe = subprocess.Popen(<command>, <**kwargs>, creationflags=CREATE_SUSPENDED)
然而,恢复这个挂起的进程要困难得多,因为它需要一个 PyHandle 来处理挂起的线程。不幸的是,Popen 不会返回为挂起线程打开 PyHandle 所需的线程 ID。作为一种解决方法,我最终对 Popen 的 _execute_child 函数进行了猴子修补,以存储 _winapi.CreateProcess 返回的线程 ID。现在我们有了挂起进程的线程 ID,我们可以恢复线程了。
要恢复挂起的进程,假设您对 Popen 进行了猴子修补以存储线程 ID,请使用:
from win32api import OpenThread, CloseHandle
from win32con import THREAD_SUSPEND_RESUME
from win32process import ResumeThread
thread_handle = OpenThread(THREAD_SUSPEND_RESUME, <inherit handle (T/F)>, pipe.tid)
ResumeThread(thread_handle)
CloseHandle(thread_handle)
如果有人知道一种无需 Monkeypatching _execute_child 即可从 Popen 获取线程 ID 的方法,或者任何更好的挂起和恢复进程的方法,请分享!
资源:
我还为 subprocess.Popen 创建了一个 包装器,如果有人想查看我的具体实现,它会在父进程死亡时杀死子进程。
也许我误解了你问题的一些细节,但我可以轻松做到这一点,甚至无需考虑线程和句柄
例如在暂停状态下启动游戏并注入 dll
import subprocess, psutil
from pyinjector import inject
proc = subprocess.Popen(args="-d3d11",executable="Client-Win64-Shipping.exe",cwd=os.getcwd(),shell=False,creationflags=4)
inject(proc.pid, "dxgi.dll")
psutil.Process(proc.pid).resume()
这正是它应该做的,尽管在我尝试使用反作弊的情况下杀死了该过程。此示例中的重要部分是creationflags=4。我还发现了一堆相互矛盾的答案和奇怪的迂回解决方案,建议您通过在管道中发送单字节消息来恢复进程。也许在某一时刻这是必要的,但在 2024 年
psutil.Process(proc.pid).resume()
就是你所需要的