0

I have multiple VBS files (each opening a different file, same program) and I wanted to open them all without having to click on all of them. I can get them to open without an issue if I use the python script I created and execute with NPPExec from Notepad++. The way I want the files to open (using method previously stated) is to open the program+file -> hit some keyboard strokes -> repeat. The issue I am having is that when I double click on the python file it will only open the program+first file --> do keyboard strokes and then for the following files it will only open the program. I am fairly certain that this issue is caused by not having the correct window in focus when the VBS script goes through the keystrokes, they are not performing on the correct window. I have a batch file that I have tried as well, and I am having the same issue.

VBS file that opens the program+file --> keystrokes I have tried to use App.Activate without luck

Dim objShell
Set objShell = WScript.CreateObject( "WScript.Shell" )
objShell.Run """C:\Program Files (x86)\Program\Program.exe""" & """C:\temp_folder\file.ext"""
objShell.AppActivate """C:\Program Files (x86)\Program\Program.exe"""
WScript.Sleep 3000
objShell.SendKeys "{TAB}"
objShell.SendKeys "{TAB}"
objShell.SendKeys "{UP}"
objShell.SendKeys "{TAB}"
objShell.SendKeys "{DOWN}"
objShell.SendKeys "{ENTER}"

Python code to open multiple VBS files Works the way I want it to, but only if run from Notepad++ and NPPExec Double clicking on python script does not work the proper way

import os
import time
import subprocess
alfs = []
for file in os.listdir(os.getcwd()):
    if file.endswith(".ext"):
        alfs.append(file)

for f, item in enumerate(alfs):
    subprocess.call('cmd /c %s'%alfs[f])    
    time.sleep(2)

Batch file to open multiple VBS files I"m running the batch file by double clicking on it and results are similar to Python double clicking method.

for /r "." %%a in (*.vbs) do %%~fa

I'm mostly piecing together code that I found to get it to work how I want. I understand Python fairly well, but I am completely new to VBS and Batch.

2 Answers2

1

AppActivate Method reference:

Activates an application window.

  • Syntax: object.AppActivate title
  • Arguments:
    • object: WshShell object.
    • title: Specifies which application to activate. This can be a string containing the title of the application (as it appears in the title bar) or the application's Process ID.

Ensure that the string supplied to objShell.AppActivate is either the title of desired instance of the Program.exe or it's Process ID.

In addition to SendKeys Method reference, read Sending Keystrokes to a Program. This article explains fundamental insufficiency of your any script - timing issue:

You should be aware that sending keystrokes to an application is not the optimal method for automating a procedure. If you have an application in your enterprise that you need to automate and it has no COM-based object model, you might consider this technique. However, you should first examine whether other methods exist for automating that particular application.

Although SendKeys can be used effectively, there are several potential problems with this approach:

  • The script might have difficulty determining which window to send the keystrokes to.
  • Because the application runs in GUI mode, a user might close the application prematurely. Unfortunately, this will not terminate the script, and the script could end up sending keystrokes to the wrong application.
  • The script might have difficulty synchronizing with the application.

This timing issue is especially troublesome, simply because scripts tend to run much faster than GUI applications.

and using AppActivate:

Before sending keystrokes to an application, you must first ensure that the application is running and that the focus is on the application (that is, the application is running in the active window).

You can place your script in a loop, periodically calling AppActivate until the return value is True. At that point, the application is loaded and prepared to accept keystrokes.

When the script is determining which application to activate, the given title is compared to the title of each window visible on-screen. If no exact match exists, the AppActivate method sets the focus to the first window whose title begins with the given text. If a window still cannot be found, the first window whose title string ends with the text is given the focus. The partial matching with the leading and trailing text of title bars ensures that AppActivate works with applications, such as Notepad, that display the name of the currently opened document on the title bar. (For example, when you first start Notepad, the window title is Untitled - Notepad, not Notepad.)

(Above quote is a digest only with my emphases: too long to quote whole article here.)

Edit.

Let's face up that SendKeys method sends keystroke(s) to the active window sight unseen as actually we never know which window is currently focused. Take advantage from Run Method (Windows Script Host) full syntax objShell.Run sCmdLine, 1, False where window style 1 meaning is

  • 1 Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.

Tested using next sample script (commented for better understanding):

option explicit
On Error GoTo 0

Dim objShell, sProgram, sTxtFile, sTxtPath, sCmdLine, sTxtExists
Set objShell = WScript.CreateObject( "WScript.Shell" )

sProgram = "C:\Windows\System32\notepad.exe" 
sTxtFile = Replace( Wscript.ScriptName, ".vbs", ".txt", 1, -1, vbTextCompare)
sTxtPath = CreateObject("Scripting.FileSystemObject").BuildPath( _
             objShell.ExpandEnvironmentStrings("%temp%"), sTxtFile)
sTxtExists = CreateObject("Scripting.FileSystemObject").FileExists(sTxtPath)

    ' delete file merely for testing and debugging to ensure that 
    '             `NOTEPAD` will ask whether create nonexistent file
If sTxtExists Then CreateObject("Scripting.FileSystemObject").DeleteFile( sTxtPath)
WScript.Sleep 500                       ' wait for deleting

sCmdLine = """" & sProgram & """ """ & sTxtPath & """"
objShell.Run sCmdLine, 1, False
              '  this `1` activates currently launched notepad
              '           and its possible initial dialogue takes focus
WScript.Sleep 1000      ' hence, `AppActivate` is not necessary

                                  ' alternative to `DeleteFile( sTxtPath)`
' If NOT sTxtExists Then          ' answer initial dialogue only if necessary  
    objShell.SendKeys "{TAB}"
    WScript.Sleep 100
    objShell.SendKeys "{TAB}"
    WScript.Sleep 100
    objShell.SendKeys "{TAB}"
    WScript.Sleep 100
    objShell.SendKeys "{ENTER}"
    WScript.Sleep 100
' End If
objShell.SendKeys Cstr(Now)
WScript.Sleep 100

However, there is another timing and focus issue in your launcher. Would Python time.sleep(2) suffice? Surely not: every vbs script waits 3 seconds before the first SendKeys but next one is launched every 2 seconds!

Batch script equivalent: Timeout command pauses the command processor for the specified number of seconds.
Trailing 1>NUL hides output countdown Waiting for X seconds, press CTRL+C to quit ...

for /r "." %%a in (*.vbs) do (
    C:\Windows\System32\wscript.exe "%%~fa"
    timeout /T 5 /NOBREAK 1>NUL
)

Would 5 seconds suffice?

JosefZ
  • 28,460
  • 5
  • 44
  • 83
  • I understand the flaws in using the SendKeys, but for the program/files I am opening, this was the only option I could come up with. I was using the correct name for App.Activate, however there is a pop-up dialogue that comes up upon opening a file (in which the keystrokes are made), however this dialogue is not called out separately from the program. I tried to figure out how to use the process ID, but couldn't find a good way to get the ID # while using the Run command, since the Exec command would not work for my situation (I think) – bachelor.party Jun 14 '16 at 18:15
0

From a DOS BATCH perspective, this should help you:

FOR %%G IN (file1.txt file2.txt file3.txt) DO start notepad.exe %%G

You can make the necessary modifications to handle VBS files.

tale852150
  • 1,618
  • 3
  • 17
  • 23