dcsimg
Results 1 to 29 of 29

Thread: Best way to communicate between two known vb6 apps?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Best way to communicate between two known vb6 apps?

    I want to communicate two apps, these are both running in the same USER space, are in the same host, BUT I don't want it to be sockets, or anything that generate DISK I/O traffic.

    Both programs already has the pHnd of the other app.

    I am looking for the Simpliest/low resources way.

  2. #2
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    13,020

    Re: Best way to communicate between two known vb6 apps?

    Well, using sockets, UDP or TCP would be my first thought but you say you don't want to do that though not sure why as that does not generate disk operations. DDE may be an option though I have never used it for this purpose and am not sure how well that would work for you.

    What vaolume and frequency of info are you looking to communicate between them?

  3. #3
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    3,654

    Re: Best way to communicate between two known vb6 apps?

    If you have to access to the source code of both programs you can have a look at named pipes:
    http://www.vbforums.com/showthread.p...er-Named-Pipes

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by DataMiser View Post
    Well, using sockets, UDP or TCP would be my first thought but you say you don't want to do that though not sure why as that does not generate disk operations. DDE may be an option though I have never used it for this purpose and am not sure how well that would work for you.

    What vaolume and frequency of info are you looking to communicate between them?
    just poking an integer to reset a watchdog. Actually I use the registry with no_save attribute, but I think that is too costly, that can be simplier.

    the reasoung not to use sockets, is for maintain the nComputing compatibility, If I just send an UDP, maybe that message is picked up by the other side app from other user running at the same host. And it is not guarantee to be picked up!, so the algorithm can be broken.
    Last edited by flyguille; Sep 20th, 2018 at 08:32 AM.

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by Arnoutdv View Post
    If you have to access to the source code of both programs you can have a look at named pipes:
    http://www.vbforums.com/showthread.p...er-Named-Pipes
    I don't think this is guarantee to connect inside the same user space and only by the counterpart of the same Windows user.



    I was looking for at a program that uses the Window message stack, it required to have atleast one Window being visible, as it uses FindWindow, now FindWindow will be limited to the same user space.

    Maybe I can to setup a visible window which is not really visible, but marked as visible.

    But if there is a way given the pHnd to find a known invisible window of it, that will be better.

  6. #6
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    13,020

    Re: Best way to communicate between two known vb6 apps?

    Yes UDP is unreliable if you just send and forget. If you return a response then you know the data was received.

    But yes I suppose you could use a hidden text box or something and then use API to find window and set the text of that textbox as needed.

  7. #7
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    576

    Re: Best way to communicate between two known vb6 apps?

    Provided that the applications are both running on the default desktop, I believe you can communicate through the taskbar with the hidden.
    The sending application looks like this:
    Code:
    Option Explicit
    Private Type CopyDataStruct
        dwData As Long
        cbData As Long
        lpData As Long
    End Type
    Private Declare Function apiFindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function apiSendMessage Lib "User32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As CopyDataStruct) As Long
    Private Declare Sub apiCopyMemory Lib "Kernel32" Alias "RtlMoveMemory" (ByRef Destination As Byte, ByRef Source As String, ByVal Length As Long)
    Private Sub cmdSend_Click()
        If Trim(txtText.Text) = "" Then Exit Sub
        Call SendCommand(txtText.Text)
    End Sub
    Private Sub cmdStop_Click()
        Call SendCommand(Chr(1) & "QUIT")
        Unload Me
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        Unload Me
    End Sub
    Private Sub SendCommand(ByVal SendData As String)
        Const WM_ACTIVATE       As Long = &H6
        Const WM_COPYDATA       As Long = &H4A
        Const APP_NAME          As String = "Receiver"
        Const CLASS_NAME_HIDDEN As String = "SystemTray_HiddenWindow_"
        Const RECEIVED_DATA     As String = "Received_Data_"
        Dim buff(1 To 255)      As Byte
        Dim cData               As CopyDataStruct
        Dim hwnd                As Long
        Dim strData             As String
        If Len(RECEIVED_DATA & SendData) > 254 Then
            MsgBox "Data overflow (Maximum is 238 characters)"
            Exit Sub
        End If
        hwnd = apiFindWindow(vbNullString, CLASS_NAME_HIDDEN & APP_NAME)
        strData = RECEIVED_DATA & SendData
        If hwnd = 0 Then hwnd = apiFindWindow(vbNullString, APP_NAME)
        If hwnd = 0 Then Exit Sub
        Call apiCopyMemory(buff(1), ByVal strData, Len(strData))
        With cData
            .dwData = 3
            .cbData = Len(strData) + 1
            .lpData = VarPtr(buff(1))
        End With
        Call apiSendMessage(hwnd, WM_COPYDATA, WM_ACTIVATE, cData)
    End Sub
    The receiving application looks like this:
    Code:
    Option Explicit
    Private Sub Form_Load()
        Call HookSystemTray(hWnd)
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        Unload Me
    End Sub
    Public Sub ReceivedData(ByVal Data As String)
        If Data = Chr(1) & "QUIT" Then
            Unload Me
        Else
            lblText.Caption = Data & " - Visible = " & Visible
        End If
    End Sub
    In a module:
    Code:
    Option Explicit
    Private Const GWL_WNDPROC As Long = -4
    Public Const WM_ACTIVATE       As Long = &H6
    Public Const WM_COPYDATA       As Long = &H4A
    Public Const RECEIVED_DATA     As String = "Received_Data_"
    Public Type CopyDataStruct
        dwData                      As Long
        cbData                      As Long
        lpData                      As Long
    End Type
    Private Declare Function apiStrLen Lib "Kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long
    Private Declare Function apiCallWindowProc Lib "User32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function apiSetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Sub apiCopyMemoryBYTE Lib "Kernel32" Alias "RtlMoveMemory" (ByRef Destination As Byte, ByRef Source As Long, ByVal Length As Long)
    Private Declare Sub apiCopyMemorySTRUCT Lib "Kernel32" Alias "RtlMoveMemory" (ByRef Destination As CopyDataStruct, ByRef Source As Long, ByVal Length As Long)
    Private PrevSystemTray    As Long
    
    Public Sub HookSystemTray(ByVal hWnd As Long)
        If PrevSystemTray <> 0 Then
            Call apiSetWindowLong(hWnd, GWL_WNDPROC, PrevSystemTray)
            PrevSystemTray = 0
        Else
            PrevSystemTray = apiSetWindowLong(hWnd, GWL_WNDPROC, AddressOf SystemTrayWinProc)
        End If
    End Sub
    Private Function SystemTrayWinProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Dim bytBuffer(1 To 255) As Byte
        Dim cdsData             As CopyDataStruct
        Dim strData             As String
        If (uMsg = WM_COPYDATA) And (wParam = WM_ACTIVATE) Then
            Call apiCopyMemorySTRUCT(cdsData, ByVal lParam, Len(cdsData))
            With cdsData
                If .dwData = 3 Then
                    Call apiCopyMemoryBYTE(bytBuffer(1), ByVal .lpData, .cbData)
                    strData = StrConv(bytBuffer, vbUnicode)
                    If Left(strData, Len(RECEIVED_DATA)) = RECEIVED_DATA Then
                        strData = Mid(strData, Len(RECEIVED_DATA) + 1)
                        strData = Left(strData, apiStrLen(StrPtr(strData)))
                        Call frmReceiver.ReceivedData(strData)
                    End If
                End If
            End With
        End If
        SystemTrayWinProc = apiCallWindowProc(PrevSystemTray, hWnd, uMsg, wParam, lParam)
    End Function
    Attached Files Attached Files

  8. #8
    Addicted Member
    Join Date
    Jun 2018
    Posts
    177

    Re: Best way to communicate between two known vb6 apps?

    What about Memory Mapped File concept as an efficient IPC technique?

    http://www.vbforums.com/showthread.p...pped-File-Demo

  9. #9
    Hyperactive Member
    Join Date
    Feb 2017
    Posts
    457

    Re: Best way to communicate between two known vb6 apps?

    I'm personally a fan of using the textbox change event.
    You can put a textbox in one or both apps depending on which way communication needs to flow.
    Use FindWindow to locate the App.Hwnd of interest, and then the Hwnd of the textbox.
    Use SendMessage to communicate with the textbox.
    The textbox change event will automatically receive that message and you can set up a Select Case for
    whatever message and action you want.
    Simple, Works Great, and I use it all the time.

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by vb6forever View Post
    I'm personally a fan of using the textbox change event.
    You can put a textbox in one or both apps depending on which way communication needs to flow.
    Use FindWindow to locate the App.Hwnd of interest, and then the Hwnd of the textbox.
    Use SendMessage to communicate with the textbox.
    The textbox change event will automatically receive that message and you can set up a Select Case for
    whatever message and action you want.
    Simple, Works Great, and I use it all the time.
    just Form.Caption weirdprefix + value

    and let the other side to find it with the weirdprefix , FindWindow support asterics as find expression?

  11. #11
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    If you are going to rely on window spelunking to rendezvous you might as well define custom messages within WM_APP through 0xBFFF. Of course the problems with window spelunking include things like the inability to run more than one copy of such a multi-process application within each Windows session. You may also run into process isolation issues if your processes run at different integrity levels.

  12. #12
    Fanatic Member
    Join Date
    Dec 2014
    Posts
    864

    Re: Best way to communicate between two known vb6 apps?

    why not just run both forms from the same project.
    i mean, u can have multiple forms running.
    or, run the second executable from the first project to gain access to its memory.

  13. #13
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    2,017

    Re: Best way to communicate between two known vb6 apps?

    OK, maybe i'm just stupid, but if those two programs run in the same userspace on the same machine....
    Why not setup the program "receiver" as ActiveX-Exe-Server, and set a reference in "sender" to that Exe?
    The only thing you'd need in "receiver" is a public class-method you could call from "sender"
    One System to rule them all, One IDE to find them,
    One Code to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    For health reasons i try to avoid reading unformatted Code

  14. #14
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    It should be noted that UDP within the same machine has no reliable delivery issues. It never goes down into the underlying network protocol stack, let alone onto the wire (physical media).

    You could also use Mailslots, the Microsoft analog of UDP but with a richer namespace (not limited to 64K port numbers). Sadly we have no free ActiveX library supporting that so receivers need to block or use a polling loop or a worker thread via one technique or another. Between machines networked over IP it uses UDP over the SMB ports.

  15. #15
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    13,020

    Re: Best way to communicate between two known vb6 apps?

    What I was talking about being unreliable was the send and forget method. The sender has no way of knowing if the intended receiver is even running or on the correct port. The message sends in any case and no errors are raised. This is not an issue if you use a response of some sort to tell the sender the message was received.

  16. #16
    Hyperactive Member
    Join Date
    Feb 2017
    Posts
    457

    Re: Best way to communicate between two known vb6 apps?

    flyguille (FWIW this is what I use for simple communication between Apps).
    As dilettante points out if multiple processes using the same name won't work UNLESS you append a counter at the end of the Form.Caption for each process to make it unique.
    Consider this pseudocode as two of the functions are calls to my own routines.
    SendMessageTimeoutString is API.

    Code:
    Public Sub SendTo_AppX(strText As String)
    'Generic Routine to Send Messages to AppX
    'AppX receives these messages in Textbox "tbFromOtherApp"
    
    'Main Routine to Find
    '  1) Hidden textbox in AppX to receive All messages
    '  2) Textbox that handles receipt
    '  3) Send Info as a string to the TextBox
    
    
    'Inputs:
    '   mblnRaiseChildError
    '   - determines whether the the calling routine will also
    '     raise an error
    '   strText
    '   - Info (comma delimited) to send to AppX
    
       On Error GoTo Error_SendTo_AppX
       
       '-----------------------
    
       Dim dl As Long
       Dim hParent As Long
       Dim hMsgsTo As Long
    
       '*******
       'STARTUP
       '*******
       mblnRaiseChildError = True
    
       '*******
       'MAIN
       '*******
       'Find (Parent)
       hParent = FindSDIForm("frmX")
       If hParent <> 0 Then
       
          'Find "tbFromOtherApp" TextBox in AppX
          hMsgsTo = FindChildByWindowText(hParent, "TextBox", "tbFromOtherApp")
          If hMsgsTo <> 1 Then
          
             'Hidden Textbox Found, Send Info to AppX
             dl = SendMessageTimeoutString(hMsgsTo, WM_SETTEXT, 0, strText, SMTO_ABORTIFHUNG, 100, 0) 
    
          End If       'hMsgsTo
       End If          'hParent
    
       '*******
       'WRAPUP
       '*******
       Exit Sub
       
    Error_SendTo_AppX:
    
      With TError
         .Type = ERR_CRITICAL
         .Src = mstrModule & "SendTo_AppX"
         .Action = MsgAndLog
      End With
      
      Call DoError
     
    End Sub
    Last edited by vb6forever; Sep 21st, 2018 at 10:44 AM.

  17. #17

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by Zvoni View Post
    OK, maybe i'm just stupid, but if those two programs run in the same userspace on the same machine....
    Why not setup the program "receiver" as ActiveX-Exe-Server, and set a reference in "sender" to that Exe?
    The only thing you'd need in "receiver" is a public class-method you could call from "sender"
    the idea of a watchdog (very used in arcade machines since 70's), is to watch for if the main loop of the game is running healthy, so that way the watchdog method know it is ok, if it not ok, it RESET the cpu!.

    In this case, we have a watchdog app, it is like a guardian against fraud, like releasing the machine for unlimited usage, fraudulent usage of the task manager, or other killer app, etc.

    So, it not only must check if the app to be guarded its process exists, but also must know if it is healthy running, and not hunged. And a good way is to insert a communication stream somewhere in the loop.

    If I do, like activeX, share the same process space, and the process is killed, both apps are ruined IIRC.


    Now I am observing others problems about VB6, in modern Win10, if it is a low budget PC, the HDD sometimes turn soo saturate the DISK I/O, that the execution of background apps are like LAGGED, overall if they check for files in the hdd, it can froze a background app like by minutes, overall when loading a game. Only if it request disk I/O. Like a simple dir() inside the loop. So here I need to resolve this other problem.
    Last edited by flyguille; Sep 21st, 2018 at 01:43 PM.

  18. #18
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,668

    Re: Best way to communicate between two known vb6 apps?

    I would simply use ROT with RegisterActiveObject and GetActiveObject to directly pass COM references and call out-of-process methods through COM provided proxies.

    https://github.com/wqweto/RotServer -- this is a sample repo that implements this idea.

    Edit: Now I realise this is for a watchdog impl. Probably polling on parent process ID would be much cheaper.

    cheers,
    </wqw>

  19. #19

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    760

    Re: Best way to communicate between two known vb6 apps?

    I thinks my idea is flawed, just monitoring the window title, if the process is hung? retrieving its window name from other process is stil possible?.

  20. #20
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    2,017

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by flyguille View Post
    If I do, like activeX, share the same process space, and the process is killed, both apps are ruined IIRC.
    Huh?
    I was under the impression, that an ActiveX-EXE (!!) has its own process-space!
    http://www.vbforums.com/showthread.p...ll-activex-exe
    One System to rule them all, One IDE to find them,
    One Code to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    For health reasons i try to avoid reading unformatted Code

  21. #21
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by flyguille View Post
    Now I am observing others problems about VB6, in modern Win10, if it is a low budget PC, the HDD sometimes turn soo saturate the DISK I/O, that the execution of background apps are like LAGGED, overall if they check for files in the hdd, it can froze a background app like by minutes, overall when loading a game. Only if it request disk I/O. Like a simple dir() inside the loop. So here I need to resolve this other problem.
    Sounds like a new thread to me.

    I don't see how this is a VB6 problem though. If you must use low-spec machines and want snappy performance there are a few things you might do.

    Do not use SSD or eMMC "drives" use a real hard drive. Don't use 64-bit Windows if at all possible, it just wastes RAM and CPU cache giving nothing in return. Have an adequate amount of RAM, 4GB will be plenty. Turn off features your users will be denied access to anyway, for example indexing the drives (Indexing Service). Uninstall optional Windows components, etc.

    But as I said that's another thread, and one for General PC not here.

  22. #22
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    571

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by flyguille
    I thinks my idea is flawed, just monitoring the window title, if the process is hung? retrieving its window name from other process is stil possible?.
    You can use:
    Private Declare Function IsHungAppWindow Lib "user32" (ByVal hWnd As Long) As Long
    against window handle to check is it responding.

  23. #23
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by wqweto View Post
    I would simply use ROT...
    That may work for downlevel OSs but not since Vista. Each UIPI integrity level has its own distinct ROT in Windows now.

    UIPI also will get in the way of passing window messages between processes. You can get around that but you need to jump through hoops. The elevated process needs to be digitally signed and located in System32, needs a uiAccess="true" manifest, and must call ChangeWindowMessageFilter() or ChangeWindowMessageFilterEx() for each uMsg number that it wants to receive from lower-integrity (non-elevated) processes.

    If you really want to communicate between two processes that run at different integrity levels UDP and TCP are the most obvious choices. I'm not sure but Named Pipes and Mailslots may not be controlled by UIPI because these can already be protected through security attributes, however those can be clunkier for VB6 programmers to use.

  24. #24
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    I tested this with the server running elevated and the client as a standard user: [VB6] PipeRPC - RPC Over Named Pipes.

    It worked fine, so UIPI doesn't seem to be an issue. The only downside is that we don't have a free and widely available ActiveX control for Named Pipes, so the server code uses a Timer control to poll. An alternative might be some code supporting a worker thread that could make blocking calls and notify the interactive thread and pass it the incoming data.

    This allows bidirectional data transfers, but it is a sort of "procedure call" rather than a peer to peer communication relationship. You could also use Named Pipes more like TCP, but then both ends would need to poll for incoming data or else have worker threads.


    The only ActiveX control I have ever seen for Named Pipes was written by Unisys (or maybe Microsoft or a Microsoft Partner) and requires a software license for their ClearPath MCP Mainframe OS.

  25. #25
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    Ok, I just found this https://www.nsoftware.com/ipworks/ipc/ but the price tag is pretty punishing.

  26. #26
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,668

    Re: Best way to communicate between two known vb6 apps?

    Quote Originally Posted by dilettante View Post
    That may work for downlevel OSs but not since Vista.
    dilettante, you are the first mentioning elevation in this thread. The ROT sample is working fine on everything since Vista too, provided that the client and server application are on the same elevation level. I'm wondering if this is more of the FUD you've spreading lately? Btw, your hwnd approach has the same issues on the same OSes you deem ROT approach unusable.

    Anyway, the sample project is on github for everyone to test if it works for their cases on win10 or you are right and this is unusable on Vista and later versions. . .

    cheers,
    </wqw>

  27. #27
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,783

    Re: Best way to communicate between two known vb6 apps?

    If I misunderstood what he was asking about between this thread and his other one and neither process is elevated then you are right that a ROT-based solution will work for him. But then message passing works too. At least he has alternatives.

    The Named Pipes or TCP/IP approaches work in either case but I believe when he said "no sockets" he was referring to Winsock. Of course we also have Unix Sockets (AF_UNIX) now but I haven't seen anyone try to get that working in VB6 yet and it needs a late version of Windows anyway.

  28. #28
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,668

    Re: Best way to communicate between two known vb6 apps?

    I would personally use your memory mapped file approach from above but on the paging file, the so called Named Shared Memory.

    Never seen any mentioning of elevation barriers with memory mapped files too.

    cheers,
    </wqw>

  29. #29
    Lively Member jj2007's Avatar
    Join Date
    Dec 2015
    Posts
    122

    Re: Best way to communicate between two known vb6 apps?

    In order of preference:

    1. WM_COPYDATA is fast and simple.
    2. Using a shared DLL is another interesting option, perhaps even faster than WM_COPYDATA, see Inter-Process communication with shared segments.
    3. Memory-mapped files.
    4. Pipes
    5. Sockets

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