python创建一个隐藏的后台进程,用于执行指定更换WIn10桌面背景图片的脚本

任务管理器是看不到的,使用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)

 

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注