web-dev-qa-db-fra.com

Forcer une VBS à s'exécuter en utilisant cscript au lieu de wscript

Quelle est la méthode approuvée (et donc correcte) de stackoverflow pour forcer un serveur VBS à s'exécuter à l'aide de cscript au lieu de wscript - indépendamment de ce que l'utilisateur tente?

Une recherche rapide sur Google montre de nombreux exemples, mais certains d'entre eux ne fonctionnent tout simplement pas et ceux qui le font souvent ne gèrent pas le fait qu'il ait peut-être été argumenté, alors je tiens à savoir quelle est la meilleure solution.

Voici un exemple qui ne gère pas les 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

Je comprends que cela pourrait probablement être facilement modifié pour gérer les arguments, mais sachez que ce n'est peut-être pas la meilleure façon d'aborder le problème.

Contexte: j'écris un script qui peut être exécuté en double-cliquant sur ou (probablement) à partir d'un fichier de commandes DOS ou en tant que tâche planifiée. Il peut contenir un ou plusieurs arguments de ligne de commande facultatifs.

17
Richard

Mon Seigneur, quelles ordures sans mélange. Cela me fait pleurer de voir un tel code cruddy (aucune offense à personne, lol). Sérieusement, voici mes 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

Il gère les arguments ET recherche les espaces dans lesdits arguments - de sorte que dans le cas d'un nom de fichier transmis à l'instance de script d'origine contenant des espaces, il ne serait pas "tokenisé" lorsqu'il est passé à cscript.exe.

La seule chose qu’elle ne fait pas, c’est tester StdIn (par exemple, dans le cas où une personne transmettrait quelque chose au script via la ligne de commande, mais oubliant d’utiliser "cscript script.vbs"), mais s’il était exécuté par WScript. exe, les méthodes de WScript.StdIn renvoient toutes des erreurs de type Invalid Handle. Il n’ya donc aucun moyen de tester cela.

N'hésitez pas à me faire savoir s'il existe un moyen de "casser" ceci; Je suis disposé à l'améliorer si nécessaire.

22

Deux petits ajouts à forceCScriptExecution me permettent de voir sa fenêtre après la fin et de gérer son code de retour.

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

Remarques: "cmd/k" laisse les fenêtres rester après l'exécution. Le paramètre "1" active la fenêtre. Le paramètre "true" attend la fin, la variable "ret" peut donc renvoyer le code d'erreur.

4
clv

Voici un exemple similaire dans JScript pour faire en sorte que les fichiers .js soient exécutés dans 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

3
sstur

Une approche pourrait être de lui donner une autre extension au lieu de .vbs. Dites .cvbs par exemple. Associez .cvbs à cscript.exe et non à wscript.exe. De cette manière, l’exécution ou le double-clic sur un fichier .cvbs n’appellera jamais wscript.exe.

1
AnthonyWJones

Voici l'extrait de code que j'utilise pour certains de mes scripts. Il gère également les arguments . Tout ce que vous avez à faire est de remplacer {EnterWorC} par un "w" ou un "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

Ici, vous devrez remplacer la 2ème ligne (2ème ligne non vide)

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

Pour Wscript: WorC="W"

Pour CScript: WorC="C"

Ce n'est pas sensible à la casse.

0
Ronnie Matthews