如何为游戏窗口设置SetWindowDisplayAffinity为WDA_NONE以实现画面捕获?
解决SetWindowDisplayAffinity调用时的权限拒绝问题
出现PermissionError: [WinError 5] Access denied通常是因为Python进程权限不足,或者目标游戏窗口存在进程保护机制,以下是可行的解决思路:
以管理员身份运行脚本
很多游戏默认会以管理员权限启动,如果你的Python脚本权限低于游戏进程,就会被拒绝访问。右键点击你的Python脚本或Python解释器,选择「以管理员身份运行」再尝试执行。启用调试权限(SeDebugPrivilege)
对于一些高权限进程,需要获取调试权限才能修改其窗口属性。可以在代码中添加权限提升逻辑,修改后的完整代码如下:
import ctypes import ctypes.wintypes # 权限相关定义 SE_DEBUG_NAME = "SeDebugPrivilege" TOKEN_ADJUST_PRIVILEGES = 0x0020 TOKEN_QUERY = 0x0008 SE_PRIVILEGE_ENABLED = 0x0002 class LUID(ctypes.Structure): _fields_ = [ ("LowPart", ctypes.wintypes.DWORD), ("HighPart", ctypes.wintypes.LONG) ] class LUID_AND_ATTRIBUTES(ctypes.Structure): _fields_ = [ ("Luid", LUID), ("Attributes", ctypes.wintypes.DWORD) ] class TOKEN_PRIVILEGES(ctypes.Structure): _fields_ = [ ("PrivilegeCount", ctypes.wintypes.DWORD), ("Privileges", LUID_AND_ATTRIBUTES * 1) ] def enable_debug_privilege(): htoken = ctypes.wintypes.HANDLE() # 获取当前进程的令牌 if not ctypes.windll.advapi32.OpenProcessToken( ctypes.windll.kernel32.GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ctypes.byref(htoken) ): return False luid = LUID() # 获取SeDebugPrivilege的LUID if not ctypes.windll.advapi32.LookupPrivilegeValueW( None, SE_DEBUG_NAME, ctypes.byref(luid) ): ctypes.windll.kernel32.CloseHandle(htoken) return False tp = TOKEN_PRIVILEGES() tp.PrivilegeCount = 1 tp.Privileges[0].Luid = luid tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED # 启用权限 result = ctypes.windll.advapi32.AdjustTokenPrivileges( htoken, False, ctypes.byref(tp), ctypes.sizeof(tp), None, None ) ctypes.windll.kernel32.CloseHandle(htoken) return result != 0 # 先启用调试权限 if not enable_debug_privilege(): print("Failed to enable debug privilege") WDA_NONE = 0x00000000 # No restrictions on window display # Load the user32 DLL user32 = ctypes.WinDLL("user32", use_last_error=True) # 替换成你的游戏窗口标题 game_window_name = "Your Game Window Title" # Find the window handle by its title. The first parameter (class name) is None. hwnd = user32.FindWindowW(None, game_window_name) if hwnd == 0: raise Exception(f"Window with title {game_window_name} not found.") # Call SetWindowDisplayAffinity to set the window's display affinity. result = user32.SetWindowDisplayAffinity(hwnd, WDA_NONE) if result == 0: # If the function fails, raise an error with the last error code. raise ctypes.WinError(ctypes.get_last_error()) print(f"{result=}")
检查游戏的反作弊/保护机制
如果游戏带有VAC、Easy Anti-Cheat(EAC)或其他反作弊系统,这类系统会阻止外部进程修改窗口属性,防止被捕获。这种情况下强行修改可能触发反作弊检测,导致账号封禁,不建议尝试。确认窗口句柄正确性
有时候FindWindowW可能找到同名的其他窗口,导致修改了错误的进程。可以使用Windows自带的Spy++工具(Visual Studio工具集内)定位正确的游戏窗口句柄,或者结合GetWindowThreadProcessId获取进程ID,验证是否为目标游戏的进程ID。
内容的提问来源于stack exchange,提问作者jedrix
相关产品推荐
相关产品推荐

