問題は、2 つのアプリケーション間でデータを適切にマーシャリングしていないことです。1 つのアプリケーションでメモリを割り当て、そのメモリへのポインターを 2 番目のアプリケーションに渡します。しかし、アプリケーションにはプライベート メモリ空間があり、互いのメモリを読み取ることができないため、そのポインタは 2 番目のアプリケーションには役に立ちません。
そのアプリケーションのメモリ空間で何を指しているかによって、アクセス違反を引き起こしているか、正しく動作していない可能性があります。
AllocHGlobal
とFreeHGlobal
関数の命名に混乱しているかもしれません。第一印象に反して、実際にはグローバルメモリの割り当てと解放を行いません。少なくとも、マシン上で実行されているすべてのプロセスがグローバルにアクセスできるメモリではありません。この名前は、Windows のHGLOBAL
データ型に由来します。16 ビット Windows の時代には、すべてのアプリケーションが共通のメモリ空間を共有し、互いのメモリを読み取ることができたので、まさにこれを意味していました。しかし、最近の 32 ビット Windows ではそうではありません。名前は下位互換性のために残されています。今日では事実上同じことHGLOBAL
を意味します。HLOCAL
詳細については、MSDN を参照してください。. しかし、それはほとんど好奇心です。コードを正しく機能させるために、すべてを知って理解する必要はありません。
要点はAllocHGlobal
、プロセスのデフォルト ヒープからメモリを割り当て、そのプロセスだけが読み取ることができるということです。したがって、プロセス間でメモリをマーシャリングして、メッセージを受信する他のプロセスからアクセスできるようにする必要があります。もちろん、これを手動で行うこともオプションです。しかし、あまり良いものではありません。正しく理解するのは難しく、ほとんど意味がありません。Tim のコメントが示唆しているように、より簡単なオプションは、マーシャリングを行うWM_COPYDATA
messageを使用することです。このメッセージを使用すると、共有するデータがCOPYDATASTRUCT
構造体にパッケージ化されます。
カスタムRF_TESTMESSAGE
ウィンドウ メッセージをWM_COPYDATA
. 必要な構造定義を含むサンプル コードは、pinvoke の Web サイトで入手できます。
このようなもの (警告 — テストもコンパイルもされていません):
Private Const WM_COPYDATA As Integer = &H004A
<StructLayout(LayoutKind.Sequential)> _
Public Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cdData As Integer
Public lpData As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure MyData
Public M As String
Public I As Integer
End Structure
Public Function SendTest()
' Create your data structure, MyData, and fill it.
Dim data As New MyData
data.M = "QWERTY"
data.I = 15
Dim pData As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(data))
Marshal.StructureToPtr(data, pData, False)
' Create the COPYDATASTRUCT you'll use to shuttle the data.
Dim copy As New COPYDATASTRUCT
copy.dwData = IntPtr.Zero
copy.lpData = pData
copy.cbData = Marshal.SizeOf(data)
Dim pCopy As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(copy))
Marshal.StructureToPtr(copy, pCopy, False)
' Send the message to the other application.
SendMessage(New IntPtr(11111), WM_COPYDATA, IntPtr.Zero, pCopy)
' Free the memory we allocated
' (This works because SendMessage is synchronous, and does not
' return until the other application has finished processing
' the data that you have sent it. That also means that the
' other application should not and cannot free the memory.
' If it needs it after processing the message, it needs to
' make a local copy.)
Marshal.FreeHGlobal(pCopy)
Marshal.FreeHGlobal(pData)
End Function
を使用して簡単なルートに行かずWM_COPYDATA
、代わりに自分でデータをマーシャリングすることに決めた場合は、RegisterWindowMessage
関数を呼び出す必要があります (まだコードでそうしていない場合は見えません)。ウィンドウ メッセージは一意です。