Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadID As Long
End Type
Private Declare Function ShellExecute Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal _
lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Private Declare Function FindExecutable Lib "shell32.dll" Alias _
"FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, _
ByVal lpResult As String) As Long
Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, _
phWritePipe As Long, lpPipeAttributes As Any, ByVal nSize As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal HFile As Long, ByVal _
lpBuffer As String, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead _
As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal HFile As Long, _
lpFileSizeHigh As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle _
As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
lpApplicationName As Long, ByVal lpCommandLine As String, _
lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles _
As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal _
lpCurrentDirectory As Long, lpStartupInfo As Any, lpProcessInformation As _
Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As _
Long, ByVal uExitCode As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Function GetDriveLetter(ByVal PathString As String) As String
Dim DriveStr As String
DriveStr = Trim$(PathString)
If InStr(DriveStr, ":") = 2 Then
GetDriveLetter = Left$(DriveStr, 2)
Else
GetDriveLetter = "C:"
End If
End Function
Public Sub StartProcess(BatchFile As String, InitialPath As String, strOutput As _
String, strError As String)
Dim ProcInfo As PROCESS_INFORMATION
Dim ret As Long
Dim lSuccess As Long
Dim StartInfo As STARTUPINFO
Dim SecAttr As SECURITY_ATTRIBUTES
Dim hReadPipe1 As Long
Dim hWritePipe1 As Long
Dim hReadPipe2 As Long
Dim hWritePipe2 As Long
Dim BytesRead As Long
Dim stdoutBuff As String
Dim stderrBuff As String
Dim BytesLeft As Long
Dim CurrFolder As String
Dim StdOutCharCount As Integer
Dim StdErrCharCount As Integer
Dim ShowPipeError As Boolean
Dim fName As String
If ret <> 1 Then
CloseHandle (hReadPipe1)
CloseHandle (hWritePipe1)
CloseHandle (hReadPipe2)
CloseHandle (hWritePipe2)
Exit Sub
End If
StdOutCharCount = 0
StdErrCharCount = 0
Do
Do
BytesLeft = GetFileSize(hReadPipe1, 0&)
If BytesLeft = -1 Then ShowPipeError = True
If BytesLeft > 0 Then
stdoutBuff = String(BytesLeft, " ")
lSuccess = ReadFile(hReadPipe1, stdoutBuff, BytesLeft, BytesRead, 0&)
DoEvents
If lSuccess = 1 Then
StdOutCharCount = StdOutCharCount + Len(Left(stdoutBuff, BytesRead))
strOutput = strOutput + Left(stdoutBuff, BytesRead)
'strOutput.SelStart = Len(strOutput)
'strOutput.Refresh
DoEvents
End If
End If
Loop Until BytesLeft <= 0
Do
BytesLeft = GetFileSize(hReadPipe2, 0&)
If BytesLeft = -1 Then ShowPipeError = True
If BytesLeft > 0 Then
stderrBuff = String(BytesLeft, " ")
lSuccess = ReadFile(hReadPipe2, stderrBuff, BytesLeft, BytesRead, 0&)
DoEvents
If lSuccess = 1 Then
StdErrCharCount = StdErrCharCount + Len(Left(stderrBuff, BytesRead))
strError = strError + Left(stderrBuff, BytesRead)
'strError.SelStart = Len(strOutput)
'strError.Refresh
DoEvents
End If
End If
Loop Until BytesLeft <= 0
lSuccess = WaitForSingleObject(ProcInfo.hProcess, 1)
BytesLeft = GetFileSize(hReadPipe1, 0&) + GetFileSize(hReadPipe2, 0&)
Loop Until lSuccess = 0 And BytesLeft <= 0
MSKB Q173085 HOWTO: Create a Process for Reading and Writing to a Pipe
This example illustrates a Visual Basic application starting another process with the purpose of redirecting that process's standard IO handles. The Visual Basic application redirects the created process's standard output handle to an anonymous pipe, then proceeds to read the output through the pipe. This sample just redirects STDOUT of the new process. To redirect other handles (STDIN and STDERR), create a pipe for each handle for which redirection is desired. The Visual Basic application would read from the read ends of the pipes for the redirected STDOUT and STDERR. If STDIN redirection was desired, the Visual Basic application would write to the write end of the appropriate pipe.