我有一个Jenkins管道,它在远程服务器上执行一个程序,该程序使用pywin来操作应用程序进行功能测试。
当我使用远程桌面时,我的应用程序运行良好,但当我关闭远程桌面并从Jenkins运行时,应用程序会丢失。
我所做的是打开应用并发送回车键。
这是我的应用:
os.startfile("C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe")
time.sleep(5)
handle = win32gui.FindWindow(0, "SAP Logon 740")
keyboard = Controller()
keyboard.press(Key.enter)
所以我尝试将焦点添加到应用程序以强制关注但没有成功:
os.startfile("C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe")
time.sleep(5)
handle = win32gui.FindWindow(0, "SAP Logon 740")
win32gui.ShowWindow(handle, 5)
win32gui.SetForegroundWindow(handle)
keyboard = Controller()
keyboard.press(Key.enter)
我将按键更改为相同的结果:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('{ENTER}')
我尝试更改为pywinauto尝试单击按钮而不是发送回车,但我发现更多问题,因为pywinauto无法识别我的应用程序标题:
app = Application().start("C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe")
app["SAP Logon 740"] # this doesn't work
app.top_window_() # this doesn't work either
handle = win32gui.FindWindow(0, "SAP Logon 740")
sapApp = app.window_(handle = handle) #Finally this works but...
sapApp["Log &On"].click() # This doesn't work
sapApp.log_on.Click() # This doesn't work
我得到了这个例外:
ctypes.ArgumentError: argument 2: <class 'TypeError'>: expected LP_c_ulong instance instead of pointer to c_long
我知道这个名字是因为我试过了:
print(sapApp.descendants(control_type="MenuBar"))
得到了这个结果:
[<win32_controls.ButtonWrapper - 'Log &On', Button, 14221798>, ...]
所以我知道这个按钮的名称,但是没有能够点击它。
我也尝试将焦点设置到应用程序,结果相同:
sapApp.SetFocus()
随着远程桌面oppened一切正常但它已关闭我的应用程序没有输入
以前有人有这个问题吗?我没想到还能尝试什么呢?
由于
修改
这是ctypes错误的完整描述:
File "e:\Jenkins\workspace\my-project\scripts\test_pywin.py", line 23, in <module> sapApp.log_on.Click()
File "E:\Python_V365\lib\site-packages\pywinauto\controls\hwndwrapper.py", line 725, in click self.verify_actionable()
File "E:\Python_V365\lib\site-packages\pywinauto\base_wrapper.py", line 591, in verify_actionable self.wait_for_idle()
File "E:\Python_V365\lib\site-packages\pywinauto\controls\hwndwrapper.py", line 710, in wait_for_idle win32functions.WaitGuiThreadIdle(self)
File "E:\Python_V365\lib\site-packages\pywinauto\win32functions.py", line 283, in WaitGuiThreadIdle GetWindowThreadProcessId(handle, ctypes.byref(process_id))
ctypes.ArgumentError: argument 2: <class 'TypeError'>: expected LP_c_ulong instance instead of pointer to c_long
还尝试(后端=&#34; uia&#34;)以相同的结果启动应用程序:
app = Application(backend="uia").start("C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe")
启动程序后尝试连接会给我这个错误:
app = Application().connect(title="SAP Logon 740", timeout=10)
File "e:\Jenkins\workspace\tacion_BehaveImplementation-637TPHZXXSFG4MVWWWJCBSJOWSAVPZMPOYFKFKNYKRT5XRBIZFBQ\scripts\test_pywin.py", line 12, in <module> app = Application().connect(title="SAP Logon 740", timeout=10)
File "E:\Python_V365\lib\site-packages\pywinauto\application.py", line 944, in connect self.process = findwindows.find_element(**kwargs).process_id
File "E:\Python_V365\lib\site-packages\pywinauto\findwindows.py", line 84, in find_element elements = find_elements(**kwargs)
TypeError: find_elements() got an unexpected keyword argument 'timeout'
这最终有效:
app = Application().connect(title="SAP Logon 740", backend="uia")
sapApp = app["SAP Logon 740"]
但是发现问题实际上是我需要等待应用程序完全加载所以这也有效:
app = Application().start("C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe")
time.sleep(5)
app["SAP Logon 740"]
但是按钮仍然存在同样的问题
答案 0 :(得分:1)
远程桌面的问题不依赖于该工具。 RDP本身在最小化或断开连接时不保留GUI上下文(当操作系统被锁定时会发生相同的效果)。但是这些症状通常涉及.click_input()
和.type_keys() / keyboard.SendKeys()
方法,这些方法在没有GUI上下文的情况下无效。
最小化RDP问题的解决方法:
将RDP切换到窗口模式(非全屏),在那里运行脚本并快速切换到本地计算机。现在你可以正常工作了。这是手动运行的最简单方法。
在本地的远程计算机(我使用TightVNC)和VNC客户端(也称为TightVNC)上安装VNC服务器软件。如果您看到黑屏,则可能需要更新远程计算机上的视频卡驱动程序。如果至少使用一次RDP,则还必须重新启动远程主机。主要好处:您甚至可以从远程主机断开连接,但TightVNC将始终保持GUI上下文。这更适合自动运行(Jenkins代理必须在此活动桌面中运行,它根本不能作为服务运行)。像Citrix这样的另一个虚拟桌面环境也可以用于此目的,但我没有个人经验。
RDP(mstsc
命令)有一些参数可以从当前连接解除虚拟远程桌面的绑定(现在不记得了)。用于自动远程运行的其他工具可能包括psexec
或Ansible with psexec插件。
如果找不到此应用程序的主窗口(进程PID),则saplogon.exe
可能会生成具有目标窗口的另一个进程。然后,您必须app = Application().connect(title="SAP Logon 740", timeout=10)
与正确的进程ID绑定。这对于这样的发射器来说是非常普遍的问题。
ctypes.ArgumentError
更有趣。请提供错误的完整回溯。我怀疑这可以在pywinauto方面修复。可能会发生这种错误,因为其他Python库使用ctypes
方式不正确,但可能会有问题。
如果使用默认的“win32”后端无法找到LogOn按钮,您可以尝试Application(backend="uia").connect(...)
。差异在Getting Started Guide。
答案 1 :(得分:0)
如果我了解您的问题(也是我的问题),可以在此处找到正确的答案:
(此链接来自此页面:Remote Execution Guide in pywinauto)
确切的操作过程,如页面中所述:
要断开与远程桌面的连接,请在 远程计算机(在“远程桌面”窗口中)作为管理员:
%windir%\ System32 \ tscon.exe RDP-Tcp#NNN / dest:console
其中RDP-Tcp#NNN是当前远程桌面会话的ID, 例如,RDP-Tcp#0。您可以在Windows任务管理器上看到它 “会话”列中的“用户”标签。
您将看到“您的远程桌面会话已结束”消息,并且 远程桌面客户端将关闭。但是所有的程序和测试 远程计算机将继续正常运行。
我只是对其进行测试,所以可以正常工作。