VB6 - ShellPipe "Shell with I/O Redirection" control
Note: Please see new attachment posted a few replies down!
Overview
ShellPipe is a VB6 UserControl that can be used to "shell" (run) a child process that uses the standard I/O streams, redirecting the child's streams to the anonymous pipes created in the parent process.
Much of this can be accomplished using the Scripting Runtime. However this has many limitations such as synchronous I/O operations that are not compatible with the event-driven model of the typical VB6 program.
This UserControl wraps up a lot of the Win32 API calls you might do this with yourself into a "black box" easily dropped into Projects.
Sort of like Winsock
So the ShellPipe control has an object model somewhat like the standard Winsock control.
Once the parent runs the child successfully (optionally passing a command line) the parent can write to the child's StdIn stream. Child events such as StdOut stream output and termination raise events in the parent.
Minor streamlining
Both StdOut and StdErr output from the child take one combined path back to the parent. You could easily break this out and use a second DataArrival Event or an additional parameter identifying the source.
Output polling is done using a Timer control to support Win9x, since Win9x cannot do overlapped I/O.
Different view of client/server
One way to look at the relationship is to consider the parent to be a "client" and the child a "server." This is more like the COM and RPC model of communication than what we think of with TCP/IP.
You can easily use a control array of ShellPipe controls to allow the parent to run multiple children.
Demo
Here I have a simple child program (server) which uses the Scripting Runtime for StdIO, since it doesn't need to do any async processing. This server accepts file directory lookup requests and returns a directory listing reply.
The parent program (client) uses a ShellPipe control to run the server. Then it awaits user input for directory lookups, formats/sends these requests to the server, and displays returned response data. While this goes on it runs a Timer-driven visual "heartbeat" to demonstrate the non-blocking nature of ShellPipe.
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
Error at:
strMsg = tsStdIn.ReadLine()
Method 'ReadLine' of object 'ITextStream" failed.
I have made of reference to Microsoft Scripting Runtime.
1 Attachment(s)
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
I recompiled the posted source and had no problem. Are you trying to run the "server" program in the IDE?
Ahh, that must be it.
No, to test the "server" separately in the IDE you would have to provide an alternate source for StdIn and StdOut.
Here's a hacked Main module allowing manual IDE testing:
Code:
Option Explicit
'
'Requires: Microsoft Scripting Runtime.
'
Private Declare Function AllocConsole Lib "kernel32" () As Long
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private tsStdIn As Scripting.TextStream
Private tsStdOut As Scripting.TextStream
Private Function DirTree( _
ByVal DirPath As String, _
ByVal Depth As Integer, _
Optional ByVal Level As Integer = 0) As String
Dim strLevelIndent As String
Dim colFolderNames As Collection
Dim strDirItem As String
Dim varDirPathItem As Variant
Dim lngAttr As Long
Const REPARSE_POINT As Long = &H400&
strLevelIndent = Space$(4 * Level)
Set colFolderNames = New Collection
On Error Resume Next
strDirItem = Dir$(DirPath, vbReadOnly Or vbHidden Or vbDirectory)
If Err.Number Then
DirTree = Err.Description
Exit Function
End If
On Error GoTo 0
Do Until Len(strDirItem) = 0
varDirPathItem = DirPath & strDirItem
'On Error Resume Next
lngAttr = GetAttr(varDirPathItem)
If Err.Number Then
DirTree = Err.Description
Exit Function
End If
On Error GoTo 0
If (lngAttr And REPARSE_POINT) = 0 Then
If (lngAttr And vbDirectory) <> 0 Then
If strDirItem <> "." And strDirItem <> ".." Then
colFolderNames.Add varDirPathItem & "\"
End If
Else
DirTree = DirTree & strLevelIndent & varDirPathItem & vbNewLine
End If
End If
strDirItem = Dir$()
Loop
Level = Level + 1
For Each varDirPathItem In colFolderNames
DirTree = DirTree & strLevelIndent & varDirPathItem & vbNewLine
If Level <= Depth Then
DirTree = DirTree & DirTree(varDirPathItem, Depth, Level)
End If
Next
End Function
Private Sub Main()
'Inbound requests:
'
' QUIT<newline>
'
'or:
'
' <depth>|<directory path><newline>
'
'Outbound responses:
'
' QUITTING
'
'or:
'
' <response length><newline><directory tree>
'
Dim strMsg As String
Dim strParts() As String
Dim IDEMode As Boolean
On Error Resume Next
Debug.Assert CBool(1 / 0)
IDEMode = CBool(Err.Number)
On Error GoTo 0
If IDEMode Then AllocConsole
With New Scripting.FileSystemObject
Set tsStdIn = .GetStandardStream(StdIn)
Set tsStdOut = .GetStandardStream(StdOut)
End With
Do
strMsg = tsStdIn.ReadLine()
If UCase$(strMsg) = "QUIT" Then
tsStdOut.WriteLine "QUITTING"
Exit Do
Else
Sleep 1500 'Hang around pretending this is lots of work.
strParts = Split(strMsg, "|")
strMsg = DirTree(strParts(1), CInt(strParts(0) - 1))
tsStdOut.WriteLine CStr(Len(strMsg))
tsStdOut.Write strMsg
End If
Loop
If IDEMode Then FreeConsole
End Sub
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
Your're not supposed to run the server by itself. Run the client only.
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
Quote:
Originally Posted by
dilettante
I recompiled the posted source and had no problem. Are you trying to run the "server" program in the IDE?
Ahh, that must be it.
No, to test the "server" separately in the IDE you would have to provide an alternate source for StdIn and StdOut.
The server failed in the both IDE & EXE.
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
If you must run the server by itself it must be linked for the Console Subsystem in Windows or else you need to allocate a console as suggested above.
The attachment here has a small script for relinking a compiled EXE. If you extract LinkConsole.vbs to the same folder as your compiled DirServer.exe, you can drag the EXE icon onto the VBS icon and drop it to relink DirServer.exe. This will cause it to open a console window when run stand-alone or you can run it within cmd.exe like any command line program.
Check the script first. It may need to be tweaked if you installed VB6 into a non-default location, since it uses LINK.EXE from the VB6 compiler tools.
1 Attachment(s)
Re: VB6 - ShellPipe "Shell with I/O Redirection" control
Ok, let's try this again.
The new attachment has the extra code in DirServer to create a Console window if run from the IDE. This means if you run it in the IDE, it pops up a Console window and you have to "play" being the client manually.
That is what the Console window screenshot above was all about.
Then you can compile and relink the DirServer.exe using LinkConsole.vbs (also in the new attachment).
From there you can open the DirClient project which uses the ShellPipe control. This can be run within the IDE or compiled and run. Since it is a Windows Subsystem program like most VB6 programs there is no need for any relinking of DirClient.exe. When you run DirClient (whether compiled or in the IDE) it runs the compiled and relinked DirServer.exe as a child process, writes to its StdIn and reads from its StdOut. You won't see any Console windows.
To be clear: To test DirClient you must first compile and relink DirServer.
The readme.txt has been updated to describe relinking for DirServer.exe.