Force a VBS to run using cscript instead of wscript
Asked Answered
F

5

20

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.

Freshwater answered 14/1, 2011 at 15:16 Comment(5)
Add handling of WScript.Arguments and you're set.Curler
@Kyle: sounds like an answer to me not a comment.Ransack
Seems like you answered it on your own, I was just confirming.Curler
@Kyle: You're right, but I was wondering whether the whole approach of looking at Wscript.FullName in this way was the best possible thing to do. Or to quote Perl, there is more than one way to do it ... and maybe mine isn't the best?Freshwater
I can't think of another way to do it.Curler
F
23

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.

Federalism answered 7/3, 2011 at 12:7 Comment(3)
Nice use of //nologo and well remembered on the test of space (and then adding the quotes) for each argument.Freshwater
The CreateObject line is missing a space between the script name and the arguments. As such, the run command fails. To fix, change WScript.ScriptFullName & """" & Str to WScript.ScriptFullName & """ " & Str.Freshwater
FYI: I edited the script to include the space / add line breaks to display the code better on site. However I just realised the space isn't missing - during the for loop spaces are prefixed on all arguments. As well as separating arguments from one another, the first of these separates them from the script name.Godbey
S
5

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.

Selfpossession answered 25/9, 2015 at 20:33 Comment(0)
C
4

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

Circumpolar answered 8/1, 2013 at 9:7 Comment(0)
R
1

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.

Ransack answered 14/1, 2011 at 21:33 Comment(2)
Sadly this won't work as I don't have control over the computer where this script will be run. I need to be able to give them mycode.vbs and know that however they try to run it, it will always be run with cscript rather than wscript.Freshwater
It won't work period. It will result in Input Error: There is no script engine for file extension ".cvbs".Kali
D
0

Here is my code snippet i use for some of my scripts. It handles Arguments as well. All you have to do is replace the {EnterWorC} with either a "w" or "c" WITH quotes

Dim WorC, Command, Arguments, I

WorC={EnterWOrC}  'Make sure you replace "{EnterWOrC}" with a "w" or a "c" and BE SURE TO PUT QUOTES AROUND THE LETTER.

WorC=LCase (WorC)
If lcase (WorC)="w" Or lcase (WorC)="c" Then

If LCase (Right (WScript.FullName,11))<> WorC & "script.exe" Then
    command=WScript.ScriptFullName
    Arguments=""
    For I=0 To UBound (WScript.Arguments)
        Arguments=Arguments & Chr (34) & WScript.Arguments(I) & Chr (34) & Space (1)
    Next
    CreateObject("Wscript.Shell").Run WorC & "script.exe " & Chr (34) & command & Chr (34) & Space (1) & Arguments, 1
    WScript.Quit
End If
    WorC=Empty
    Command=Empty
    I=Empty
    Arguments=Empty
End If

Here you will have to replace the 2nd line (2nd NON-blank line)

WorC={EnterWOrC}  'Make sure you replace "{EnterWOrC}" with a "w" or a "c" and BE SURE TO PUT QUOTES AROUND THE LETTER.

For Wscript: WorC="W"

For CScript: WorC="C"

It is NOT case Sensitive.

Dahle answered 5/6, 2016 at 17:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.