How do I share specific pieces of information between related apps or multiple instances of one app?

Robert Gustafson 606 Reputation points
2021-10-19T02:01:51.73+00:00

WHAT I HAVE:
Visual Basic 2019, WinForms, .NET Framework 4.6-4.8

MY ISSUE:
I want to structure a desktop app so that it can share specific information with related desktop apps--or with other instances of itself--when they're running at the same time. Each app or app instance would have its own instance of an object of some type, say MyClass,--which the relate apps or other app instances could look at to compare with their own corresponding MyClass instances.

For instance, an application that can be multiply-instanced might want to have, say, a file-name String that other instances of itself could see, so that the app can make sure that simultaneously-running instances aren't using and modifying the same file, the same document, the same picture, the same database, or the same whatever at the same time. Ideally, the ability to share and compare info should be a simple object-oriented thing that doesn't require me to explicitly set up a common file or common database simply for a relatively small amount of "state-info" for each app or app instance. (That seems like overkill!)

Give me some advice ASAP, please provide any code in VB.NET, and keep it as simple as possible, as I don't want to devote a large part of app development simply for the sharing and comparing of a relatively limited bit of data between a program and other programs or instances of itself.

Developer technologies | Windows Forms
Developer technologies | VB
{count} votes

12 answers

Sort by: Most helpful
  1. RLWA32 49,666 Reputation points
    2021-10-21T02:36:30.057+00:00

    It sounds to me like you want to create shared memory. You can use memory-mapped-files to accomplish this.

    2 people found this answer helpful.
    0 comments No comments

  2. Castorix31 90,686 Reputation points
    2021-10-21T06:57:43.187+00:00

    You can type on Google :

    Interprocess Communication .net

    and you will find samples using the various IPC methods, like :

    VB.NET IPC InterProcess Communication
    Simple Inter-Process Communication In VB.Net
    How to: Use Anonymous Pipes for Local Interprocess Communication
    etc...

    1 person found this answer helpful.
    0 comments No comments

  3. Castorix31 90,686 Reputation points
    2021-10-28T14:30:16.767+00:00

    A small test with the simplest method, WM_COPYDATA
    between 3 instances of the program, to be improved... :

    144576-wm-copydata.gif

    Imports System.Runtime.InteropServices  
      
    Public Class Form1  
      
        Public Const WM_COPYDATA As Integer = &H4A  
      
        <StructLayout(LayoutKind.Sequential)>  
        Public Structure COPYDATASTRUCT  
            Public dwData As IntPtr  
            Public cbData As Integer  
            Public lpData As IntPtr  
        End Structure  
      
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>  
        Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByRef lParam As COPYDATASTRUCT) As Integer  
        End Function  
      
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>  
        Public Structure DATASTRUCT  
            Public hWnd As IntPtr  
            Public nPID As Integer  
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)>  
            Public sMessage As String  
        End Structure  
      
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
            Dim sProcessName As String = System.AppDomain.CurrentDomain.FriendlyName  
            Dim nWindows As Integer = 0  
            Dim procs As Process() = Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(sProcessName))  
            If procs.Length > 0 Then  
                For Each proc As Process In procs  
                    If (proc.MainWindowHandle <> IntPtr.Zero And proc.MainWindowHandle <> Me.Handle) Then  
                        nWindows += 1  
                        Dim data As DATASTRUCT  
                        data.hWnd = proc.MainWindowHandle  
                        data.nPID = proc.Id  
                        data.sMessage = "This is a test"  
                        Dim nSize As Integer = Marshal.SizeOf(data)  
                        Dim pData As IntPtr = Marshal.AllocHGlobal(nSize)  
                        Marshal.StructureToPtr(data, pData, True)  
                        Dim cds As New COPYDATASTRUCT()  
                        cds.cbData = nSize  
                        cds.lpData = pData  
                        Dim nRet As Integer = SendMessage(proc.MainWindowHandle, WM_COPYDATA, CInt(Me.Handle), cds)  
                        If (nRet <> 1) Then  
                            MessageBox.Show(String.Format("Error sending WM_COPYDATA) : 0x{0:X}", nRet), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)  
                        End If  
                        Marshal.FreeHGlobal(pData)  
                    End If  
                Next  
            End If  
            If (nWindows > 0) Then  
                MessageBox.Show(String.Format("WM_COPYDATA sent to {0} windows", nWindows.ToString()), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)  
            Else  
                MessageBox.Show("WM_COPYDATA not sent", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)  
            End If  
        End Sub  
      
        Friend WithEvents Button1 As Button  
        Friend WithEvents RichTextBox1 As RichTextBox  
      
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load  
            Me.Button1 = New System.Windows.Forms.Button()  
            Me.Button1.Location = New System.Drawing.Point(120, 16)  
            Me.Button1.Name = "Button1"  
            Me.Button1.Size = New System.Drawing.Size(80, 30)  
            Me.Button1.Text = "Button1"  
            Me.Button1.UseVisualStyleBackColor = True  
      
            Me.RichTextBox1 = New System.Windows.Forms.RichTextBox()  
            Me.RichTextBox1.Location = New System.Drawing.Point(60, 60)  
            Me.RichTextBox1.Name = "RichTextBox1"  
            Me.RichTextBox1.Size = New System.Drawing.Size(200, 120)  
            Me.RichTextBox1.Text = ""  
      
            Me.ClientSize = New System.Drawing.Size(320, 200)  
            Me.Controls.Add(Me.Button1)  
            Me.Controls.Add(Me.RichTextBox1)  
            CenterToScreen()  
        End Sub  
      
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)  
            If (m.Msg = WM_COPYDATA) Then  
                Dim pCDS As COPYDATASTRUCT = CType(m.GetLParam(GetType(COPYDATASTRUCT)), COPYDATASTRUCT)  
                If (pCDS.cbData = Marshal.SizeOf(GetType(DATASTRUCT))) Then  
                    Dim data As DATASTRUCT = CType(Marshal.PtrToStructure(pCDS.lpData, GetType(DATASTRUCT)), DATASTRUCT)  
                    Dim hWndFrom As IntPtr = data.hWnd  
                    Dim nPIDFrom As Integer = data.nPID  
                    Dim sMessage As String = data.sMessage  
                    Dim sText = String.Format("From window : 0x{0:X} (PID={1}){2}Message : {3}{2}", hWndFrom, nPIDFrom.ToString(), Environment.NewLine, sMessage)  
                    RichTextBox1.Text += sText  
                    m.Result = CType(1, IntPtr)  
                    Return  
                End If  
            End If  
            MyBase.WndProc(m)  
        End Sub  
    End Class  
    
    1 person found this answer helpful.
    0 comments No comments

  4. Robert Gustafson 606 Reputation points
    2021-10-20T03:31:23.57+00:00

    You apparently didn't carefully read the full description of my issue. I'm not talking about sharing data within a single run-time instance of a single project or a single solution. I'm talking about a situation where 2 or more apps' .exe's are executing simultaneously, or where 2 or more instances of a single app's .exe are executing simultaneously.

    This is principally about Windows' multitasking nature, and finding a way to allow different programs, or different instances of a single program, to (economically) communicate info with each other when they're running at the same time. I want to overcome the tendency of programs or program instances that are executing "in parallel" to act like fully separate islands with respect to each other. If program X and program Y--which are not necessarily in the same solution--are active in Windows simultaneously, then what's the most convenient way for X and Y to share and compare some of each other's info? Also, if multiple "run-time 'copies'"--instance--of program X are active at the same time, how does one instance of X share and compare info with the other instances of X (arguably a more problematic concern)?

    Does this explain my situation better?

    0 comments No comments

  5. Robert Gustafson 606 Reputation points
    2021-10-27T11:32:33.303+00:00

    The examples seem (moreorless) straightforward. The problem is, they're all 1-way communication between 2 distinct processes--1 a server, the other a client. What if I need the communication to be 2-way? Moreover, what if--as I previously talked about--the processes are alternate instances of a single program? In either case, an app would have to be able to be server AND client (simultaneously or alternately). I need a better example set.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.