Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force a VBS to run using cscript instead of wscript

What is the stackoverflow approved (and hence correct) method to force a VBS to run using cscript instead of wscript - irrespective of what the user tries?

A quick Google search shows plenty of examples, but some of them simply don't work and those which do often don't handle the fact that it may have been run with arguments so I'm keen to know what the best way is.

Here is one example which doesn't handle arguments:

sExecutable = LCase(Mid(Wscript.FullName, InstrRev(Wscript.FullName,"\")+1))
If sExecutable <> "cscript.exe" Then
  Set oShell = CreateObject("wscript.shell")
  oShell.Run "cscript.exe """ & Wscript.ScriptFullName & """"
  Wscript.Quit
End If

I appreciate that this could probably be easily modified to handle arguments, but realise that this may not be the best way to approach the problem.

Background: I'm writing a script which can run by double clicking or (most likely) from either a DOS batch file or as a scheduled task. It can contain one or more optional command line arguments.

like image 301
Richard Avatar asked Jan 14 '11 15:01

Richard


People also ask

What is the difference between WScript and Cscript?

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.

How do I run cscript?

Right-click the script in Windows Explorer and select Open to run in WScript or Open in MS-DOS Window (Windows 9x) or Open in Command Window (Windows NT and Windows 2000) to run in CScript.

How do I run a VBS script manually?

Click the Start button, and then click Run. In the Open field, type the full path of the script, and then click OK. You can also type WScript followed by the full name and path of the script you want to run.


4 Answers

My Lord, what unadulterated rubbish. It makes me cry to see such cruddy coding (no offense to anybody, lol). Seriously, though, here's my 2 pence:

Sub forceCScriptExecution
    Dim Arg, Str
    If Not LCase( Right( WScript.FullName, 12 ) ) = "\cscript.exe" Then
        For Each Arg In WScript.Arguments
            If InStr( Arg, " " ) Then Arg = """" & Arg & """"
            Str = Str & " " & Arg
        Next
        CreateObject( "WScript.Shell" ).Run _
            "cscript //nologo """ & _
            WScript.ScriptFullName & _
            """ " & Str
        WScript.Quit
    End If
End Sub
forceCScriptExecution

It handles arguments, AND checks for spaces in said arguments -- so that in the case of a filename passed to the original script instance that contained spaces, it wouldn't get "tokenized" when passed to cscript.exe.

Only thing it doesn't do is test for StdIn (e.g., in the case where someone piped something to the script via the command line, but forgot to use "cscript script.vbs") -- but if it was executed by WScript.exe, WScript.StdIn's methods all return Invalid Handle errors, so there's no way to test that anyway.

Feel free to let me know if there's a way to "break" this; I'm willing to improve it if necessary.

like image 102
Mike the BookRaider Avatar answered Oct 29 '22 14:10

Mike the BookRaider


Two small additions to forceCScriptExecution let me see its Window after termination and handle its return code.

Sub forceCScriptExecution
    Dim Arg, Str
    If Not LCase( Right( WScript.FullName, 12 ) ) = "\cscript.exe" Then
        For Each Arg In WScript.Arguments
            If InStr( Arg, " " ) Then Arg = """" & Arg & """"
            Str = Str & " " & Arg
        Next
        **ret =** CreateObject( "WScript.Shell" ).Run **("cmd /k** cscript //nologo """ & WScript.ScriptFullName & """ " & Str**,1,true)**
        WScript.Quit **ret**
    End If
End Sub

Notes: "cmd /k" let the windows stay after execution. Parameter "1" activates the window. Parameter "true" waits for termination, so variable "ret" can return the error code.

like image 41
clv Avatar answered Oct 29 '22 16:10

clv


Here's a similar one in JScript for making .js files run in CScript:

(function(ws) {
  if (ws.fullName.slice(-12).toLowerCase() !== '\\cscript.exe') {
    var cmd = 'cscript.exe //nologo "' + ws.scriptFullName + '"';
    var args = ws.arguments;
    for (var i = 0, len = args.length; i < len; i++) {
      var arg = args(i);
      cmd += ' ' + (~arg.indexOf(' ') ? '"' + arg + '"' : arg);
    }
    new ActiveXObject('WScript.Shell').run(cmd);
    ws.quit();
  }
})(WScript);

WScript.echo('We are now in CScript. Press Enter to Quit...');
WScript.stdIn.readLine();

https://gist.github.com/4482361

like image 26
sstur Avatar answered Oct 29 '22 16:10

sstur


One approach might be to give it another extension instead of .vbs. Say .cvbs for example. Associate .cvbs with cscript.exe not wscript.exe, that way executing or double clicking a .cvbs file will never invoke the wscript.exe.

like image 40
AnthonyWJones Avatar answered Oct 29 '22 15:10

AnthonyWJones