Results 1 to 7 of 7

Thread: VB6 - ShellPipe "Shell with I/O Redirection" control

  1. #1
    PowerPoster
    Join Date
    Feb 06
    Posts
    8,685

    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.
    Last edited by dilettante; Aug 18th, 2012 at 07:49 AM. Reason: deleted original attachment, see new one below

  2. #2
    Addicted Member
    Join Date
    Jan 10
    Posts
    237

    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.

  3. #3
    PowerPoster
    Join Date
    Feb 06
    Posts
    8,685

    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
    Attached Images Attached Images  

  4. #4
    PowerPoster
    Join Date
    Jan 08
    Posts
    6,886

    Re: VB6 - ShellPipe "Shell with I/O Redirection" control

    Your're not supposed to run the server by itself. Run the client only.
    The better the information you give to begin with and the sooner you reply the sooner you will get help and get your problem resolved


    When I was young and in my prime I used to program all the time but now I'm old and getting gray I only program once a day

  5. #5
    Addicted Member
    Join Date
    Jan 10
    Posts
    237

    Re: VB6 - ShellPipe "Shell with I/O Redirection" control

    Quote Originally Posted by dilettante View Post
    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.

  6. #6
    PowerPoster
    Join Date
    Feb 06
    Posts
    8,685

    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.
    Last edited by dilettante; Aug 18th, 2012 at 07:48 AM. Reason: delted original attachment, now included in the new one below

  7. #7
    PowerPoster
    Join Date
    Feb 06
    Posts
    8,685

    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.
    Attached Files Attached Files

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •