【发布时间】:2017-12-13 11:11:45
【问题描述】:
在 VBA 中使用 .Run 启动 .exe 时,典型的调用可能如下所示:
x = wsh.Run(Command:="program.exe ""argument""", WindowStyle:=0, waitonreturn:=False)
windowStyle=0 理论上应该会导致程序在用户不可见的情况下运行。但是,如果 .exe 中出现您不想让用户看到的弹出窗口怎么办?
windowStyle 输入不会抑制警告消息的出现或向用户显示声明“计算完成”之类的弹出窗口,这通常也会暂停代码,直到弹出窗口被清除。以自动方式清除窗口(即单击“确定”)是微不足道的(请参阅this answer),但对于我作为一个相对初学者来说,从一开始就阻止它出现在用户面前是很困难的。 (即当 .exe 触发弹出窗口时,它对用户是不可见的,然后由 VBA 代码自动关闭)
目前我使用这个函数检测到一个新的弹出窗口的存在(其中sCaption是弹出窗口的名称):
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
sStr = Left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
然后自动关闭它。但它仍然会在屏幕上短暂地向用户闪现。理想情况下,我希望这个 VBA 代码在后台运行,这样用户就可以在运行时继续执行其他任务,而不会被闪烁的框分心。
有没有办法强制 program.exe 的所有窗口(包括弹出窗口)在运行时不可见?
有关更多信息,请参阅我之前关于如何关闭弹出窗口的问题,here。该线程涉及如何防止其出现给用户。
编辑 1
SendKeys 是喜怒无常的,所以当我检测到弹出窗口时,我使用这个循环代码来杀死 .exe,因此 .exe 不需要聚焦来关闭弹出窗口(关闭弹出窗口会杀死.exe 在我的情况下):
....
Main Code Body
....
t = Now
waittime = Now + TimeValue("0:01:30") 'limit to run a single row of calculations
Do While t < waittime
If GetHandleFromPartialCaption(lhWndP, "Popup Window Text") = True Then
Set oServ = GetObject("winmgmts:")
Set cProc = oServ.ExecQuery("Select * from Win32_Process")
For Each oProc In cProc
If oProc.Name = "Program.exe" Then
errReturnCode = oProc.Terminate()
Marker2 = 1
Exit Do
End If
Next
Endif
Loop
....
Main Code Body Continues
....
其中GetHandleFromPartialCaption() 是上面的函数,根据 sCaption 参数查找弹出窗口。我的代码在 .exe 运行计算时不断循环并搜索弹出窗口,并在 .exe 出现时立即终止它。但它仍然会闪现给用户。
【问题讨论】:
-
即使您不显示弹出窗口,它也需要有焦点才能使用
SendKeys关闭它。这意味着您的用户会在他或她正在做的事情中被打断,例如,如果他或她正在打字。 -
我使用
Terminate()来杀死.exe 而不是SendKeys,因为它太喜怒无常并且不断打开和关闭numlock。请参阅上面我的帖子中的编辑 1。 -
我不是 100% 确定,但是如果强制您的电子表格始终位于所有其他窗口之上呢?并使用诸如 application.displayalerts = false 之类的东西来阻止提示出现(这些提示不会在您的电子表格之外,但可能会有所帮助)
-
@QHarr 请不要更改其中包含拼写错误的代码,除非您绝对确定 OP 在将代码从 IDE 转录到问题时犯了错误。代码中的拼写错误可能是问题的确切原因。
-
@TylerH 注意到虽然代码编译时不会出现该错误,这就是为什么我觉得将简单的 Thenn 更改为 Then 是安全的。
标签: vba excel hidden window-style