Solved

Passing of structure in interprocess communication(NOT STRING)

Posted on 2006-07-09
6
508 Views
Last Modified: 2008-03-17
hi to all and best of luck.  :)) I'm stuck-up here with the problem .. I could manage to pass string to another process/application using WM_COPYDATA but it takes v. long to pass a structure. Do remember that one p'mtr of structure is an object and doing that giving errors..
i wish if you can give me any code that allows passing "structure" between 2 applications
------------this is class one - sending message
Imports System.Runtime.InteropServices
Public Class clsIPC
    Inherits System.Windows.Forms.NativeWindow Implements IDisposable
    Private Const GLOBAL_IDENTITY_ONE = "GLOBAL_IDENTITY_ONE"
    Private Const GLOBAL_IDENTITY_TWO = "GLOBAL_IDENTITY_TWO"
    Private Const MESSAGE_FOR_ONE = "MESSAGE_ONE"
    Private Const MESSAGE_FOR_TWO = "MESSAGE_TWO"
    Private Const WM_COPYDATA As Integer = &H4A
#Region "API Declaration"
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure CopyData
        Public dwData As IntPtr
        Public cbData As Integer
        Public lpData As IntPtr
    End Structure
    Private Declare Auto Function SendMessage Lib "user32" _
        (ByVal hWnd As IntPtr, _
         ByVal Msg As Integer, _
         ByVal wParam As IntPtr, _
         ByRef lParam As CopyData) As Boolean
    Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" _
        (ByVal lpString As String) As IntPtr
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As IntPtr, ByVal wMsg As IntPtr, ByVal wParam As Integer, _
        ByVal lParam As Integer) As IntPtr

#End Region
#Region "process for messanging to application GLOBAL_IDENTITY_TWO"
    'get handle of globlal application named GLOBAL_IDENTITY_TWO
    Public ReadOnly Property GET_HANDLE_TWO() As IntPtr
        Get
            Return FindWindow(vbNullString, GLOBAL_IDENTITY_TWO)
        End Get
    End Property
    Structure PT
        Dim x As Object
        Dim y As Char
        Dim xy As String
    End Structure
    Dim MyVariable As New PT
    Public Function sendMessageToTwo()
        Dim data As CopyData
        Dim message As String = "this is to be sent"
        Dim hwndTarget As IntPtr
        Dim MessageId As IntPtr
        hwndTarget = Me.GET_HANDLE_TWO
        MessageId = ONE_TO_TWO_MESSAGEID()
        MyVariable.x = message
        MyVariable.y = "c"
        MyVariable.xy = "String is here"
        System.GC.KeepAlive(MyVariable)
        data.lpData = Marshal.AllocHGlobal(Marshal.SizeOf(MyVariable))
        data.cbData = Marshal.SizeOf(MyVariable)
        Dim MyPointer As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(MyVariable))
        Marshal.StructureToPtr(MyVariable, data.lpData, True)
        SendMessage(hwndTarget, WM_COPYDATA, Me.Handle, data)
        MsgBox("WM_COPYDATA")
        Exit Function
        If Not System.IntPtr.Zero.Equals(hwndTarget) Then
            Call PostMessage(hwndTarget, MessageId, 0, 0)
            MsgBox("Message sent")
        Else
            MsgBox("Unable to send Message ! probably GLOBAL_IDENTITY_TWO Not found")
        End If
    End Function
    Public ReadOnly Property ONE_TO_TWO_MESSAGEID() As IntPtr
        Get
            Static objONE_TO_TWO_MESSAGEID As IntPtr
            If IntPtr.Zero.Equals(ONE_TO_TWO_MESSAGEID) Then
                objONE_TO_TWO_MESSAGEID = RegisterWindowMessage(MESSAGE_FOR_TWO)
            End If
            Return objONE_TO_TWO_MESSAGEID
        End Get
    End Property
#End Region
Region "dispose method and new()/constructor"

    Public Sub Dispose() Implements IDisposable.Dispose
        If Not Me.Handle.Equals(IntPtr.Zero) Then
            Me.ReleaseHandle()
        End If
    End Sub
    Public Sub New()
        Dim Params As CreateParams = New CreateParams
        Params.Caption = GLOBAL_IDENTITY_ONE
        Me.CreateHandle(Params)
    End Sub
#End Region
End Class
--------------------------------------xxxxxxxxxxxxxxxxxxxxxxxxxx----------------------------------

----this is class two-listening to message-----------
Imports System.Runtime.InteropServices
Public Class clsIPC
    Inherits System.Windows.Forms.NativeWindow Implements IDisposable
    Private Const GLOBAL_IDENTITY_ONE = "GLOBAL_IDENTITY_ONE"
    Private Const GLOBAL_IDENTITY_TWO = "GLOBAL_IDENTITY_TWO"
    Private Const MESSAGE_FOR_ONE = "MESSAGE_ONE"
    Private Const MESSAGE_FOR_TWO = "MESSAGE_TWO"
    Private Const WM_COPYDATA As Integer = &H4A
    Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" _
        (ByVal lpString As String) As IntPtr
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As IntPtr, ByVal wParam As Integer,ByVal lParam As Integer) As IntPtr
    <StructLayout(LayoutKind.Sequential)> _
   Private Structure CopyData
        Public dwData As IntPtr
        Public cbData As Integer
        Public lpData As IntPtr
    End Structure
    Structure PT
        Dim x As Object  '<<<----- whenever i use object as member of a structure i get an exception An unhandled exception
                                 'of type 'System.ExecutionEngineException' occurred in mscorlib.dll if i use string as a
                                 'member  there is no error
        Dim y As Integer
        Dim xy As Integer
    End Structure

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Select Case m.Msg
            Case WM_COPYDATA
                Dim data As CopyData
                Dim message As String
                Dim MyPoint As New PT
                data = CType(m.GetLParam(GetType(CopyData)), CopyData)
                MyPoint = Marshal.PtrToStructure(data.lpData, GetType(PT))   <<<---- @ this point i'm getting the error [debug]
                'MyPoint = Marshal.PtrToStructure(CType(m.GetLParam(GetType(CopyData)), CopyData).lpData, GetType(PT))
                MsgBox(CType(MyPoint.x, String))

              Case TWO_TO_ONE_MESSAGEID().ToInt32
                MessageBox.Show("GOT A MESSAGE FROM ONE--- CALLING METHOD A", "VBNETMessaging")
                Call A()
        End Select
        MyBase.WndProc(m)
    End Sub
    Private Sub A()
        MsgBox("Message from Method A")
    End Sub
    Public ReadOnly Property TWO_TO_ONE_MESSAGEID() As IntPtr
        Get
            Static objTWO_TO_ONE_MESSAGEID As IntPtr

            If IntPtr.Zero.Equals(objTWO_TO_ONE_MESSAGEID) Then
                objTWO_TO_ONE_MESSAGEID = RegisterWindowMessage(MESSAGE_FOR_TWO)
            End If
            Return objTWO_TO_ONE_MESSAGEID
        End Get
    End Property
#Region "dispose method and new()/constructor"
    Public Sub Dispose() Implements IDisposable.Dispose
        If Not Me.Handle.Equals(IntPtr.Zero) Then
            Me.ReleaseHandle()
        End If
    End Sub
    Public Sub New()
        Dim Params As CreateParams = New CreateParams
        Params.Caption = GLOBAL_IDENTITY_TWO
        Me.CreateHandle(Params)
    End Sub
#End Region
End Class
--------------------------------------xxxxxxxxxxxxxxxxxxxxxxxxxx----------------------------------
0
Comment
Question by:theGhost_k8
6 Comments
 
LVL 48

Accepted Solution

by:
AlexFM earned 250 total points
ID: 17070814
Marshal functions must know how to marshal every structure member. When structure contains primitive types or strings, Marshal knows what to do with them. Object cannot be marshalled. You need to find another way or use pure managed solutions like remoting.
Generally, Marshal class must know how to convert structure to array of bytes. For Object type there is no such way.
0
 
LVL 21

Author Comment

by:theGhost_k8
ID: 17070951
I'd like if you post or give reference to perticular topic . -ve thoughts are not right....
instead better if you sugges "do it like this example-code".. not just  "you cant do blah-blah-blah"...
0
 
LVL 8

Expert Comment

by:plq
ID: 17071390
Alex is right as far as I am concerned. Can't is a valid answer in EE. In general I can't imagine wanting to send a class structure to another application - you should communicate using standards

I am not going to read all your code, but you could look at serialising you class into a memory stream and then move that to a string or byte array to pass to the remote function. To support serialisation can be a big job with some classes, but yours looks easy enough. Otherwise you could move your class to a DLL that is referenced by the caller and by the callee.

Some other alternatives.

- write your string to a registry setting (ugh)
- write your string to a temp file or xml file (yuk)
- write a DLL which uses memory mapped files and pass your string through the MMF (a lot of work)
- Just compress your structures into a single string using separators like chr(1), chr(2), and then split them out again at the other end

Remoting (alexfms suggestion) is probably better than all of these, although I'm quite lazy so would go for the chr(n) separated string above.

hth
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now