在 VBA shell 命令中使用 AppActivate 和 Sendkeys

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4675281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 11:04:37  来源:igfitidea点击:

Using AppActivate and Sendkeys in VBA shell command

shellvbasendkeys

提问by elbillaf

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.

我想在 VBA 中使用 shell 命令在应用程序之间来回切换。我正在使用 SendKeys 在进程 A 中执行操作,然后移动到进程 B,然后处理 A,然后处理 B。它在第一次迭代中工作正常。当我使用 AppActivate 返回进程 B 时,它实际上确实将焦点切换回进程 B。但是,它会忽略来自 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

采纳答案by Steve Jorgensen

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.

令人惊讶的是,您已经取得了如此大的成就。很有可能,您永远无法使这项工作可靠地工作 - 期间。一旦你让它工作,关于 Acrobat UI 在未来版本中的行为方式会发生一些变化,或者 Windows 将对哪些事物可以将事件发送到哪些其他事物的规则进行另一次更改,然后你又被灌输了.

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.

在这种情况下,您可能遇到的是 Windows 试图防止应用程序在用户显然忙于与第一个应用程序交互时从另一个应用程序窃取焦点。您会在尝试执行某些操作时遇到相同类型的问题,例如在一个应用程序中使用按钮将数据写入临时文件并打开 MS Word 进行编辑。Windows 会阻止焦点从当前应用转移到 MS Word,因为您只是单击了当前应用中的一个按钮。

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 :)

因此,与其尝试解决这个不可能的技术问题,不如让我们退后一步,问问您最初希望通过完成所有这些来完成什么。那样的话,也许我们可以带你去你想去的地方:)

回答by Mechaflash

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.

当您调用 AppActivate 时,脚本会暂停,等待目标应用程序终止。应用程序终止后,脚本继续运行。我看不到这个问题的解决方案。

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 CMDas a new window and pass CSCRIPT //NoLogo //B WScript.CreateObject("WSCript.shell").AppActivate("Window Name")as the argument, and see if that bypasses the issue.

我使用批处理文件为 AppActivate 命令调用 CSCRIPT,并且我注意到您严格使用 VBS 文件。尝试CMD作为新窗口调用并CSCRIPT //NoLogo //B WScript.CreateObject("WSCript.shell").AppActivate("Window Name")作为参数传递,看看是否绕过了问题。

回答by cloudyjudgement

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.

同样,我试图在我用 shell 命令打开的 pdf 文档上使用 AppActivate,以便我可以在它上面使用 SendKeys。它总是会生成运行时错误“5”。我的解决方案最终是根本不使用 AppActivate,实际上无论如何打开文档都会将其置于最前沿。问题是 SendKeys 语句在 shell 命令之后立即执行,但 pdf 需要一两秒钟才能打开。我的解决方案是在执行 sendkeys 语句之前暂停代码几秒钟。

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

我使用了 pootle flump 的时间延迟curtosy。在此处查看线​​程:http: //www.dbforums.com/microsoft-access/1219379-time-delay-vba.html

回答by Barun Rai

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.

在各种论坛上研究了几个小时后,我发现我将无法在 Adob​​e Reader 中使用 Adob​​e 库对象和函数。剩下的唯一可行的选择是使用 Shell 命令来使用 Adob​​e Reader 文件菜单中可用的“另存为文本”选项。快捷键是Alt+ f+ a+ x+ s。我在下面的代码中实现了这些完美的工作,尽管我需要在某些步骤中插入延迟。

Sub SavePDFasText()
Dim AdobeReaderPath As String
Dim PdfFilePath As String
Dim PDFid, NotepdId As Double

AdobeReaderPath = "C:\Program Files\Adobe\Reader 10.0\Reader\AcroRd32.exe"
PdfFilePath = "D:\PowerGenMacro\opm_11.pdf"
PDFid = Shell(AdobeReaderPath & " " & PdfFilePath, vbNormalFocus)
Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 5)
'Alt+f+a+x is required to save the pdf as text in the adobe reader
SendKeys "%(FAX)", True
Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 2)
SendKeys "%S", True
SendKeys "^q", True

End Sub

回答by Sahara_trip

Try sendkeys "%{tab}" to switch windows but then keep only 2 active windows.

尝试使用 sendkeys "%{tab}" 来切换窗口,但只保留 2 个活动窗口。

or try appactivate only after sendkeys {Tab} so that text entry box is not selected before switchibg windows cmd.

或仅在 sendkeys {Tab} 之后尝试 appactivate 以便在 switchibg windows cmd 之前不选择文本输入框。

or try try appactivate window name, 1 then sleep 2000 °to allow time to bring that window into focus

或尝试尝试 appactivate window name, 1 然后 sleep 2000 ° 以留出时间将该窗口聚焦