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. Robert Gustafson 606 Reputation points
    2021-10-27T21:19:16.107+00:00

    Can you give me a simple VB.NET example? Specifically, one instance of a program passing info back and forth with another instance of the same program? This is uncharted territory for me.

    0 comments No comments

  2. Robert Gustafson 606 Reputation points
    2021-11-03T23:06:20.42+00:00

    Do you have a simpler example?! I mean, do I have to rely on SendMessage API and subclassing? Other examples I was referred to didn't have these things, and I prefer not to rely on Win32 API unless it's absolutely neccessary. I mean, if I simply want 1 instance of my application to be able to compare its own instance of an object of a certain type, say MyType, with the same-type object instances in other instances of the same app, can't I do it without the "unmanaged" stuff? I don't want to send/receive "messages" between instances of my program (that's not specific enough info), I want to send/receive a piece of data--say, a String or a Date or info of a user-defined class/structure type. Remember, keep it simple.

    A possible pseduo-code example follows--with function GetInfoFromOtherInstances obtaining InfoType information from all other instances of the same program:

    '   possible definition for InfoType object
    Public Class InfoType '(scope would be Public or Friend)
       Public Property FileName As String '(sample member)
       Public Property CatalogName As String '(sample member)
       *(other members)*
    End Class
    
    
    
    '   compare information for this app instance with that of others
    Friend Class HandleInfo '(scope would be Public or Friend)    
       Friend Sub DetermineInfo()
          '   define InfoType information for this specific app instance
          Dim InfoForThisInstance As InfoType = *some expression or function*
          '   get array of InfoType data from other instances of same app
          Dim InfoForOtherInstances() As InfoType = GetInfoFromOtherInstances()
          '   check to see if this instance is relying on same info as another
          If InfoForOtherInstances.Contains(InfoForThisInstance) Then
             *code to execute if same info is used by another instance*
           Else
             *code to execute if this info is unique* 
          End If
       End Sub
    
       Private Function GetInfoFromOtherInstances() As InfoType
          *insert neccessary code here*
       End Function
    End Class
    

    Your job is to tell me what the (VB.NET) code for the GetInfoFromOtherInstances function (and any other supporting code) would be like.


  3. Robert Gustafson 606 Reputation points
    2021-11-04T04:23:49.423+00:00

    I need an example of how memory-mapped files can be used to shared corresponding data-object info between a given instance of a program and other parallel instances of it. (I haven't seen any multiple-instances-of-1-app examples of MMFs.) I imagine that the GetInfoFromOtherInstances function might, say, rely on a memory-mapped Dictionary with some "instance identifier" of some kind as the key, and the respective InfoType information as the value.

    BTW, the means of identifying each instance--and whether or not it's the "current" instance--mustn't depend on something like the caption of the app's main form, because the app might change that during at run-time. I need to rely on a key, whether it's derived from .NET or Win32 app-associated info or it's self-set by me, that is intrinsically instance-unique!

    PS. I'm sorry if it seems like I'm asking to be led by hand, but I've got other stuff to deal with with my app, so I don't want to spend a lot of time experimenting with something I've never used before.

    PPS. I feel like we are getting closer to something I can use; the only thing missing is specificity. BTW, keep examples in VB.NET.


  4. Castorix31 90,686 Reputation points
    2021-11-06T15:28:33.957+00:00

    Another simple sample with MMF to share a structure between several instances of an app :

    146940-vb-mmf.gif

    Imports System.IO  
    Imports System.IO.MemoryMappedFiles  
    Imports System.Runtime.InteropServices  
      
    Public Class Form1  
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>  
        Public Structure DATASTRUCT  
            Public nValue As Integer  
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)>  
            Public sMessage As String  
        End Structure    
      
        Dim mmf As MemoryMappedFile = Nothing  
      
        Friend WithEvents Button1 As Button  
        Friend WithEvents Button2 As Button  
        Friend WithEvents TextBox2 As TextBox  
        Friend WithEvents TextBox3 As TextBox  
        Friend WithEvents TextBox4 As TextBox  
        Friend WithEvents NumericUpDown1 As NumericUpDown  
      
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
            Dim nSize As Integer = Marshal.SizeOf(GetType(DATASTRUCT))  
            mmf = MemoryMappedFile.CreateOrOpen("testmap", nSize)  
            Using accessor = mmf.CreateViewAccessor(0, nSize)  
                Dim data As DATASTRUCT  
                data.nValue = Convert.ToInt32(Math.Round(NumericUpDown1.Value, 0))  
                data.sMessage = TextBox2.Text  
                Dim pDATA As IntPtr = Marshal.AllocHGlobal(nSize)  
                Dim byteArray As Byte() = New Byte(nSize - 1) {}  
                Marshal.StructureToPtr(data, pDATA, False)  
                Marshal.Copy(pDATA, byteArray, 0, nSize)  
                accessor.WriteArray(Of Byte)(0, byteArray, 0, byteArray.Length)  
                Marshal.FreeHGlobal(pDATA)  
            End Using  
        End Sub  
      
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click  
            Dim nSize As Integer = Marshal.SizeOf(GetType(DATASTRUCT))  
            Try  
                Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")  
                    Using accessor = mmf.CreateViewAccessor(0, nSize)  
                        Dim byteArray As Byte() = New Byte(nSize - 1) {}  
                        accessor.ReadArray(Of Byte)(0, byteArray, 0, byteArray.Length)  
                        Dim pDATA As IntPtr = Marshal.AllocHGlobal(nSize)  
                        Marshal.Copy(byteArray, 0, pDATA, byteArray.Length)  
                        Dim data As DATASTRUCT = CType(Marshal.PtrToStructure(pDATA, GetType(DATASTRUCT)), DATASTRUCT)  
                        Marshal.FreeHGlobal(pDATA)  
                        TextBox3.Text = data.nValue.ToString()  
                        TextBox4.Text = data.sMessage  
                    End Using  
                End Using  
            Catch ex As Exception  
                MessageBox.Show(String.Format("Error : {0}", ex.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)  
            End Try  
        End Sub  
      
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load  
            Button1 = New Button()  
            Button2 = New Button()  
            NumericUpDown1 = New NumericUpDown()  
            TextBox2 = New TextBox()  
            TextBox3 = New TextBox()  
            TextBox4 = New TextBox()  
      
            Button1.Location = New System.Drawing.Point(60, 35)  
            Button1.Name = "Button1"  
            Button1.Size = New System.Drawing.Size(100, 23)  
            Button1.TabIndex = 0  
            Button1.Text = "Write"  
            Button1.UseVisualStyleBackColor = True  
      
            Button2.Location = New System.Drawing.Point(256, 35)  
            Button2.Name = "Button2"  
            Button2.Size = New System.Drawing.Size(100, 23)  
            Button2.TabIndex = 1  
            Button2.Text = "Read"  
            Button2.UseVisualStyleBackColor = True  
      
            NumericUpDown1.Location = New System.Drawing.Point(60, 98)  
            NumericUpDown1.Name = "NumericUpDown1"  
            NumericUpDown1.Size = New System.Drawing.Size(100, 20)  
            NumericUpDown1.TabIndex = 2  
      
            TextBox2.Location = New System.Drawing.Point(60, 139)  
            TextBox2.Name = "TextBox2"  
            TextBox2.Size = New System.Drawing.Size(100, 20)  
            TextBox2.TabIndex = 3  
      
            TextBox3.Location = New System.Drawing.Point(256, 98)  
            TextBox3.Name = "TextBox3"  
            TextBox3.Size = New System.Drawing.Size(100, 20)  
            TextBox3.TabIndex = 4  
      
            TextBox4.Location = New System.Drawing.Point(256, 139)  
            TextBox4.Name = "TextBox4"  
            TextBox4.Size = New System.Drawing.Size(100, 20)  
            TextBox4.TabIndex = 5  
      
            ClientSize = New System.Drawing.Size(426, 205)  
            Controls.Add(NumericUpDown1)  
            Controls.Add(TextBox4)  
            Controls.Add(TextBox3)  
            Controls.Add(TextBox2)  
            Controls.Add(Button2)  
            Controls.Add(Button1)  
            Name = "Form1"  
            Text = "Form1"  
      
            CenterToScreen()  
        End Sub  
    End Class  
      
    

  5. Robert Gustafson 606 Reputation points
    2021-11-06T23:20:46.307+00:00

    How do I identify each instance of the app? Assume I'm working with an undetermined # of app instances, and I'm using memory-mapping to keep track of the DATASTRUCT info for all instances--say, by storing some kind of DATASTRUCT grouping, like a Dictionary with an app-instance "ID's" as the Keys and DATASTRUCT app-instance data as the Values: I need to know how to create a key to indicate the current instance, so I can tell if the data for the current instance is already in the map or needs to be added. I would also need to be able to look through the list to see if a foreign instance has the same data. (Your sample seems to be based on getting a single DATASTRUCT value from an unidentified instance of the app.)

    Also, do I need to use the "unmanaged type" stuff in the field declarations for DATASTRUCT? Wouldn't marking the fields in the DATASTRUCT type as "<Serializable()>" be enough? Finally, it would have been nice if some comments were present, so I could more easily figure out what the code is doing--especially if I have to improvise something myself.

    All in all, I need to memory-map not a single instance of a data type, but a group thereof--1 instance of a data type for each instance of the app. And I need to be able to tell the app instances apart.


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.