我正在尝试将我正在开发的VB 2010应用程序中的结构化数据发送到现有库,该库希望将字符串转换为字节数组。我在将数据作为字节数组发送时遇到问题 - 我可以将应该转换为字节的普通字符串发送到我编写的测试程序。
这是两个应用程序。首先是听众过程:
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)'在侦听器进程中崩溃。
如何将编码为字节数组的字符串从发送方发送到侦听器,以便侦听器可以将其解码回字符串?
我意识到将字符串作为字符串发送会更容易,但是现有的库需要它作为字节数组,所以我试图让我的发送者针对这个测试监听器工作,我可以看到发生了什么。
提前致谢!
答案 0 :(得分:2)
结构中的可变长度数组总是很痛苦。
在两个应用程序中将lpData
声明为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)