0
votes

I use a batch to execute locally in each client a robocopy command, synchronize a folder and then starts an application which has a batch with its own pattern.

My next project is to convert this batch in a VBScript, using it directly from a remote shared folder instead to have the batch stored locally in each client.

Even if I'm not a good VBScript programmer, on the metrics, I'm almost set, but I'm stuck on porting the where command to a VBScript.

In my batch file, I execute this command:

FOR /F "tokens=* USEBACKQ" %%F IN (`where /R C:\appfolder startapp.bat /F`) DO (
  SET strAPP=%%F
)

In C:\appfolder there is installed a software in each client and for some reasons, may be installed in wrong and different patterns, so the common startapp.bat may have a different pattern in each client. For this reason the FOR instance above help me to create a variable named %strapp% which is used later in the batch to start the application.

Now, my VBScript is working using the exact pattern but without this "where command prevention", I would like to have the same feature that batch does, just to prevent that in the future the clients may have again a wrong installation in a non-common pattern.

e.g. in VBS using a strmsg menu, when the user from its client choose the right option, the VBScript starts the application:

objShell.Run("%comspec% /K C:\appfolder\startapp.bat & exit"), 1, True

strFlag = True

And it works, I tried to add the old where command and set a variable adding & in each concatenate commands, all of those in one row with no luck....

e.g.

objShell.Run("%comspec% /K FOR /F "tokens=* USEBACKQ" %%F IN (`where /R C:\appfolder startapp.bat /F`) DO (SET strAPP=%%F) & %strapp% & exit"), 1, True

strFlag = True

I tried to use double quotes "" with no luck at all.

2

2 Answers

1
votes

A VBScript implementation of where could look like this:

Function Where(fldr, filename)
  For Each f In fldr.Files
    If LCase(f.Name) = LCase(filename) Then
      Where = f.Path
      Exit Function
    End If
  Next

  For Each sf In fldr.SubFolders
    Where = Where(sf, filename)
    If Not IsEmpty(Where) Then Exit Function
  Next
End Function

The function would be called like this:

Set fso = CreateObject("Scripting.FileSystemObject")

strAPP = Where(fso.GetFolder("C:\appfolder"), "startapp.bat")

Set objShell = CreateObject("WScript.Shell")
objShell.Run "%comspec% /c """ & strAPP & """", 1, True

As a side note, it's pointless to start a CMD instance with the option /k (keep window) when you're going to exit from it anyway. Start it with the option /c (close window) and remove the exit statement.

As per Ansgar suggestion below, adding method parameter 0, CMD window is hidden

objShell.Run "%comspec% /c """ & strAPP & """", 0, True
0
votes

There are some bugs found:

  • expanded %comspec% ... Not necessary (thanks to Ansgar Wiechers' comment), it's simply an aspect of my baseless and excessive suspicion of environment variables used in VBScript... Paranoia is the right term, I think :)
  • inner " quotes should be doubled
  • parameter name is %F from command line; doubled % percent sign (%%F) in a batch only
  • /V:ON enable delayed environment variable expansion using ! as the delimiter. For example, /V:ON would allow !var! to expand the variable var at execution time. The %var% syntax expands variables at input (parse) time, which is quite a different thing when inside of a FOR loop as well as when in a line of & concatenated commands
  • usebackq: missing back quotes in (`where ...`) do ...
  • added !&echo !strapp!&pause before &exit. This way you could see result while debugging...

Forgotten something? However, all VBScript is as follows:

option explicit
Dim strResult: strResult=Wscript.ScriptName

Dim WshShell: Set WshShell = WScript.CreateObject("WScript.Shell")
Dim cmd, retrn, params
cmd = WshShell.ExpandEnvironmentStrings("%comspec%") 
params = " /E:ON /V:ON /K FOR /F ""USEBACKQ tokens=*"" %F IN (`where /R C:\appfolder startapp.bat /F`) DO (SET strAPP=%F)&!strapp!&echo !strapp!&pause&exit"
retrn = WshShell.Run(cmd & params, 1, true)

strResult = strResult & vbNewline & cmd
strResult = strResult & vbNewline & params
strResult = strResult & vbNewline & retrn

Wscript.Echo strResult
Wscript.Quit

@JosefZ

Thanks for your answer, even if I like the Ansgar solution, I made working yours, I wanted to post it here just in case is useful for someone-else. At the end, your amended working VBscript (for me) with a where command is this one:

option explicit
Dim strResult: strResult=Wscript.ScriptName

Dim WshShell: Set WshShell = WScript.CreateObject("WScript.Shell")
Dim cmd, retrn, params
cmd = WshShell.ExpandEnvironmentStrings("%comspec% /C") 
params = "FOR /F ""tokens=* USEBACKQ"" %F IN (`where /R C:\appfolder startapp.bat /F`) DO (SET strAPP=%F) & cmd /C %strapp%"
retrn = WshShell.Run(cmd & params, 1, true)
Wscript.Quit