Shell Standard Output in Visual Basic 6

First, let me say that I am not a Visual Basic 6 expert ...

I need:

  • run from VB6 client code exeternal.exe file
  • wait for the process to complete and - while it is running - read the messages coming from your standard output on the fly (so I can print it out to text widgets or analogies).

I am wondering if it is possible to do this in VB6 ... after a long search on the internet, I haven't come up with anything. Found many examples of how to use the function Shell

, but it seems to force me to read stdout all at once when the process is finished, but I want to poll the process for "fresh" messages as they become available.

Any code snippets / suggestions / links are really appreciated.

Thanks in advance!

+1


source to share


5 answers


Use CreatePipe()

to create an anonymous channel that you can transfer to CreateProcess()

. Then you can read that pipe as needed (using polling or overlapping / asynchronous I / O.



This will give you enough information to find a good example.

+6


source


You can always use the Exec method of WshShell to complete the job.



I prefer to use my own cExec.cls API based solution much simpler than Bob Rimersma's custom control (but not as versatile).

+4


source


You can also create a batch file with all the commands you need to execute, and then call the batch file from VB6 by executing

 Shell "C:\YourPath\BatchFileName.bat > OutputFileName.txt"   'Overwrites OutputFilename.txt everytime

      

after executing it, then open OutputFileName.txt

and you will find all messages and output that were generated during the batch process. Then you can read it in VB6 in a simpleopen "filename" for input as #1

You should also note that if you use double GreaterThan characters, the output file will not be overwritten every time a batch is executed. Instead, it will be appended to new lines of output.

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

      

+2


source


Here is the function you want. The execution of the declaration of API (CreatePipe, CreateProcessA, CloseHandle, etc.), Types (PROCESS_INFORMATION, STARTUPINFO, SECURITY_ATTRIBUTES) constants (STARTF_USESTDHANDLES, STARF_USESHOWWINDOW, etc.) is provided to the reader.

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

      

+1


source


In fact, Mr. Erickson, there are private variables (mCommand) that are undefined and events that are undefined, which seems to actually indicate the prevailing notion that this is just one member function ripped out from the class.

I suppose that recreating this class is left to the discretion of the reader, and also fixing the type mismatches that also show up in the code you provided? Thanks anyway and thanks to wqw for the class. Could you show some examples of use?

0


source







All Articles