任务管理器是看不到的,使用Process Explorer可以查看到这个进程。
要使用ShellExecuteEx
来启动进程,你需要从shell32
库导入这个函数,并定义相应的结构体和参数。以下是如何在你的代码中使用ShellExecuteEx
来替代CreateProcess
的示例:
首先,你需要定义SHELLEXECUTEINFO
结构体,并设置适当的参数。然后,使用ShellExecuteEx
函数来启动进程。
步骤1: 定义SHELLEXECUTEINFO
结构体
import ctypes
from ctypes import wintypes
from ctypes.wintypes import DWORD, HANDLE, BOOL, WORD
# 定义 SECURITY_ATTRIBUTES 结构体
class SECURITY_ATTRIBUTES(ctypes.Structure):
_fields_ = [
("nLength", wintypes.DWORD),
("lpSecurityDescriptor", wintypes.LPVOID),
("bInheritHandle", wintypes.BOOL),
]
# 定义 SHELLEXECUTEINFO 结构体
class SHELLEXECUTEINFO(ctypes.Structure):
_fields_ = [
("cbSize", wintypes.UINT),
("fMask", wintypes.UINT),
("hwnd", wintypes.HWND),
("lpVerb", wintypes.LPCWSTR),
("lpFile", wintypes.LPCWSTR),
("lpParameters", wintypes.LPCWSTR),
("lpDirectory", wintypes.LPCWSTR),
("nShow", wintypes.INT),
("hInstApp", wintypes.HINSTANCE),
("lpIDList", wintypes.LPVOID),
("lpClass", wintypes.LPCWSTR),
("hkeyClass", wintypes.HKEY),
("dwHotKey", wintypes.DWORD),
("hIcon", wintypes.HANDLE),
("hProcess", wintypes.HANDLE),
]
步骤2: 加载shell32
库并定义ShellExecuteEx
函数
# 加载 shell32 库
shell32 = ctypes.WinDLL('shell32', use_last_error=True)
# 定义 ShellExecuteEx 函数
ShellExecuteEx = shell32.ShellExecuteExW
ShellExecuteEx.argtypes = [
ctypes.POINTER(SHELLEXECUTEINFO),
]
ShellExecuteEx.restype = wintypes.BOOL
步骤3: 准备参数并调用ShellExecuteEx
# 设置命令和参数
src = r"C:\Users\rkey\Desktop\测试\更换桌面壁纸\change_wallpaper.py"
command = f"cmd.exe /c python {src}"
# 初始化 SHELLEXECUTEINFO 结构体
sei = SHELLEXECUTEINFO()
sei.cbSize = ctypes.sizeof(SHELLEXECUTEINFO)
sei.fMask = 0x00000040 # SEE_MASK_NOCLOSEPROCESS
sei.hwnd = None
sei.lpVerb = None # 不使用动词
sei.lpFile = "cmd.exe"
sei.lpParameters = f"/c {command}"
sei.lpDirectory = None
sei.nShow = 0 # SW_HIDE
sei.hInstApp = 0
# 调用 ShellExecuteEx
if ShellExecuteEx(ctypes.byref(sei)):
print("Process created successfully.")
else:
print("Failed to create process. Error code:", ctypes.get_last_error())
# 等待进程结束
# kernel32.WaitForSingleObject(sei.hProcess, -1)
# 关闭进程句柄
# kernel32.CloseHandle(sei.hProcess)
注意事项
错误处理:添加错误处理代码,以便在命令执行失败时获取更多信息。
进程句柄:ShellExecuteEx函数执行后,sei.hProcess将包含新创建的进程的句柄。你可以使用这个句柄来等待进程结束或关闭句柄。
这样,你就可以使用ShellExecuteEx来启动一个后台进程,而不会挂起。
完整代码:
–
import ctypes
from ctypes import wintypes
from ctypes.wintypes import DWORD, HANDLE, BOOL, WORD
# 定义 SHELLEXECUTEINFO 结构体
class SHELLEXECUTEINFO(ctypes.Structure):
_fields_ = [
("cbSize", wintypes.UINT),
("fMask", wintypes.UINT),
("hwnd", wintypes.HWND),
("lpVerb", wintypes.LPCWSTR),
("lpFile", wintypes.LPCWSTR),
("lpParameters", wintypes.LPCWSTR),
("lpDirectory", wintypes.LPCWSTR),
("nShow", wintypes.INT),
("hInstApp", wintypes.HINSTANCE),
("lpIDList", wintypes.LPVOID),
("lpClass", wintypes.LPCWSTR),
("hkeyClass", wintypes.HKEY),
("dwHotKey", wintypes.DWORD),
("hIcon", wintypes.HANDLE),
("hProcess", wintypes.HANDLE),
]
# 加载 shell32 库
shell32 = ctypes.WinDLL('shell32', use_last_error=True)
# 定义 ShellExecuteEx 函数
ShellExecuteEx = shell32.ShellExecuteExW
ShellExecuteEx.argtypes = [
ctypes.POINTER(SHELLEXECUTEINFO),
]
ShellExecuteEx.restype = wintypes.BOOL
# 设置命令和参数
src = r"C:\Users\rkey\Desktop\测试\更换桌面壁纸\change_wallpaper.py"
command = f"cmd.exe /c python {src}"
# 初始化 SHELLEXECUTEINFO 结构体
sei = SHELLEXECUTEINFO()
sei.cbSize = ctypes.sizeof(SHELLEXECUTEINFO)
sei.fMask = 0x00000040 # SEE_MASK_NOCLOSEPROCESS
sei.hwnd = None
sei.lpVerb = None # 不使用动词
sei.lpFile = "cmd.exe"
sei.lpParameters = f"/c {command}"
sei.lpDirectory = None
sei.nShow = 0 # SW_HIDE
sei.hInstApp = 0
# 调用 ShellExecuteEx
if ShellExecuteEx(ctypes.byref(sei)):
print("Process created successfully.")
else:
print("Failed to create process. Error code:", ctypes.get_last_error())
# 等待进程结束
# kernel32.WaitForSingleObject(sei.hProcess, -1)
# 关闭进程句柄
# kernel32.CloseHandle(sei.hProcess)
–