Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to pipe a script to WScript?

Tags:

windows

stdin

wsh

I would like to execute a simple VBScript/JScript generated by my application using the Windows Script Host (wscript.exe or cscript.exe) without generating a temporary script file.

I did not find a command line option to read the script form the standard input stream, but i did find several places in the WWW that document a WScript error message "Can't read script from stdin."

MSDN Windows Script Host Reference - Error Messages

So is there a hidden command line option to read the script from standard in?

Currently my program generates a small script and writes it to a temporary file. Then it creates a sub process running cscript.exe, waits for it to complete and then deletes the temporary file again. I would like to get rid of the temporary file and pass the script directly to the Script Host, if that's possible. (e.g. piping it to the cscript.exe or passing it as part of the command line arguments similar to the /c command line option of cmd.exe)

like image 732
niks Avatar asked Apr 06 '16 06:04

niks


People also ask

What is the difference between Cscript and WScript?

WSCRIPT. EXE and CSCRIPT. EXE are almost exactly identical, except that one is flagged as a windows application and the other is flagged as a console application (Guess which way around!). So the answer is: If you want your script to have a console window, use CSCRIPT.

What is WScript echo?

You can use WScript. Echo to see exactly what VBScript passes out; if the string you see in the result of WScript. Echo works in a command-prompt window, it will work as the first argument for the Run method.

How do I run a WSF script?

Click Start, select Run, enter "cscript" or "wscript" followed by the script name.

What is WScript exe used for?

If you do not specify a script or any script arguments, wscript.exe displays the Windows Script Host Settings dialog box, which you can use to set global scripting properties for all scripts that wscript.exe runs on the local computer. The /t parameter prevents excessive running of scripts by setting a timer.


1 Answers

Short answer is No unfortunately. The WScript Engine does not provide a way to pass script either piped or via the command arguments, the only option is using StdIn to interpret and process the commands (expand on this below).


Using StdIn to interpret and Execute Code Direct from the Command Line

Wasn't sure myself but wanted to test it out...

Worth noting that the testing below still requires a script to interpret the input which is probably not going to fit the requirement but is so generic I wouldn't class it as a temporary script.

The issue I can see is the more complex the code you want to pass in the harder it will be to pipe through to the cscript.exe program.

Here is a simple example that just pipes a MsgBox() call to cscript.exe.

Command line:

echo MsgBox("test piping") | cscript.exe /nologo "test.vbs"

Contents of test.vbs

Dim stdin: Set stdin = WScript.StdIn
Dim line: line = stdin.ReadAll

Call ExecuteGlobal(line)

Handling Multiple Lines on the Command Line

Piping multiple lines from echo isn't going to be easy it may work better if you use a character as a delimiter to break the commands up after being passed in. So for example;

echo MsgBox("test piping")^^^^Msgbox("test Complete") | cscript.exe /nologo "test.vbs"

then use

Split(stdin.ReadAll, "^")

to break up the command lines to execute.


Here is a more complex example;

Command Line:

echo Dim i: i = 1^^^^i = i + 2^^^^MsgBox("i = " ^^^& i) | cscript /nologo "test.vbs"

Contents of test.vbs:

Dim line Dim stdin: Set stdin = WScript.StdIn

For Each line In Split(stdin.ReadAll, "^")   
  'Takes each line from StdIn and executes it.
  Call ExecuteGlobal(line)
Next

Made a rod for my own back by using ^ as the delimiter as this has special meaning in the command line and needs to be escaped (which just so happens to be ^), plus the fact it has to be escaped again when piped hence the ^^^^.

Realised that breaking the lines down and executing them individually could cause more problems (for example a Function definition would fail). This made me re-think the approach and found it should be even simpler.

Dim stdin: Set stdin = WScript.StdIn
Dim input: input = Replace(stdin.ReadAll, "^", vbCrLf)

Call ExecuteGlobal(input)
like image 119
user692942 Avatar answered Oct 16 '22 02:10

user692942