3

開発中の VB 2010 アプリから、文字列がバイト配列に変換されることを期待する既存のライブラリに構造化データを送信しようとしています。データをバイト配列として送信するのに問題があります。バイトに変換する必要があるプレーン文字列を、作成したテスト プログラムに送信できます。

これが2つのアプリです。まず、リスナー プロセス:

Imports System.Runtime.InteropServices
Public Class frmTest

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If m.Msg = frmTest.WM_COPYDATA Then
        Dim data As CopyData
        Dim message As String

        ' get the data...
        data = CType(m.GetLParam(GetType(CopyData)), CopyData)

        message = data.lpData
        ' add the message
        txtTest.Text = message

        ' let them know we processed the message...
        m.Result = New IntPtr(1)
    Else
        MyBase.WndProc(m)
    End If
End Sub

Private Function UnicodeBytesToString(ByVal bytes() As Byte) As String

    Return System.Text.Encoding.Unicode.GetString(bytes)
End Function

Private Const WM_COPYDATA As Integer = &H4A

<StructLayout(LayoutKind.Sequential)> _
Private Structure CopyData
    Public dwData As IntPtr
    Public cbData As Integer
    Public lpData As String
End Structure
End Class

次に、データを送信するプロセス:

Imports System.Runtime.InteropServices
Imports System.Collections.Generic

Public Class frmMain

<StructLayout(LayoutKind.Sequential)> _
Private Structure CopyData
    Public dwData As IntPtr
    Public cbData As Integer
    Public lpData As String
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 Auto Function FindWindow Lib "user32" _
 (ByVal lpClassName As String, _
  ByVal lpWindowName As String) As IntPtr

Private Const WM_COPYDATA As Integer = &H4A

Private Sub cmdSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSend.Click


    Dim ClientWindow As IntPtr
    Dim a() As System.Diagnostics.Process = System.Diagnostics.Process.GetProcesses

    For Each p In a
        Console.WriteLine(p.ProcessName)
        If p.ProcessName = "Listener" Then
            ClientWindow = p.MainWindowHandle
            Exit For
        End If
    Next


    ' make sure we found an active client window
    If Not ClientWindow.Equals(IntPtr.Zero) Then

        ' if there is text to send
        If txtText.Text.Length > 0 Then
            Dim message As String = txtText.Text
            Dim data As CopyData

            ' set up the data...
            data.lpData = message
            data.cbData = message.Length * Marshal.SystemDefaultCharSize

            ' send the data
            frmMain.SendMessage(ClientWindow, frmMain.WM_COPYDATA, Me.Handle, data)

        End If
    Else
        MsgBox("Could Not Find Active Client Window.")
    End If
End Sub

Private Function UnicodeStringToBytes(
ByVal str As String) As Byte()

    Return System.Text.Encoding.Unicode.GetBytes(str)
End Function

End Class

これはすべて機能しますが、両方で「Public lpData As String」を「Public lpData As Byte()」に変更し、送信者プロセスで「data.lpData = message」を「data.lpData = UnicodeStringToBytes(message)」に修正すると、 「message = data.lpData」から「message = UnicodeBytesToString(data.lpData)」までのリスナー プロセスがクラッシュします。

バイト配列としてエンコードされた文字列を送信者からリスナーに送信して、リスナーが文字列にデコードできるようにするにはどうすればよいですか?

文字列を文字列として送信する方が簡単だと思いますが、既存のライブラリではそれをバイト配列として必要とするため、何が起こっているかを確認できるこのテストリスナーに対して送信者を機能させようとしています。

前もって感謝します !

4

1 に答える 1

2

構造体の可変長配列は常に面倒です。

両方のアプリケーションでlpDataasを宣言します。IntPtr

次に、送信アプリで:

' set up the data...
Dim string_bytes = UnicodeStringToBytes(message)

Dim pinned = GCHandle.Alloc(string_bytes, GCHandleType.Pinned)
Try
    data.dwData = New IntPtr(message.Length)
    data.cbData = string_bytes.Length
    data.lpData = pinned.AddrOfPinnedObject()

    ' send the data
    frmMain.SendMessage(ClientWindow, frmMain.WM_COPYDATA, Me.Handle, data)
Finally
    If pinned.IsAllocated Then pinned.Free()
End Try

受信アプリで:

' get the data...
data = CType(m.GetLParam(GetType(CopyData)), CopyData)

Dim message(0 To data.cbData - 1) As Byte
Marshal.Copy(data.lpData, message, 0, data.cbData)

' add the message
txtTest.Text = UnicodeBytesToString(message)
于 2013-03-30T10:37:15.097 に答える