2

Trying to call a vbs script from powershell.

Looks something like this . . .

"$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"

I tried these two methods using -ArgumentList in various arrangements. But to no avail.

Invoke-Expression -Command c:\windows\system32\Wscript.exe "$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"

Start-Process -FilePath "C:\Windows\system32\wscript.exe" "$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"

Truly do not know what the correct syntax would be?

8

1 Answer 1

4

Preface:

  • When calling your VBScript file explicitly via wscript.exe, the same rules apply as when executing any external executable from PowerShell - see the next section.

  • However, VBScripts can also be executed directly, in which case the preconfigured WSH (Windows Scripting Host) executable is used for execution; by default, this executable is wscript.exe, i.e the GUI-based WSH executable; this default be changed to the console-based cscript.exe, with cscript //H:CScript (and, conversely, you can switch back with wscript //H:WScript)

    • Thus, with wscript.exe as the default host, you can invoke your script directly; for syntactic reasons - your script path is quoted and contains variable references - you must invoke it via &, the call operator:

      & "$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"
      

Invocation via explicit use of WSH host wscript.exe (applies analogously to cscript.exe):

Invoke wscript.exe directly - no need for Invoke-Expression (which is generally best avoided)[1] or Start-Process:[2]

wscript.exe "$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"

Note:

  • wscript.exe, as a GUI-subsystem application, executes asynchronously; if you want PowerShell to wait for its termination, a simple trick is to add | Out-Null to the invocation (or use -Wait with Start-Process, but the former technique is simpler).

    • By contrast, if you want to run your VBScript as a console application, use cscript.exe, in which case the invocation is synchronous, and the script's output can be captured on the PowerShell side.
      Note that cscrpt.exe prints a "logo" (copyright message) by default before printing the script's output, which you can suppress with //nologo:

      cscript.exe //nologo "$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs" "$SavedGamesFolder\DCS\Config\olympus.json"
      
  • For the sake of completeness: The problem with your Start-Process call was that you tried to pass the pass-through arguments individually, whereas Start-Process requires them to be passed as an array, to the -ArgumentList parameter or - preferably, due to a long-standing bug - encoded in a single string:

    # Note:
    #  * "C:\Windows\system32\wscript.exe" positionally binds to -FilePath
    #  * The second argument is a single string with embedded
    #    quoting encoding all pass-through arguments, 
    #    which positionally binds to -ArgumentList
    Start-Process "C:\Windows\system32\wscript.exe" "`"$SupAppsFolder\DCS Olympus_v1.0.4_manager\frontend\client.vbs`" `"$SavedGamesFolder\DCS\Config\olympus.json`""
    
  • Unlike with direct execution of .vbs files (see preface above), explicit execution via wscript.exe or cscript.exe requires that a path to the script file be specified (though it may be relative, and a file name only will do for a script located in the current directory).
    That is, *.vbs files that are discoverable via $env:PATH cannot be specified by file name only in this case.


[1] Invoke-Expression (iex) should generally be avoided, because it can be a security risk and because better solutions are usually available (see this answer); except in unusual circumstances, don't use it to invoke an external program or PowerShell script / command (see this answer).
For the sake of completeness: the problem with your attempt to call Invoke-Expression was that you passed multiple arguments, whereas only a single one is supported, which is a string to be evaluated as PowerShell source code.

[2] Start-Process too is typically not the right tool for calling external applications, except in unusual scenarios - see this answer and GitHub docs issue #6239 for guidance on when its use is and isn't appropriate.

Sign up to request clarification or add additional context in comments.

2 Comments

So what exactly is wrong with OP's Invoke-Expression line? I mean, such that it does not work, not style-wise. You mention that it's not needed, but I don't see any explanation as to why it does not work at all, unlike your explanation re: the Start-Process line.
@TylerH: The problem is that Invoke-Expression only accepts a single argument: a single string that is evaluated as PowerShell code, which can be a security risk. The reason I didn't spell out this problem is that I didn't want to encourage use of Invoke-Expression - nothing whatsoever is gained from its use here, and there are very few legitimate use cases (see this answer). By contrast, there are legitimate reasons to use Start-Process for launching external programs (even though the use case at hand isn't one).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.