Bri*_*rns 50
根据Andrew Lessard的回答,这是一个运行命令并将输出作为字符串返回的函数 -
Public Function ShellRun(sCmd As String) As String
    'Run a shell command, returning the output as a string
    Dim oShell As Object
    Set oShell = CreateObject("WScript.Shell")
    'run command
    Dim oExec As Object
    Dim oOutput As Object
    Set oExec = oShell.Exec(sCmd)
    Set oOutput = oExec.StdOut
    'handle the results as they are written to and read from the StdOut object
    Dim s As String
    Dim sLine As String
    While Not oOutput.AtEndOfStream
        sLine = oOutput.ReadLine
        If sLine <> "" Then s = s & sLine & vbCrLf
    Wend
    ShellRun = s
End Function
用法:
MsgBox ShellRun("dir c:\")
Ale*_* K. 20
您可以CreateProcess将应用程序重定向StdOut到管道,然后直接读取该管道; http://pastebin.com/CszKUpNS
dim resp as string 
resp = redirect("cmd","/c dir")
resp = redirect("ipconfig","")
根据主要来自布莱恩·伯恩斯(Brian Burns)的各种答案,这里是一个经过测试且功能齐全的简短版本:
Function F_shellExec(sCmd As String) As String
    Dim oShell   As New WshShell 'requires ref to Windows Script Host Object Model
    F_shellExec = oShell.Exec(sCmd).StdOut.ReadAll
End Function
它工作得很好而且速度很快。但是,如果输出太大(例如扫描整个 C: 驱动器sCmd = "DIR /S C:\"),ReadAll将会崩溃
所以我想出了下面的第二个解决方案,到目前为止,在这两种情况下都运行良好。请注意,第一次读取速度更快,如果崩溃,读取会从头开始,这样您就不会错过信息
Function F_shellExec2(sCmd As String) As String
    'Execute Windows Shell Commands
    Dim oShell  As New WshShell 'requires ref to Windows Script Host Object Model
    'Dim oExec   As WshExec 'not needed, but in case you need the type
    Dim oOutput As TextStream
    Dim sReturn As String
    Dim iErr    As Long
    
    'Set oExec = oShell.Exec(sCmd) 'unused step, for the type
    Set oOutput = oShell.Exec(sCmd).StdOut
    
    On Error Resume Next
    sReturn = oOutput.ReadAll
    iErr = Err.Number
    On Error GoTo 0
    
    If iErr <> 0 Then
        sReturn = ""
        While Not oOutput.AtEndOfStream
            sReturn = sReturn & oOutput.ReadLine & Chr(10)
        Wend
    End If
    
    F_shellExec2 = sReturn
    
End Function
关于对 的引用
Windows Script Host Object Model:您将需要添加对 的引用,以便了解Windows Script Host Object Model类型WshShell(和)。 (为此,请转到VBA IDE 菜单栏中的“工具” -> “参考” 。)WshExec
根据Brian Burns 的回答,我在调用期间向可执行文件添加了传递输入(使用StdInput)。以防万一有人偶然发现并有同样的需求。
''' <summary>
'''   Executes the given executable in a shell instance and returns the output produced
'''   by it. If iStdInput is given, it is passed to the executable during execution.
'''   Note: You must make sure to correctly enclose the executable path or any given
'''         arguments in quotes (") if they contain spaces.
''' </summary>
''' <param name="iExecutablePath">
'''   The full path to the executable (and its parameters). This string is passed to the
'''   shell unaltered, so be sure to enclose it in quotes if it contains spaces.
''' </param>
''' <param name="iStdInput">
'''   The (optional) input to pass to the executable. Default: Null
''' </param>
Public Function ExecuteAndReturnStdOutput(ByVal iExecutablePath As String, _
                                 Optional ByVal iStdInput As String = vbNullString) _
                As String
   Dim strResult As String
   Dim oShell As WshShell
   Set oShell = New WshShell
   Dim oExec As WshExec
   Set oExec = oShell.Exec(iExecutablePath)
   If iStdInput <> vbNullString Then
      oExec.StdIn.Write iStdInput
      oExec.StdIn.Close    ' Close input stream to prevent deadlock
   End If
   strResult = oExec.StdOut.ReadAll
   oExec.Terminate
   ExecuteAndReturnStdOutput = strResult
End Function
注意:您将需要添加
Windows Script Host Object Model对类型WshShell和WshExec已知的引用。
(要执行此操作,请转到VBA IDE 菜单栏中的Extras -> References。)
您可以使用以下小 C# 程序来测试来自 VBA 的调用。(如果您手边没有 Visual Studio (Express),您可以按照这些说明从一个简单的源文件快速编译它。):
using System;
class Program
{
   static void Main(string[] args)
   {
      // Read StdIn
      string inputText = Console.In.ReadToEnd();
      // Convert input to upper case and write to StdOut
      Console.Out.Write(inputText.ToUpper());
   }
}
在 VBA 中,您可以运行以下方法,该方法将显示一个包含“ABCDEF”的消息框:
Public Sub TestStdIn()
   MsgBox ExecuteAndReturnStdOutput("C:\ConvertStdInToUpper.exe", "abcdef")
End Sub
小智 5
Sub StdOutTest()
    Dim objShell As Object
    Dim objWshScriptExec As Object
    Dim objStdOut As Object
    Dim rline As String
    Dim strline As String
    Set objShell = CreateObject("WScript.Shell")
    Set objWshScriptExec = objShell.Exec("c:\temp\batfile.bat")
    Set objStdOut = objWshScriptExec.StdOut
    While Not objStdOut.AtEndOfStream
        rline = objStdOut.ReadLine
        If rline <> "" Then strline = strline & vbCrLf & CStr(Now) & ":" & Chr(9) & rline
       ' you can handle the results as they are written to and subsequently read from the StdOut object
    Wend
    MsgBox strline
    'batfile.bat
    'ping 1.1.1.1 -n 1 -w 2000 > nul
    'echo 2
    'ping 1.1.1.1 -n 1 -w 2000 > nul
    'echo 4
    'ping 1.1.1.1 -n 1 -w 2000 > nul
    'echo 6
    'ping 1.1.1.1 -n 1 -w 2000 > nul
    'echo 8
End Sub
小智 5
对于那些预期回报较小的情况,这是我见过的最短的命令:
MsgBox CreateObject("WScript.Shell").Exec("C:\Windows\SysWOW64\WHOAMI.EXE /USER /FO CSV").StdOut.ReadAll