Код VBscript для захвата stdout, без отображения окна консоли
Это пример кода VBScript, который показывает, как поймать то, что программа командной строки отправляет на стандартный вывод.
Он выполняет команду xcopy /?
и отображает вывод в окне сообщения. Прежде чем появится окно сообщения, в течение секунды вы увидите всплывающее окно консоли.
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
Вот еще один пример кода VBScript, в котором показано, как выполнить script, не показывая окно консоли.
objShell.Run "c:\temp\mybatch.bat C:\WINDOWS\system32\cmd.exe", 0
или
objShell.Run "c:\temp\myscript.vbs C:\WINDOWS\system32\cscript.exe", 0
Как видите, он имеет форму <script><space><executor>
.
В последнем примере вместо objShell.Exec
используется
objShell.Run
Я не знаю, как выполнить программу командной строки (если необходимо из пакетного файла), получить стандартный вывод, не показывая окно консоли. Любые идеи?
Ответы
Ответ 1
Это доказательство понятия script:
' pocBTicks.vbs - poor man 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
показывает, как использовать .Run и временные файлы, чтобы получить что-то вроде backticks со скрытой консолью. Достойная обработка файлов, цитирование в sCmd, очистка возвращаемых строк и обработка кодировок потребуют больше работы. Но, возможно, вы можете использовать стратегию для реализации того, что соответствует вашим потребностям.
Ответ 2
Я обычно использую это:
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
Для более продвинутых команд youc wrap для comspec (cmd)
my res = execStdOut("%comspec%" & " /c " & """" & "dir /b c:\windows\*.exe" & """" & " && Echo. && Echo finished")
Ответ 3
Чтобы перенаправить вывод на консоль, запустите script с помощью cscript, например: c:\cscript myscript.vbs
.
cscript имеет несколько параметров командной строки. Самым важным (для меня) является переключатель //NOLOGO. Если yoy его использует (cscript //nologo myscript.vbs
), он будет опускать товар Microsoft...
Ответ 4
Чтобы вернуть в VBA все подпапки в G:\OF
sub M_snb()
c00= createobejct("wscript.Shell").exec("cmd /c Dir G:\OF\*. /s/b").stdout.readall
end sub
чтобы разбить возвращаемую строку на массив
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
Ответ 5
Если вы не возражаете, если появится кнопка панели задач, вы можете просто переместить окно консоли на экран перед запуском.
Если существует клавиша HKCU\Console\WindowPosition
, Windows будет использовать ее значение для размещения окна консоли. Если ключ не существует, вы получите окно с системой.
Итак, сохраните исходное значение этого ключа, установите собственное значение, чтобы поместить его вне экрана, вызовите Exec()
и запишите его вывод, затем восстановите исходное значение ключа.
Ключ WindowPosition
ожидает 32-битное значение. Высоким словом является координата X, а нижнее слово - координата 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
Если вы действительно хотите, чтобы координаты были вне экрана, вы можете получить размеры экрана с помощью VBScript с помощью IE или других инструментов.
Ответ 6
Вместо WScript.Shell
рассмотрите возможность использования Win32_Process
с startupInfo.ShowWindow = 0
для запуска процесса с помощью SW_HIDE
. Я привел подробный пример в VBS Выполнить cmd.exe вывод в переменную; а не текстовый файл.