Shell进程在Visual Basic 6中的标准输出读数

时间:2011-09-12 10:52:14

标签: vb6 process stdout polling

首先,我要说我不是Visual Basic 6专家......

我的需要是:

  • 从VB6客户端代码启动一个外部.exe文件
  • 等待该过程完成,并且 - 在执行期间 - “动态”读取来自其标准输出的消息(以便我可以在文本提交的小部件或类似物上打印它)。

我想知道是否有可能在VB6中这样做...在互联网上长时间搜索之后我没有想出任何东西。找到了很多关于如何使用Shell函数的例子,但它似乎迫使我在进程执行结束时一次性读取stdout,但我想在流程中查询“新鲜”消息因为它们可用。

非常感谢任何代码段/建议/参考。

提前致谢!

4 个答案:

答案 0 :(得分:6)

使用CreatePipe()创建一个可以传递给CreateProcess()的匿名管道。 然后,您可以根据需要从此管道中读取(使用轮询或重叠/异步I / O.

这应该为您提供足够的信息以找到一个好的例子。

答案 1 :(得分:4)

您始终可以使用Exec method of WshShell来完成这项工作。

我更喜欢使用自行开发的基于API的解决方案cExec.cls比Bob Riemersma的用户控件简单得多(但不是那么通用)。

答案 2 :(得分:2)

您还可以创建一个批处理文件,其中包含您需要运行的所有命令,然后从VB6执行

调用批处理文件
 Shell "C:\YourPath\BatchFileName.bat > OutputFileName.txt"   'Overwrites OutputFilename.txt everytime

执行该操作后,再打开OutputFileName.txt,您将找到批处理过程中生成的所有消息和输出。然后,您可以使用简单的open "filename" for input as #1

在VB6中阅读它

您还应注意,如果使用Double GreaterThan符号,则每次批处理运行时都不会覆盖输出文件。相反,它会附加新的输出行。

 Shell "C:\YourPath\BatchFileName.bat >> OutputFileName.txt"    'This will append to OutputFileName.txt

答案 3 :(得分:1)

这是您想要的功能。声明API(CreatePipe,CreateProcessA,CloseHandle等),类型(PROCESS_INFORMATION,STARTUPINFO,SECURITY_ATTRIBUTES)常量(STARTF_USESTDHANDLES,STARF_USESHOWWINDOW等)的练习留给读者。

Public Function ExecuteCommand(ByVal CommandLine As String, Optional bShowWindow As Boolean = False, Optional sCurrentDir As String) As String
        Dim proc As PROCESS_INFORMATION     'Process info filled by CreateProcessA
        Dim ret As Long                     'long variable for get the return value of the
        'API functions
        Dim start As STARTUPINFO            'StartUp Info passed to the CreateProceeeA
        'function
        Dim sa As SECURITY_ATTRIBUTES       'Security Attributes passeed to the
        'CreateProcessA function
        Dim hReadPipe As Long               'Read Pipe handle created by CreatePipe
        Dim hWritePipe As Long              'Write Pite handle created by CreatePipe
        Dim lngBytesRead As Long            'Amount of byte read from the Read Pipe handle
        Dim strBuff As String * 256         'String buffer reading the Pipe


        'if the parameter is not empty update the CommandLine property


          If Len(CommandLine) > 0 Then
              mCommand = CommandLine
          End If

        'if the command line is empty then exit whit a error message
          If Len(mCommand) = 0 Then
              ApplicationEventLogError "Command Line empty in procedure ExecuteCommand of module modPipedOutput."
              Exit Function
          End If

        'Create the Pipe
          sa.nLength = Len(sa)
          sa.bInheritHandle = 1&
          sa.lpSecurityDescriptor = 0&
          ret = CreatePipe(hReadPipe, hWritePipe, sa, 0)

          If ret = 0 Then
            'If an error occur during the Pipe creation exit
              Debug.Print "CreatePipe failed. Error: " & Err.LastDllError & " (" & ReturnError(Err.LastDllError)
              Exit Function
          End If


        'Launch the command line application
          start.cb = Len(start)
          start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW

        'set the StdOutput and the StdError output to the same Write Pipe handle
          start.hStdOutput = hWritePipe
          start.hStdError = hWritePipe
        '    start.hStdInput = hInReadPipe
          If bShowWindow Then
              start.wShowWindow = SW_SHOWNORMAL
          Else
              start.wShowWindow = SW_HIDE
          End If

        'Execute the command
          If Len(sCurrentDir) = 0 Then
              ret& = CreateProcessA(0&, mCommand, sa, sa, 1&, _
                  NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
          Else
              ret& = CreateProcessA(0&, mCommand, sa, sa, 1&, _
                  NORMAL_PRIORITY_CLASS, 0&, sCurrentDir, start, proc)
          End If

          If ret <> 1 Then
            'if the command is not found ....
              Debug.Print "File or command not found in procedure ExecuteCommand"
              Exit Function
          End If

        'Now We can ... must close the hWritePipe
          ret = CloseHandle(hWritePipe)
        '    ret = CloseHandle(hInReadPipe)
          mOutputs = vbNullString

        'Read the ReadPipe handle
          Do
              ret = ReadFile(hReadPipe, strBuff, 256, lngBytesRead, 0&)

              mOutputs = mOutputs & Left$(strBuff, lngBytesRead)
            'Send data to the object via ReceiveOutputs event

          Loop While ret <> 0

        'Close the opened handles
          Call CloseHandle(proc.hProcess)
          Call CloseHandle(proc.hThread)
          Call CloseHandle(hReadPipe)

        'Return the Outputs property with the entire DOS output
          ExecuteCommand = mOutputs

End Function