我是一个新的VB脚本程序员,试图使用VB脚本通过默认程序(在本例中为Adobe Reader X(打开pdf文件并将其另存为文本文件。
我拥有的当前脚本打开 PDF,等待 1 秒钟,然后将其另存为文本。 但是,对于速度较慢的计算机,加载 PDF 可能需要 1 秒以上。 有谁知道如何在打开文件或状态准备就绪之前进行睡眠循环?
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run """C:TempGasprices.pdf"""
Set objShell = CreateObject("WScript.Shell")
wscript.sleep 1000
objShell.SendKeys "%FAX%S"
首先,由于您是初学者,请始终使用 Option Explicit
。许多错误是由变量名中的拼写错误引起的,如果您强迫自己声明您使用的所有变量,您将捕获它们。
其次,您不需要创建两个WScript.Shell
对象,只需重用现有的对象即可。
第三,您需要激活要向其发送命令的应用程序。这就是 Shell 对象的 AppActivate
方法的用途。它返回True
或False
,指示将有问题的应用程序带到前台是否有效。你可以在循环(While Not Shell.AppActivate("Adobe Reader") ...
(中使用它来等待应用程序需要的时间。
但是,缺点是您需要知道应用程序窗口的确切标题(或其进程 ID(才能正常工作。应用程序标题可能会在没有警告的情况下更改,因此这有点不稳定。PID是健壮的,但无法猜测。
最后,您将需要WMI的帮助来列出所有进程,获取正确的PID,然后将其传递给AppActivate
。Win32_Process
类就是为此而生的。
Dim Shell, WMI, pid
Set Shell = WScript.CreateObject("WScript.Shell")
Set WMI = GetObject("winmgmts:!\.rootcimv2")
Shell.Run "start ""C:TempGasprices.pdf"""
pid = WaitForProcess("AcroRd32.exe", 5)
If pid > 0 Then
Shell.AppActivate pid
Shell.SendKeys "%FAX%S"
Else
WScript.Echo "Could not talk to PDF reader"
WScript.Quit 1
End If
Function WaitForProcess(imageName, tries)
Dim wql, process
wql = "SELECT ProcessId FROM Win32_Process WHERE Name = '" & imageName & "'"
WaitForProcess = 0
While tries > 0 And WaitForProcess = 0
For Each process In WMI.ExecQuery(wql)
WaitForProcess = process.ProcessId
Next
If WaitForProcess = 0 Then
WScript.Sleep 1000
tries = tries - 1
End If
Wend
End Function
请注意,赋值到函数名称(如 WaitForProcess = 0
中所示(会设置返回值。
您可以通过查找脚本自己的 PID 并查询来优化这一点
"SELECT ProcessId FROM Win32_Process WHERE ParentProcessId = '" & scriptPID & "'"
在WaitForProcess()
.
另一个可能的选择是测试进程 CPU 使用率...
您需要测试并查看这是否适用于您的环境...
Dim oShell, oExec, PID, X, Z
Set oShell = CreateObject("WScript.Shell")
Set oExec = oShell.Exec(Chr(34) & "C:ADOBE PATH" & Chr(34) & " " & Chr(34) & "C:YOUR PDF PATH.pdf" & Chr(34))
PID = oExec.ProcessID
WScript.Echo PID
'Prevent an Endless Loop
Z = 600 'about one minute worse case
Do
WScript.Sleep 100
X = GetCPUUsage(PID)
WScript.Echo X
Z = Z - 1
If oExec.Status <> 0 Then
MsgBox "The Process has been Terminated. Ending Script"
WScript.Quit
End If
Loop Until X = 0 Or Z = 0
If Z > 0 Then
WScript.Echo "Process Is More Or Less Opened"
Else
WScript.Echo "Process is open... Maybe?"
End If
Function GetCPUUsage(ProcID)
Dim objWMIService, colItems, objItem
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
'Just in case
GetCPUUsage = 0
Set objWMIService = GetObject("winmgmts:\.rootCIMV2")
Set colItems = objWMIService.ExecQuery("SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfProc_Process WHERE IDProcess = '" & ProcID & "'", _
"WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
For Each objItem In colItems
GetCPUUsage = objItem.PercentProcessorTime
Next
End Function