Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for an application to start in VBScript?

Tags:

pdf

vbscript

I'm a new VB Script programmer trying to use VB Script to open a pdf file via the default program (Adobe Reader X in this case) and save it as a text file.

The current script I have opens the PDF, waits 1 second, then saves it as text. However, for slower computers, it might take more than 1 second for the PDF to load up. Does anyone know how to do a sleep loop until the file is opened or the status is ready?

Set WshShell = WScript.CreateObject("WScript.Shell") 
WshShell.Run """C:\Temp\Gasprices.pdf"""
Set objShell = CreateObject("WScript.Shell") 
wscript.sleep 1000
objShell.SendKeys "%FAX%S"
like image 539
aqpham1 Avatar asked Nov 24 '25 05:11

aqpham1


1 Answers

First off, since you are a beginner, always use Option Explicit. Many errors are caused by typos in variable names, you will catch them if you force yourself to declare all variables you use.

Secondly, you don't need to create two WScript.Shell objects, just re-use the existing one.

Thirdly, you need to activate the application you want to send commands to. That's what the Shell object's AppActivate method is for. It returns True or False, indicating whether bringing the application in question to the foreground has worked or not. You could use that in a loop (While Not Shell.AppActivate("Adobe Reader") ...) to wait exactly as long as the application needs.

However, the downside is that you need to know the exact title of the application window (or its process ID) for this to work at all. Application titles might change without warning, so this is kind of shaky. The PID is robust but it is not guessable.

In the end you will need the help of WMI to list all processes, fetch the correct PID and then pass that to AppActivate. The Win32_Process class is made for this.

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

Note that assigning to the function name (as in WaitForProcess = 0) sets the return value.


You could optimize this by finding the script's own PID and querying

"SELECT ProcessId FROM Win32_Process WHERE ParentProcessId = '" & scriptPID & "'"

in WaitForProcess().

like image 175
Tomalak Avatar answered Nov 25 '25 17:11

Tomalak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!