在 VBA shell 命令中使用 AppActivate 和 Sendkeys
我想使用 VBA 中的 shell 命令在应用程序之间来回切换。 我正在使用 SendKeys 在进程 A 中执行操作,然后移动到进程 B,然后处理 A,然后处理 B。它对于第一次迭代运行良好。当我使用 AppActivate 返回进程 B 时,它实际上确实将焦点切换回进程 B。但是,它忽略了来自 SendKeys 的后续命令。
示例代码:
Sub pastePDF2TXT_v3(pdfName As String, txtName As String)
Dim acrobatID
Dim acrobatInvokeCmd As String
Dim acrobatLocation As String
Dim notepadID
Dim acrobatID2
Dim notepadID2
Debug.Print "here"
acrobatLocation = "C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Acrobat.exe"
acrobatInvokeCmd = acrobatLocation & " " & pdfName
acrobatID = Shell(acrobatInvokeCmd, 1)
AppActivate acrobatID
SendKeys "^a", True '^A selects everything already in the pdf file.
SendKeys "^c", True '^C copies the selection to the clipboard.
notepadID = Shell("NOTEPAD.EXE " & txtName, 1) ' invoke notepad on the text file.
AppActivate notepadID ' set the new app as teh active task.
SendKeys "^a", True '^A selects everything already in the text file.
SendKeys "^v", True '^V pastes the new stuff over the top of the old text file (deleting the old stuff)
SendKeys "%{END}", True ' makre sure last line of text file
SendKeys "{ENTER}", True
AppActivate acrobatID ' NOTE: APPEARS TO WORK UP TO THIS POINT.
SendKeys "{ENTER}", True ' NOTE: SECOND APP IGNORES SUBSEQUENT COMMANDS FROM HERE DOWN.
SendKeys "^a", True '^A selects everything already in the pdf file.
SendKeys "^c", True '^C copies the selection to the clipboard.
SendKeys "%f", True 'alt f, x to exit Notepad.exe
SendKeys "x", True
'acrobatID.Quit
Debug.Print "start second"
AppActivate notepadID ' set the new app as teh active task.
SendKeys "%{END}", True 'Go to end of text file.
SendKeys "^v", True '^V pastes the new stuff at end of file.
SendKeys "{ENTER}", True
SendKeys "^s", True
SendKeys "%f", True 'alt f, x to exit Notepad.exe
SendKeys "x", True
notepadID.Quit
acrobatID.Quit
End Sub
I want to switch back and forth between application with the shell command in VBA.
I am using SendKeys to do stuff in process A then move to process B, then to process A then process B. It works fine for the first iteration. When I use AppActivate to go back to process B, it actually does switch focus back to process B. HOWEVER, it ignores subsequent commands from SendKeys.
Example code:
Sub pastePDF2TXT_v3(pdfName As String, txtName As String)
Dim acrobatID
Dim acrobatInvokeCmd As String
Dim acrobatLocation As String
Dim notepadID
Dim acrobatID2
Dim notepadID2
Debug.Print "here"
acrobatLocation = "C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Acrobat.exe"
acrobatInvokeCmd = acrobatLocation & " " & pdfName
acrobatID = Shell(acrobatInvokeCmd, 1)
AppActivate acrobatID
SendKeys "^a", True '^A selects everything already in the pdf file.
SendKeys "^c", True '^C copies the selection to the clipboard.
notepadID = Shell("NOTEPAD.EXE " & txtName, 1) ' invoke notepad on the text file.
AppActivate notepadID ' set the new app as teh active task.
SendKeys "^a", True '^A selects everything already in the text file.
SendKeys "^v", True '^V pastes the new stuff over the top of the old text file (deleting the old stuff)
SendKeys "%{END}", True ' makre sure last line of text file
SendKeys "{ENTER}", True
AppActivate acrobatID ' NOTE: APPEARS TO WORK UP TO THIS POINT.
SendKeys "{ENTER}", True ' NOTE: SECOND APP IGNORES SUBSEQUENT COMMANDS FROM HERE DOWN.
SendKeys "^a", True '^A selects everything already in the pdf file.
SendKeys "^c", True '^C copies the selection to the clipboard.
SendKeys "%f", True 'alt f, x to exit Notepad.exe
SendKeys "x", True
'acrobatID.Quit
Debug.Print "start second"
AppActivate notepadID ' set the new app as teh active task.
SendKeys "%{END}", True 'Go to end of text file.
SendKeys "^v", True '^V pastes the new stuff at end of file.
SendKeys "{ENTER}", True
SendKeys "^s", True
SendKeys "%f", True 'alt f, x to exit Notepad.exe
SendKeys "x", True
notepadID.Quit
acrobatID.Quit
End Sub
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我知道这个问题很旧,但我也遇到过同样的问题,但我认为选择的答案不是正确的。
当您调用 AppActivate 时,脚本将停止,等待目标应用程序终止。应用程序终止后,脚本将继续运行。我认为这个问题没有解决办法。
编辑:
我使用批处理文件为 AppActivate 命令调用 CSCRIPT,并且我注意到您严格使用 VBS 文件。尝试将
CMD
作为新窗口调用,并传递CSCRIPT //NoLogo //B WScript.CreateObject("WSCript.shell").AppActivate("Window Name")
作为论证,看看是否绕过了问题。I know this question is old, but I have run into this same problem, but I don't think the answer that was chosen is the correct one.
When you call AppActivate, the script goes on halt, waiting for the target application to terminate. After the application is terminated, the script continues. I see no solution to this issue.
EDIT:
I use a batch-file to call CSCRIPT for the AppActivate command, and I notice you are strictly using a VBS file. Try calling
CMD
as a new window and passCSCRIPT //NoLogo //B WScript.CreateObject("WSCript.shell").AppActivate("Window Name")
as the argument, and see if that bypasses the issue.同样,我尝试对使用 shell 命令打开的 pdf 文档使用 AppActivate,以便我可以在其上使用 SendKeys。它总是会生成运行时错误“5”。我的解决方案最终是根本不使用 AppActivate,事实上打开文档无论如何都会将其带到最前面。问题是 SendKeys 语句在 shell 命令之后立即执行,但 pdf 需要一两秒钟才能打开。我的解决方案是在执行 sendkeys 语句之前暂停代码几秒钟。
我使用了延迟屈膝的方法。在这里查看线程:
http://www.dbforums.com/microsoft-access/1219379 -时间延迟-vba.html
Similarly, I was trying to use AppActivate on a pdf document I had opened with a shell command so that I could use SendKeys on it. It would always generate Run Time Error '5'. My solution, eventually was to NOT use AppActivate at all, in fact opening the document brings it to the forefront anyway. The problem is that the SendKeys statement executes immediately after the shell command but the pdf needs a second or two to open up. My solution is to pause the code for a couple seconds before excuting the sendkeys statement.
I used a time delay curtosy of pootle flump. Check out the thread here:
http://www.dbforums.com/microsoft-access/1219379-time-delay-vba.html
经过在各个论坛上进行数小时的研究后,我发现我无法通过 Adobe Reader 使用 Adobe 库对象和函数。剩下的唯一可行的选择是使用 Shell 命令来使用 Adobe Reader 文件菜单中提供的“另存为文本”选项。快捷键为Alt+f+a+x+s。我在下面的代码中实现了这些,尽管我需要在某些步骤中插入延迟,但它运行得很好。
After hours of research on various forums, I could figure out that I wont be able to use Adobe library objects and functions with Adobe Reader. The only viable option left was to use Shell Commands to use "save as text" option available in the Adobe Reader's file menu. The shortcut key is Alt+f+a+x+s. I implemented these in the below code which worked perfectly, although I was required to insert delays in some steps.
这可能更像是一条评论,而不是一个答案,但我似乎不被允许“评论”,所以……
你能走到这一步真是令人惊讶。很有可能,你永远无法可靠地完成这项工作——就这样。一旦你让它工作起来,在未来的版本中,Acrobat UI 的行为方式就会发生一些变化,或者 Windows 将会对哪些东西可以向其他东西发送事件的规则进行另一次更改,然后你再次陷入困境。
在这种情况下,您可能遇到的情况是,当用户显然正忙于与第一个应用程序交互时,Windows 试图阻止某个应用程序从另一个应用程序中窃取焦点。在尝试执行诸如在一个应用程序中使用按钮将数据写入临时文件并打开 MS Word 进行编辑之类的操作时,您会看到相同类型的问题。 Windows 会阻止焦点从当前应用程序转移到 MS Word,因为您刚刚单击了当前应用程序中的按钮。
因此,我们不要试图解决这个不可能的技术问题,而是退后一步,问一下您最初希望通过执行所有这些操作来实现什么目标。通过这种方式,也许我们可以带您到达您想去的地方:)
This might be more of a comment than an answer, but I don't seem to be allowed to "comment", so...
It's amazing you've gotten as far as you did. Chances are, you're never going to be able to make this work reliably -- period. As soon as you do make it work, something will change about how the Acrobat UI behaves in a future release, or Windows will make another change to the rules for what things can send events to what other things, and then you're hosed again.
What you are probably running into in this case is Windows trying to prevent an application stealing the focus from another when a user is apparently busy interacting with the first one. You see the same kinds of problems trying to do things like have a button in one application write data to a temporary file and open MS Word to edit it. Windows prevents the focus from transferring away from the current app and over to MS Word because you just clicked a button in the current app.
So -- instead of trying to solve this impossible technical issue, let's take a step back and ask what you were originally hoping to accomplish by doing all of this. In that way, perhaps, we can get you where you're trying to go :)
尝试
发送键“%{tab}”
切换窗口
但只保留 2 个活动窗口。
或尝试
appactivate 仅在 sendkeys {Tab} 之后,以便在 switchibg windows cmd 之前不会选择文本输入框。
或尝试
尝试 appactivate 窗口名称,1
然后睡眠 2000°,以便有时间让该窗口成为焦点
Try
sendkeys "%{tab}"
to switch windows
but then keep only 2 active windows.
or try
appactivate only after sendkeys {Tab} so that text entry box is not selected before switchibg windows cmd.
or try
try appactivate window name, 1
then sleep 2000 °to allow time to bring that window into focus
您忘记在每个发送键之间添加“DoEvents”和某种延迟/等待时间,以给它一些执行时间。
You forgot to add "DoEvents" between each sendkeys and kind of delay/wait period, to give it some time to execute.