Est-il possible d'intégrer et d'exécuter VBScript dans un fichier batch sans utiliser un fichier temporaire?

les gens ont été l'intégration et l'exécution de VBScript dans les fichiers par lots pendant une longue période. Mais toutes les solutions publiées que j'ai vues (au moment où cette question a été posée à l'origine) impliquent l'écriture d'un fichier VBS temporaire. Par exemple: intègre VBScript à L'intérieur du fichier de lots de Windows .

est-il possible d'exécuter le VBScript intégré dans un lot sans avoir à écrire un fichier temporaire?

35
demandé sur Community 2012-01-31 08:39:57

5 réponses

Note-saut à la mise à jour 2014-04-27 section au bas de cette réponse pour la meilleure solution.

je pensais que la réponse était non. Mais L'utilisateur de DosTips Liviu a découvert que le caractère <SUB> (Ctrl-Z, 0x1A, décimal 26) a des effets de bizare lorsqu'il est intégré dans un fichier batch. Si fonctionne un peu comme un terminateur de ligne tel qu'il est possible pour les commandes par lots qui suivent un REM (ou un hack:: remark) à exécuter si elles sont précédées de Ctrl-Z. http://www.dostips.com/forum/viewtopic.php?p=13160#p13160

cela a été confirmé sur XP Home Edition sp3, Vista Home Premium sp2 64 bit, et Vista Enterprise sp2 32 bit. Je suppose que ça marche sur D'autres versions de Windows.

Note - le code ci-dessous est supposé avoir des caractères Ctrl-Z intégrés. Je vous jure j'ai l'habitude de voir sur ce site lors de l'affichage avec IE8. Mais ils semblent avoir été perdus de ce poste en quelque sorte et je ne peux pas comprendre comment les poster plus. J'ai remplacé les caractères par la chaîne <SUB>

::<sub>echo This will execute in batch, but it will fail as vbs.
rem<SUB>echo This will execute in batch, and it is also a valid vbs comment
::'<SUB>echo This will execute in batch and it is also a valid vbs comment

qui est la clé d'un succès de lot/VBS hybride. Aussi longtemps que chaque commande par lots est précédée de rem<SUB> ou ::'<SUB> , alors le moteur vbs Je ne le verrai pas, mais la commande batch s'exécutera. Assurez-vous simplement de terminer la partie de lot avec un EXIT ou EXIT /B . Puis le reste du script peut être normale vbs.

vous pouvez même avoir une étiquette de lot si nécessaire. :'Label est à la fois un commentaire vbs valide et une étiquette de lot valide.

voici un script hybride trivial. (de nouveau avec <SUB> à la place de CTRL-Z)

::'<SUB>@cscript //nologo //e:vbscript "%~f0" & exit /b
WScript.Echo "Example of a hybrid VBS / batch file"

mise à jour 2012-04-15

jeb a trouvé une solution qui évite le maladroit CTRL-Z, mais il imprime ECHO OFF Au début et définit également quelques variables externes.

j'ai trouvé une solution sans CTRL-Z qui élimine les variables externes et est plus simple à comprendre.

normalement les caractères spéciaux & , | , < , > etc. ne pas travailler après une déclaration REM en lot. Mais les caractères spéciaux fonctionnent après REM. . J'ai trouvé cette pépite d'information à http://www.dostips.com/forum/viewtopic.php?p=3500#p3500 . Un test montre que REM. est toujours un commentaire VBS valide. EDIT - sur la base du commentaire de jeb, il est plus sûr d'utiliser REM^ (il y a un espace après le caret.)

voici donc un hybride trivial VBS/batch utilisant REM^ & . Le seul inconvénient est qu'il imprime REM & au début, tandis que la solution de jeb imprime ECHO OFF .

rem^ &@cscript //nologo //e:vbscript "%~f0" & exit /b
WScript.Echo "Example of a hybrid VBS / batch file"

voici un autre exemple trivial qui démontre plusieurs commandes par lots, y compris un appel à une sous-routine étiquetée.

::' VBS/Batch Hybrid

::' --- Batch portion ---------
rem^ &@echo off
rem^ &call :'sub
rem^ &exit /b

:'sub
rem^ &echo begin batch
rem^ &cscript //nologo //e:vbscript "%~f0"
rem^ &echo end batch
rem^ &exit /b

'----- VBS portion ------------
wscript.echo "begin VBS"
wscript.echo "end VBS"
'wscript.quit(0)

j'aime toujours la solution CTRL-Z parce qu'elle élimine tous les sortie.

mise à jour 2012-12-17

Tom Lavedas a publié une méthode pour exécuter commodément VBS dynamique à partir d'un script par lots sur Google Groups: no file VBS hybrid scripting . La méthode utilise mshta.exe (Microsoft HTML Application Host).

sa solution de série originale reposait sur un petit VBS externe.BAT script pour exécuter le VBS dans un FOR / F. J'ai légèrement modifié la syntaxe pour qu'il soit pratique d'intégrer directement dans un script de traitement par lots donné.

c'est assez lent, mais très pratique. Il est limité à l'exécution d'une seule ligne de VBS.

le VBS est écrit normalement, sauf que toutes les citations doivent être doublées: une citation contenant une chaîne de caractères doit être écrite comme "" , et les citations internes à une chaîne de caractères doivent être écrites comme """" . Normalement, le mini script est exécuté dans le() clause de A FOR / F. Il peut être exécuté directement, mais seulement si stdout a été redirigé ou pipé.

il devrait fonctionner sur N'importe quel système D'exploitation Windows à partir de XP aussi longtemps que IE est installé.

@echo off
setlocal
:: Define simple batch "macros" to implement VBS within batch
set "vbsBegin=mshta vbscript:Execute("createobject(""scripting.filesystemobject"")"
set "vbsBegin=%vbsBegin%.GetStandardStream(1).write("
set ^"vbsEnd=):close"^)"

:: Get yesterday's date
for /f %%Y in ('%vbsBegin% date-1 %vbsEnd%') do set Yesterday=%%Y
set Yesterday
pause
echo(

:: Get pi
for /f %%P in ('%vbsBegin% 4*atn(1) %vbsEnd%') do set PI=%%P
set PI
pause
echo(

set "var=name=value"
echo Before - %var%
:: Replace =
for /f "delims=" %%S in (
  '%vbsBegin% replace(""%var%"",""="","": "") %vbsEnd%'
) do set "var=%%S"
echo After  - %var%
pause
echo(

echo Extended ASCII:
for /l %%N in (0,1,255) do (

  %=  Get extended ASCII char, except can't work for 0x00, 0x0A.  =%
  %=  Quotes are only needed for 0x0D                             =%
  %=    Enclosing string quote must be coded as ""                =%
  %=    Internal string quote must be coded as """"               =%
  for /f delims^=^ eol^= %%C in (
    '%vbsBegin% """"""""+chr(%%N)+"""""""" %vbsEnd%'
  ) do set "char.%%N=%%~C"

  %=  Display result  =%
  if defined char.%%N (
    setlocal enableDelayedExpansion
    echo(   %%N: [ !char.%%N! ]
    endlocal
  ) else echo(   %%N: Doesn't work :(
)
pause
echo(

:: Executing the mini VBS script directly like the commented code below 
:: will not work because mshta fails unless stdout has been redirected
:: or piped.
::
::    %vbsBegin% ""Hello world"" %vbsEnd%
::

:: But this works because output has been piped
%vbsBegin% ""Hello world"" %vbsEnd% | findstr "^"
pause

mise à jour 2014-04-27

Plus de à DosTips il y a un grand recueil de js/vbs/html/hta hybrides et chimères dans cmd/chauve-souris . Beaucoup de bonnes choses de diverses personnes.

dans ce fil, Liviu de DosTips Utilisateur a découvert une belle VBS/lot hybride solution qui utilise WSF.

<!-- : Begin batch script
@echo off
cscript //nologo "%~f0?.wsf"
exit /b

----- Begin wsf script --->
<job><script language="VBScript">
  WScript.Echo "VBScript output called by batch"
</script></job>

je pense que cette solution est fantastique. Les sections batch et WSF sont clairement séparées par de beaux en-têtes. Le code de lot est absolument normal, sans aucune syntaxe étrange. La seule restriction est que le code de lot ne peut pas contenir --> .

de même, la Le code VBS dans WSF est absolument normal. La seule restriction est que le code VBS ne peut pas contenir </script> .

le seul risque est l'utilisation non documentée de "%~f0?.wsf" comme script à charger. D'une façon ou d'une autre, l'analyseur trouve et charge correctement le fonctionnement .BAT script "%~f0" , et le suffixe ?.wsf donne mystérieusement instruction à CSCRIPT d'interpréter le script comme WSF. Avec un peu de chance, MicroSoft ne désactivera jamais cette "fonctionnalité".

depuis la solution utilise WSF, le script de fournée peut contenir n'importe quel nombre de VBS indépendants, JScript, ou d'autres travaux qui peuvent être sélectivement appelés. Chaque tâche peut même utiliser plusieurs langues.

<!-- : Begin batch script
@echo off
echo batch output
cscript //nologo "%~f0?.wsf" //job:JS
cscript //nologo "%~f0?.wsf" //job:VBS
exit /b

----- Begin wsf script --->
<package>
  <job id="JS">
    <script language="VBScript">
      sub vbsEcho()
        WScript.Echo "VBScript output called by JScript called by batch"
      end sub
    </script>
    <script language="JScript">
      WScript.Echo("JScript output called by batch");
      vbsEcho();
    </script>
  </job>
  <job id="VBS">
    <script language="JScript">
      function jsEcho() {
        WScript.Echo("JScript output called by VBScript called by batch");
      }
    </script>
    <script language="VBScript">
      WScript.Echo "VBScript output called by batch"
      call jsEcho
    </script>
  </job>
</package>
47
répondu dbenham 2017-12-26 09:59:43

EDIT: ma première réponse était fausse pour VBScript, maintenant mon prochain essai...

bonne idée d'utiliser CTRL-Z, mais je n'aime pas les caractères de contrôle dans un fichier de commandes, comme il est difficile de copier et de les coller.

Cela dépend de votre navigateur, de votre éditeur, de votre ...

vous pourriez obtenir un VBScript/Batch hybride aussi avec des caractères normaux, et le code" normal".

:'VBS/Batch Hybrid
:
:
:'Makes the next line only visible for VBScript ^
a=1_
<1' echo off <nul 

set n=nothing' & goto :'batchCode & REM Jump to the batch code

'VBScript-Part
wscript.echo "VB-Start"
wscript.echo "vb-End"
wscript.quit(0)

'Batch part
:'batchCode
set n=n'& echo Batch-Start
set n=n'& echo two
set n=n'& echo Batch-End
set n=n'& cscript /nologo /E:vbscript vbTest.bat

le truc est de préparer chaque ligne de lot avec set n=n'& c'est légal pour les deux, mais vbs ignorera le reste de la ligne, seul le lot exécutera le reste de la ligne.

L'autre variante est :'remark ^ , c'est une remarque pour les deux, mais pour le lot cela remarques aussi la ligne suivante par le multiligne caractère.

Le VbScript voit alors a=1<1 le reste de la ligne est une remarque '

Lot ne voit que <1' echo off <nul , la première redirection de 1' sera annulée par la seconde <nul , de sorte qu'il résulte à seulement echo off < nul .

le seul problème restant est que vous pouvez voir le premier echo off , car il ne fonctionne pas en lot pour utiliser le @ après une redirection.

pour JScript existe une solution plus simple hybrid scripting

11
répondu jeb 2017-05-23 12:25:54

And my attempt ( first posted here ).Il ressemble à la solution de jeb, mais (au moins selon moi) le code est plus lisible:

:sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul

'& echo/ 
'& cscript /nologo /E:vbscript %~f0
'& echo/
'& echo BATCH: Translation is at best an ECHO.
'& echo/
'& pause
'& rem del /q "%windir%\System32\'.exe"
'& exit /b

WScript.Echo "VBScript: Remorse is the ECHO of a lost virtue."
WScript.Quit

et l'explication:

  1. ' (simple quote) n'est pas interdit symbole comme une partie d'un nom de fichier dans windows donc il n'y a aucun problème à avoir un fichier appelé '.exe
  2. Il y a peu de commandes empaquetées avec windows qui ne font rien sans paramètres de ligne de commande.Le plus rapide (à ne rien faire) et le plus léger comme une taille (selon mes tests) sont subst.exe et doskey.exe
  3. donc à la première ligne, je fais face à la doskey.exe à '.exe (si elle n'existe pas déjà) et puis continuer à l'utiliser comme '& (comme l' .exe extension devrait être dans %PATHEXT% ).Ceci sera considéré comme un commentaire dans VBScript et dans la fournée ne fera rien - juste continuera avec la commande suivante sur la ligne.

il y a bien sûr des failles .Au moins pour la première exécution éventuellement, vous aurez besoin des permissions de l'administrateur car l'adaptation dans %windir%\System32\ pourrait être refusée.Pour la robustesse vous pouvez également utiliser '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe .\'.exe >nul et ensuite à la fin: '& rem del /q .\'.exe

avec '.exe à gauche dans votre chemin vous pourriez inintelligemment l'utiliser de manière inappropriée , et le d'exécution sur chaque ligne de l'.exe pourrait éventuellement diminuer la performance.

..Et dans la partie batch, les commandes ne doivent être qu'en une seule ligne.

mise à jour 9.10.13 (..conformément à la convention susmentionnée)

Voici une autre façon qui exige auto-renommage du fichier de lot:

@echo off
goto :skip_xml_comment
<!--
:skip_xml_comment

echo(
echo Echo from the batch
echo(

( ren %0 %0.wsf 
 cscript %0.wsf 
 ren %0.wsf %0 )


exit /b 0
-->

<package>
   <job id="vbs">
      <script language="VBScript">

         WScript.Echo "Echo from the VBS"

      </script>
   </job>
</package>

et une brève explication:

  1. lorsque le lot est auto-renommé et renommé avec l'ancien nom, et cela se fait sur une ligne (ou entre parenthèses) le script sera exécuté sans erreur.Dans ce cas est ajouté également un appel de CSCRIPT.EXE avec .WSF fichier.Auto-renommage est un peu risqué , mais plus rapide qu'un fichier temporaire.
  2. Windows script host n'a pas beaucoup de soins pour les éléments en dehors de données xml, tant qu'il n'y a aucune xml symboles & < > ; donc @echo off et goto peut être utilisé sans soucis. Mais pour des raisons de sécurité, il est bon de mettre les commandes par lots dans la section commentaire xml (ou CDATA).Pour éviter les messages d'erreur du lot, j'ai sauté le <!-- avec goto ici.
  3. avant de fermer le script de lot de commentaires xml est terminé par exit

donc les bonnes choses sont qu'il n'y a pas besoin d'écrire tout le code de lot dans les commandes d'une seule ligne, il n'y a pas d'ennuyeux echo off affiché, le code jscript et différents travaux peuvent être ajoutés au script.Aussi pas besoin de symboles spéciaux et la création de fichiers exe supplémentaires comme '.exe

d'un autre côté, un changement de nom peut être risqué.

3
répondu npocmaka 2013-11-04 13:09:21

j'ai essayé d'assembler toutes les solutions en un seul script à http://www.dostips.com/forum/viewtopic.php?p=37780#p37780 .

il y a le script de traitement par lots qui convertit les langues les plus populaires en un fichier de traitement par lots ( ).js , .vbs , .ps1 , .fsm , .hta et historique .pl ).

Il fonctionne comme suit:


    :: convert filename1.vbs to executable filename1.bat
    cmdize.bat filename1.vbs

3
répondu jsxt 2014-11-06 07:55:07

il y a une solution très simple pour ce problème. Il suffit d'utiliser un flux de données alternatif (ADS) pour stocker le code VBS. Pour l'expliquer simplement, une annonce est un autre endroit où vous pouvez stocker d'autres données dans le même fichier , c'est-à-dire, un fichier est composé de ses données originales plus tout nombre de annonces supplémentaires . Chaque annonce est identifiée en séparant son propre nom du nom du fichier original via un deux-points. Par exemple:

test.bat                    <- a file called "test.bat"
test.bat:script_.vbs        <- an ADS of file "test.bat" called "script_.vbs"

vous pouvez trouver une description plus technique et détaillée des annonces dans le web, mais il est important de mentionner maintenant que cette fonctionnalité fonctionne sur les disques NTFS seulement . Maintenant, voyons comment utiliser cette fonctionnalité pour résoudre ce problème particulier.

tout d'abord, créez le fichier Batch original de la manière habituelle. Vous pouvez également lancer le bloc-notes.exe de la ligne de commande de cette façon:

notepad test.bat

Pour mon exemple, j'ai inséré les lignes suivantes dans test.bat :

@echo off
setlocal

For /f "delims=" %%i in ('Cscript //nologo "test.bat:script_.vbs" "Select a folder"') do Set "folder=%%i"

echo Result: "%folder%"

Notez le nom du script VBS. Après avoir sauvegardé test.bat et fermé le bloc-notes, créez le script VBS en utilisant le bloc-notes, entrez donc cette commande à la ligne de commande:

notepad test.bat:script_.vbs

et créer le script de la manière habituelle:

Dim objFolder, objShell
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.BrowseForFolder(0, "Select a folder.", &H4000, 0)
If Not (objFolder Is Nothing) Then
   wscript.echo objFolder.Self.path
Else
   wscript.echo 0
End If

Sauvegardez ce fichier et lancez test.bat . Il fonctionne! ;)

vous pouvez consulter les annonces du fichier test.bat via le commutateur /R dans la commande dir . Vous pouvez lire une explication plus détaillée de cette méthode et ses limites à ce post .

2
répondu Aacini 2017-03-16 02:24:33