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.
How do I share specific pieces of information between related apps or multiple instances of one app?
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
12 answers
Sort by: Most helpful
-
-
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.
-
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.
-
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 :
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
-
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.