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!
source to share
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
source to share
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
source to share
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?
source to share