VB6 - ShellPipe "Shell with I/O Redirection" control-VBForums
Results 1 to 10 of 10

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

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

    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
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,058

    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

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

    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 2008
    Posts
    11,072

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

    Your're not supposed to run the server by itself. Run the client only.


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  5. #5
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,058

    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

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

    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

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

    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

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

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

    Here is an update to ShellPipe.

    This is version 7 which optionally breaks out child process output, i.e. data written to StdOut and StdErr can be received separately by the parent program. There are also some minor bug fixes.

    By default the new property ErrAsOut = True, making version 7 highly compatible with earlier versions. But when ErrAsOut = False several new events, methods, and properties prefixed ErrXXXX come into play.


    The hardest part about dropping version 7 into a project previously using an earlier version is that the buffer class SmartBuffer was renamed as a more modest SPBuffer (in response to several snide remarks about the grandiose name). So to "upgrade" a Project you now need to copy the new files ShellPipe.ctl, ShellPipe.ctx, and SPBuffer.cls into the Project folder and also remove SmartBuffer.cls from the Project and add SPBuffer.cls to it instead.

    So a .VBP beginning:

    Code:
    Type=Exe
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\..\Windows\system32\stdole2.tlb#OLE Automation
    Form=Form1.frm
    UserControl=ShellPipe.ctl
    Class=SmartBuffer; SmartBuffer.cls
    Becomes:

    Code:
    Type=Exe
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\Windows\system32\stdole2.tlb#OLE Automation
    Form=Form1.frm
    UserControl=ShellPipe.ctl
    Class=SPBuffer; SPBuffer.cls
    I hope you find it useful.

    ShellPipe version 7 is attached here as a ZIP archive containing a very small VB6 Project that uses it. This Project just uses ShellPipe to run cscript.exe against a supplied script test.vbs, send some input to the script via StdIn and capture output from the script via the StdOut and StdErr streams.
    Attached Files Attached Files
    Last edited by dilettante; May 26th, 2014 at 02:08 PM. Reason: reposted attachment, minor cleanup & bug fix

  9. #9
    Member
    Join Date
    May 2013
    Posts
    47

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

    Quote Originally Posted by dilettante View Post
    Here is an update to ShellPipe.

    This is version 7 which optionally breaks out child process output, i.e. data written to StdOut and StdErr can be received separately by the parent program. There are also some minor bug fixes.

    By default the new property ErrAsOut = True, making version 7 highly compatible with earlier versions. But when ErrAsOut = False several new events, methods, and properties prefixed ErrXXXX come into play.


    The hardest part about dropping version 7 into a project previously using an earlier version is that the buffer class SmartBuffer was renamed as a more modest SPBuffer (in response to several snide remarks about the grandiose name). So to "upgrade" a Project you now need to copy the new files ShellPipe.ctl, ShellPipe.ctx, and SPBuffer.cls into the Project folder and also remove SmartBuffer.cls from the Project and add SPBuffer.cls to it instead.

    So a .VBP beginning:

    Code:
    Type=Exe
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\..\Windows\system32\stdole2.tlb#OLE Automation
    Form=Form1.frm
    UserControl=ShellPipe.ctl
    Class=SmartBuffer; SmartBuffer.cls
    Becomes:

    Code:
    Type=Exe
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\Windows\system32\stdole2.tlb#OLE Automation
    Form=Form1.frm
    UserControl=ShellPipe.ctl
    Class=SPBuffer; SPBuffer.cls
    I hope you find it useful.

    ShellPipe version 7 is attached here as a ZIP archive containing a very small VB6 Project that uses it. This Project just uses ShellPipe to run cscript.exe against a supplied script test.vbs, send some input to the script via StdIn and capture output from the script via the StdOut and StdErr streams.
    Can you tell me what you use this;;Can do inter-process communication

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    16,149

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

    My own uses are many.

    There are lots of command line programs that do not come in an equivalent DLL usable from VB6, or in some cases no "free" DLL when I have a customer who insists on using someting free.

    It is also possible to write formless VB6 programs or WSH scripts that can be run as background worker processes but require some back and forth communication. This communication can be commands sent to the child process and results or status returned back from such children.

    Anonymous pipes are probably the most basic form of IPC we have.

    But this does not do things like reach out to arbitrary processes. It is meant for well defined scenarios where your VB6 program starts and runs some external command line program.

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
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.