web-dev-qa-db-fra.com

Code VBscript pour capturer la sortie standard, sans afficher la fenêtre de la console

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?

18
mgr326639

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.

3
Ekkehard.Horner

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") 
14
Jakob Sternberg

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 ...

6
Bob Rivers

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.

1
Bond

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()
0
hollopost

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
0
snb