3

我是一名新的 VB 脚本程序员,试图使用 VB 脚本通过默认程序(在本例中为 Adob​​e Reader X)打开 pdf 文件并将其保存为文本文件。

我当前的脚本打开 PDF,等待 1 秒,然后将其保存为文本。但是,对于速度较慢的计算机,加载 PDF 可能需要 1 秒以上的时间。有谁知道如何在文件打开或状态准备好之前进行睡眠循环?

Set WshShell = WScript.CreateObject("WScript.Shell") 
WshShell.Run """C:\Temp\Gasprices.pdf"""
Set objShell = CreateObject("WScript.Shell") 
wscript.sleep 1000
objShell.SendKeys "%FAX%S"
4

2 回答 2

5

首先,由于您是初学者,请始终使用Option Explicit. 许多错误是由变量名中的拼写错误引起的,如果你强迫自己声明你使用的所有变量,你就会发现它们。

其次,您不需要创建两个WScript.Shell对象,只需重新使用现有的一个。

第三,您需要激活要向其发送命令的应用程序。这就是 Shell 对象的AppActivate方法的用途。它返回Trueor 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:!\\.\root\cimv2")

Shell.Run "start ""C:\Temp\Gasprices.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().

于 2013-10-08T17:02:51.923 回答
1

另一种可能的选择是测试进程 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:\\.\root\CIMV2")
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
于 2013-10-09T07:35:56.987 回答