windowsbatch-filewsh

execute WshShell command from a batch script


I've got a simple question:

What's the best way to execute a single WshShell command from a Windows batch (.bat) script?

(hopefully it's not creating a new file with VB code)


Solution

  • You can access WshShell via VBScript or Jscript. Both can be embedded within a batch file, but JScript is much cleaner.

    Most people execute VBScript within batch by writing a temporary VBS file. But it is possible to do it without a temporary file. See Is it possible to embed and execute VBScript within a batch file without using a temporary file? for various options.

    Embedding JScript within batch is quite easy. See https://stackoverflow.com/a/5656250/1012053. I use a very slight variation of that technique.

    @if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
    
    :: ******* Begin batch code *********
    @echo off
    :: Your batch logic goes here
    
    :: At any point you can execute the following to access your JScript
    cscript //E:JScript //nologo "%~f0" yourJscriptParametersGoHere
    
    :: Be sure to terminate your script so that 
    :: it does not fall through into the JScript code
    exit /b
    
    ********* Begin JScript code **********/
    var WshShell=WScript.CreateObject("WScript.Shell")
    
    /* do whatever with your WshShell object */
    

    Explanation:

    The key to the technique is the first line. It must be a line that has valid syntax for both JScript and batch.

    Batch sees the first line as a simple IF command that always evaluates to false, so it never executes the non-existent @end command, and no harm is done. The following lines are all normal batch code until exit /b is reached, at which point batch processing terminates and the remaining lines are ignored.

    JScript sees the first line as an empty conditional compilation block, followed by the beginning of a multi-line comment. JScript ignores the following batch code because it is all part of the comment. The comment ends with */, and then normal JScript code follows.

    The only thing that could fail is if your batch code must have */ within it, because that would terminate the JScript comment prematurely. But that can be solved by putting something between the * and / that disappears after batch parsing. If the code is not quoted, then you can simply escape the slash as follows: *^/. If the code is quoted, then you can expand an undefined variable: *%=%/. A variable named = is guaranteed not to be defined.