VBscript代码捕获stdout,而不显示控制台窗口
这是一个VBScript代码示例,显示如何捕捉命令行程序发送到标准输出的任何内容。 它执行命令xcopy /?
并在消息框中显示输出。 在消息框出现之前,一会儿你会看到控制台窗口popup。
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代码示例,显示如何执行脚本而不显示控制台窗口。
objShell.Run "c:\temp\mybatch.bat C:\WINDOWS\system32\cmd.exe", 0
要么
objShell.Run "c:\temp\myscript.vbs C:\WINDOWS\system32\cscript.exe", 0
正如你所看到的,它的forms是<script><space><executor>
。 最后一个示例使用objShell.Run
而不是objShell.Exec
我不知道的是如何执行一个命令行程序(如果需要从一个batch file中),捕获标准输出,而不显示控制台窗口。 有任何想法吗?
这个脚本的certificate:
' 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
演示了如何使用.Run和临时文件来获得像隐藏控制台一样的反引号。 体面的文件处理,在sCmd中引用,清理返回的string以及处理编码需要更多的工作。 但也许你可以使用这个策略来实现一些符合你的需求的东西。
我通常使用这个:
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
对于更高级的命令你可以换一个comspec(cmd)
my res = execStdOut("%comspec%" & " /c " & """" & "dir /bc:\windows\*.exe" & """" & " && Echo. && Echo finished")
为了将输出redirect到控制台,请使用cscript运行脚本,例如: c:\cscript myscript.vbs
。
cscript有几个命令行选项。 对我来说最重要的是切换// NOLOGO。 如果同时使用它( cscript //nologo myscript.vbs
),它将省略微软商品…
如果您不介意显示任务栏button,则可以在启动之前将控制台窗口移出屏幕。
如果存在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
如果你真的想确保坐标是离屏的,你可以通过使用IE或其他工具通过VBScript获得屏幕尺寸。
要在VBA中返回G:\ OF中的所有子文件夹
sub M_snb() c00= createobejct("wscript.Shell").exec("cmd /c Dir G:\OF\*. /s/b").stdout.readall end sub
将返回的string拆分成一个数组
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
而不是WScript.Shell
,考虑使用使用Win32_Process
与startupInfo.ShowWindow = 0
启动与SW_HIDE
。 我在VBS下发布了一个详细的例子运行cmd.exe输出到一个variables; 不是文本文件 。