Ceci est un exemple de code VBScript qui montre comment intercepter tout programme envoyé par une ligne de commande à la sortie standard . Il exécute la commande xcopy /?
et affiche la sortie dans une boîte de message. Avant que la boîte de message ne s'affiche, la fenêtre de la console s'ouvre pendant une fraction de seconde.
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExec = objShell.Exec("xcopy /?")
Do
line = objExec.StdOut.ReadLine()
s = s & line & vbcrlf
Loop While Not objExec.Stdout.atEndOfStream
WScript.Echo s
Voici un autre exemple de code VBScript qui montre comment exécuter un script sans afficher la fenêtre de la console.
objShell.Run "c:\temp\mybatch.bat C:\WINDOWS\system32\cmd.exe", 0
ou
objShell.Run "c:\temp\myscript.vbs C:\WINDOWS\system32\cscript.exe", 0
Comme vous pouvez le constater, il a la forme <script><space><executor>
. Le dernier exemple utilise objShell.Run
au lieu de objShell.Exec
Ce que je ne sais pas, c'est comment exécuter un programme en ligne de commande (si nécessaire à partir d'un fichier de commandes), intercepter la sortie standard, sans afficher la fenêtre de la console. Des idées?
Ce script de preuve de concept:
' pocBTicks.vbs - poor man's version of backticks (POC)
Option Explicit
' Globals
Const SW_SHOWMINNOACTIVE = 7
Const ForReading = 1
Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )
Dim goWSH : Set goWSH = CreateObject( "WScript.Shell" )
' Dispatch
WScript.Quit demoBTicks()
' demoBTicks -
Function demoBTicks()
demoBTicks = 1
Dim aCmds : aCmds = Array( _
"dir pocBTicks.vbs" _
, "dur pocBTicks.vbs" _
, "xcopy /?" _
)
Dim sCmd
For Each sCmd In aCmds
WScript.Echo "########", sCmd
Dim aRet : aRet = BTicks( sCmd )
Dim nIdx
For nIdx = 0 To UBound( aRet )
WScript.Echo "--------", nIdx
WScript.Echo aRet( nIdx )
Next
Next
demoBTicks = 0
End Function ' demoBTicks
' BTicks - execute sCmd via WSH.Run
' aRet( 0 ) : goWSH.Run() result
' aRet( 1 ) : StdErr / error message
' aRet( 2 ) : StdOut
' aRet( 3 ) : command to run
Function BTicks( sCmd )
Dim aRet : aRet = Array( -1, "", "", "" )
Dim sFSpec2 : sFSpec2 = goFS.GetAbsolutePathName( "." )
Dim sFSpec1 : sFSpec1 = goFS.BuildPath( sFSpec2, goFS.GetTempName() )
sFSpec2 = goFS.BuildPath( sFSpec2, goFS.GetTempName() )
aRet( 3 ) = """%COMSPEC%"" /c """ + sCmd + " 1>""" + sFSpec1 + """ 2>""" + sFSpec2 + """"""
Dim aErr
On Error Resume Next
aRet( 0 ) = goWSH.Run( aRet( 3 ), SW_SHOWMINNOACTIVE, True )
aErr = Array( Err.Number, Err.Description, Err.Source )
On Error GoTo 0
If 0 <> aErr( 0 ) Then
aRet( 0 ) = aErr( 0 )
aRet( 1 ) = Join( Array( aErr( 1 ), aErr( 2 ), "(BTicks)" ), vbCrLf )
BTicks = aRet
Exit Function
End If
Dim nIdx : nIdx = 1
Dim sFSpec
For Each sFSpec In Array( sFSpec2, sFSpec1 )
If goFS.FileExists( sFSpec ) Then
Dim oFile : Set oFile = goFS.GetFile( sFSpec )
If 0 < oFile.Size Then
aRet( nIdx ) = oFile.OpenAsTextStream( ForReading ).ReadAll()
goFS.DeleteFile sFSpec
End If
End If
nIdx = nIdx + 1
Next
BTicks = aRet
End Function
montre comment utiliser les fichiers .Run et les fichiers temporaires pour obtenir quelque chose comme un backtick avec une console cachée. Un traitement de fichier correct, la citation dans sCmd, le nettoyage des chaînes retournées et le traitement des encodages nécessiteront davantage de travail. Mais peut-être pouvez-vous utiliser la stratégie pour mettre en œuvre quelque chose qui correspond à vos besoins.
J'utilise habituellement ceci:
Wscript.echo execStdOut("ping google.com")
Function execStdOut(cmd)
Dim goWSH : Set goWSH = CreateObject( "WScript.Shell" )
Dim aRet: Set aRet = goWSH.exec(cmd)
execStdOut = aRet.StdOut.ReadAll()
End Function
Pour des commandes plus avancées, vous devez utiliser wrap to comspec (cmd)
my res = execStdOut("%comspec%" & " /c " & """" & "dir /b c:\windows\*.exe" & """" & " && Echo. && Echo finished")
Afin de rediriger la sortie vers la console, exécutez le script en utilisant cscript, ex .: c:\cscript myscript.vbs
.
cscript a quelques options en ligne de commande. Le plus important (pour moi) est le commutateur // NOLOGO. Si vous l'utilisez (cscript //nologo myscript.vbs
), les produits Microsoft seront omis ...
Si cela ne vous dérange pas que le bouton barre des tâches apparaisse, vous pouvez simplement déplacer la fenêtre de la console hors écran avant de la lancer.
Si la clé HKCU\Console\WindowPosition
existe, Windows utilisera sa valeur pour positionner la fenêtre de la console. Si la clé n'existe pas, vous obtenez une fenêtre positionnée par le système.
Enregistrez donc la valeur d'origine de cette clé, définissez votre propre valeur pour la positionner à l'écran, appelez Exec()
et capturez sa sortie, puis restaurez la valeur d'origine de la clé.
La clé WindowPosition
attend une valeur 32 bits. Le mot haut est la coordonnée X et le mot bas, la coordonnée Y (XXXXYYYY
).
With CreateObject("WScript.Shell")
' Save the original window position. If system-positioned, this key will not exist.
On Error Resume Next
intWindowPos = .RegRead("HKCU\Console\WindowPosition")
On Error GoTo 0
' Set Y coordinate to something crazy...
.RegWrite "HKCU\Console\WindowPosition", &H1000, "REG_DWORD"
' Run Exec() and capture output (already demonstrated by others)...
.Exec(...)
' Restore window position, if previously set. Otherwise, remove key...
If Len(intWindowPos) > 0 Then
.RegWrite "HKCU\Console\WindowPosition", intWindowPos, "REG_DWORD"
Else
.RegDelete "HKCU\Console\WindowPosition"
End If
End With
Si vous (vraiment} _ voulez vous assurer que les coordonnées sont hors écran, vous pouvez obtenir les dimensions de l'écran via VBScript à l'aide de IE ou d'autres outils.
C’est ainsi que vous pouvez obtenir la ligne de commande StdOut (résultat) sans voir cette fenêtre contextuelle noire en vbscript
Set Sh = CreateObject("WScript.Shell")
tFile=Sh.ExpandEnvironmentStrings("%Temp%")&"\t.txt"
Sh.Run "cmd.exe /c xcopy /? > """&tFile&""" ",0,False
Wscript.echo CreateObject("Scripting.FileSystemObject").openTextFile(tFile).readAll()
Pour retourner dans VBA tous les sous-dossiers de G:\OF
sub M_snb()
c00= createobejct("wscript.Shell").exec("cmd /c Dir G:\OF\*. /s/b").stdout.readall
end sub
diviser la chaîne retournée dans un tableau
sub M_snb()
sn=split(createobejct("wscript.Shell").exec("cmd /c Dir G:\OF\*. /s/b").stdout.readall,vbCrLf)
for j=0 to ubound(sn)
msgbox sn(j)
next
End Sub