Les gens intègrent et exécutent VBScript dans des fichiers de commandes depuis longtemps. 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égrer VBScript dans le fichier batch de Windows .
Est-il possible d'exécuter VBScript incorporé dans un lot sans écrire de fichier temporaire?
Remarque - passez au MISE À JOUR 2014-04-27section au bas de cette réponse pour la meilleure solution.
Je pensais que la réponse était non. Mais alors l'utilisateur de DosTips Liviu a découvert que le <SUB>
le caractère (Ctrl-Z, 0x1A, décimal 26) a des effets bizarres lorsqu'il est incorporé dans un fichier de commandes. Si fonctionne un peu comme un terminateur de ligne de sorte qu'il est possible pour les commandes batch qui suivent un REM (ou un hack :: remarque)) de s'exécuter si elles sont précédées de Ctrl-Z. http://www.dostips.com/forum/viewtopic.php?p=13160#p1316
Cela a été confirmé sur XP Home Edition sp3, Vista Home Premium sp2 64 bits et Vista Enterprise sp2 32 bits. Je suppose que cela fonctionne sur d'autres versions de Windows.
Remarque - le code ci-dessous est censé contenir des caractères Ctrl-Z. Je jure que je les voyais sur ce site lorsqu'ils sont consultés avec IE8. Mais ils semblent avoir été perdus de cette façon et je ne sais plus comment les publier. 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
C'est la clé d'un hybride batch/vbs réussi. Tant que chaque commande batch est précédée de rem<SUB>
ou ::'<SUB>
, le moteur vbs ne le verra pas, mais la commande batch sera exécutée. Assurez-vous simplement de terminer la partie de lot avec un EXIT
ou EXIT /B
. Ensuite, le reste du script peut être des vbs d'apparence normale.
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. (à nouveau avec <SUB>
à la place du caractère Ctrl-Z intégré)
::'<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 CTRL-Z maladroit, mais il imprime ECHO OFF au début et définit également des variables étrangères.
J'ai trouvé une solution sans CTRL-Z qui élimine les variables étrangères et est plus simple à comprendre.
Normalement, les caractères spéciaux &
, |
, <
, >
etc. ne fonctionne pas après une instruction REM
en batch. Mais les caractères spéciaux fonctionnent après REM.
. J'ai trouvé cette pépite d'informations sur http://www.dostips.com/forum/viewtopic.php?p=3500#p35 . Un test montre que REM.
est toujours un commentaire VBS valide. [~ # ~] modifier [~ # ~] basé sur le commentaire de jeb, il est plus sûr à utiliser REM^
(il y a un espace après le curseur).
Voici donc un hybride VBS/batch trivial utilisant REM^ &
. Le seul inconvénient est qu'il imprime REM &
au début, alors 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 illustre plusieurs commandes batch, 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 car elle élimine toute sortie étrangère.
MISE À JOUR 2012-12-17
Tom Lavedas a publié une méthode pour exécuter facilement VBS dynamique à partir d'un script batch sur Google Groupes: Pas de script hybride VBS de fichier . La méthode utilise mshta.exe (Microsoft HTML Application Host).
Sa solution par lots d'origine reposait sur un petit script VBS.BAT externe pour exécuter le VBS dans un FOR/F. J'ai légèrement modifié la syntaxe pour la rendre pratique à intégrer directement dans un script batch 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 doit être écrite comme ""
, et les guillemets internes à une chaîne doivent être écrits comme """"
. Normalement, le mini script est exécuté dans la clause IN () d'un FOR/F. Il peut être exécuté directement, mais uniquement si stdout a été redirigé ou canalisé.
Il devrait fonctionner sur n'importe quel système d'exploitation Windows à partir de XP en avant tant 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
Chez DosTips, il existe un grand recueil de hybrides et chimères js/vbs/html/hta en cmd/bat . Beaucoup de bonnes choses de diverses personnes.
Dans ce fil, Liviu, utilisateur de DosTips, a découvert une solution magnifique hybride VBS/batch 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 des en-têtes Nice. Le code batch est absolument normal, sans aucune syntaxe étrange. La seule restriction est que le code de lot ne peut pas contenir -->
.
De même, 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. L'analyseur recherche et charge correctement le script .BAT en cours d'exécution "%~f0"
, et le ?.wsf
le suffixe demande mystérieusement à CSCRIPT d'interpréter le script comme WSF. Espérons que Microsoft ne désactivera jamais cette "fonctionnalité".
Étant donné que la solution utilise WSF, le script de commandes peut contenir n'importe quel nombre de travaux VBS, JScript ou autres indépendants pouvant être appelés de manière sélective. Chaque travail 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>
EDIT: Ma première réponse était incorrecte pour VBScript, maintenant mon prochain essai ...
Belle idée d'utiliser CTRL-Z, mais je n'aime pas les caractères de contrôle dans un fichier de commandes, car il est problématique de les copier-coller.
Cela dépend de votre navigateur, de votre éditeur, de votre ...
Vous pouvez également obtenir un VBScript/Batch hybride avec des caractères normaux et un 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
L'astuce consiste à ajouter à chaque ligne de lot set n=n'&
c'est légal pour les deux, mais vbs ignorera le reste de la ligne, seul le batch exécutera le reste de la ligne.
L'autre variante est :'remark ^
, il s'agit d'une remarque pour les deux, mais pour le lot, cette remarque concerne également la ligne suivante par le caractère multiligne.
Le VbScript voit alors a=1<1
le reste de la ligne est une remarque '
Le lot ne voit que <1' echo off <nul
, la première redirection de 1'
sera remplacé par le deuxième <nul
, il en résulte que echo off < nul
.
Le seul problème restant est que vous pouvez voir le premier echo off
, car cela ne fonctionne pas en batch pour utiliser le @
après une redirection.
Pour JScript existe une solution plus simple script hybride
J'ai essayé d'assembler toutes les solutions dans un seul script à http://www.dostips.com/forum/viewtopic.php?p=37780#p3778 .
Il y a le script batch qui convertit les langues les plus populaires en un fichier batch (. Js , . Vbs , . ps1 , . wsf , . hta et historique . pl ).
Cela fonctionne comme suit:
:: convertir filename1.vbs en exécutable filename1.bat cmdize.bat filename1.vbs
Et ma tentative ( d'abord posté ici ). Cela ressemble à la solution du 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:
'.exe
subst.exe
et doskey.exe
doskey.exe
à '.exe
(s'il n'existe pas déjà), puis continuez à l'utiliser comme '&
(comme l'extension .exe devrait être dans % PATHEXT% ). Cela sera considéré comme un commentaire dans VBScript et dans le lot ne fera rien - va simplement continuer avec la prochaine commande sur la ligne.Il y a bien sûr quelques défauts. Au moins pour la première exécution, vous aurez éventuellement besoin d'autorisations d'administrateur en tant que coping dans %windir%\System32\
peut être refusé. Pour la robustesse, vous pouvez également utiliser '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe .\'.exe >nul
puis à la fin: '& rem del /q .\'.exe
Avec '.exe
laissé sur votre chemin, vous pourriez involontairement l'utiliser de manière incorrecte, et l'exécution sur chaque ligne de '.exe pourrait éventuellement diminuer les performances.
..Et dans le lot, les commandes ne doivent être que sur une seule ligne.
Mise à jour 9.10.13 (..suivant la convention ci-dessus)
Voici une autre façon qui nécessite l'auto-renommage du fichier batch:
@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 courte explication:
CSCRIPT.EXE
avec .WSF
fichier. L'auto-renommage est un peu risqué, mais plus rapide qu'un fichier temporaire.& < > ;
donc @echo off
et goto
peuvent être utilisés sans soucis. Mais pour des raisons de sécurité, il est bon de mettre des commandes par lots dans la section des commentaires xml (ou CDATA). Pour éviter les messages d'erreur du lot, j'ai ignoré le <!--
avec goto
ici.exit
Donc, les bonnes choses sont qu'il n'est pas nécessaire d'écrire tout le code batch dans des commandes sur une seule ligne, il n'y a pas de _ echo off
affiché, du code jscript et différents travaux peuvent être ajoutés au script.Pas besoin de symboles spéciaux et de création de fichiers exe supplémentaires comme '.exe
En revanche, l'auto-renommage peut être risqué.
Il existe une solution très simple à ce problème. Utilisez simplement un Autre flux de données (ADS) pour stocker le code VBS. Pour l'expliquer simplement, un ADS est un autre endroit où vous pouvez stocker d'autres données dans le même fichier, c'est-à-dire qu'un fichier est composé de ses données d'origine plus n'importe quel nombre de ADS supplémentaires. Chaque ADS est identifié en séparant son propre nom du nom de fichier d'origine via 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 ADS sur 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.
Commencez par créer le fichier batch d'origine de la manière habituelle. Vous pouvez également démarrer notepad.exe à partir 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 test.bat
a été enregistré et le Bloc-notes fermé, créez le script VBS à l'aide du Bloc-notes, entrez donc cette commande sur la ligne de commande:
notepad test.bat:script_.vbs
Et créez 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
Enregistrez ce fichier et exécutez test.bat
. Ça marche! ;)
Vous pouvez consulter les ADS de test.bat
fichier via le /R
basculez dans la commande dir
. Vous pouvez lire une explication plus détaillée de cette méthode et de ses limites à ce post .