Introduction
Sometimes, we need to communicate with other applications, such as send and receive strings. In VB6, we can easily use the SendMessage function to send a wm_datacopy message, because we can define lparam as Any. But in VB.NET, when we declare the Win32 API function SendMessage, it does not accept "Any" as data type, which means we can only send 32 bit integer parameters by using the SendMessage function in .NET.
Microsoft introduced a way to connect different applications by using Remoting; it's suitable for mass communication, but if we just want to send some simple messages, it will use more resources to develop and run it on the computer.
In this article, I will introduce a simple way to send strings to another application running in the same computer, by using the SendMessage function; the concept is:
Concept
For security reasons, there's no way to directly access another process' memory in VB.NET, so if we want to send a string to another application, what we can do is encode the string to a byte array, and send each member in the byte array sequentially; at the end of the sending session, we need to send a terminator byte.
At the receiving end, we put every received byte into a byte array until the terminator byte is received. Then, we raise en event to indicate that a new string was received successful.
Using the code
Here is the component to send and build the string:
Imports System.Text
Public Class BuildString
Private Declare Function PostMessage Lib "user32.dll" _
Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As _
Integer, ByVal wParam As Integer, ByVal lParam As Integer) _
As Integer
Public Event StringOK(ByVal Result As String)
Private hwnd As Integer = 0
Private wMsg As Integer = 0
Private wParam As Integer = 0
Private lParam As String = ""
Private tempA(-1) As Byte
Private enc As Encoding = Encoding.UTF8
Public Property Encode() As Encoding
Get
Return enc
End Get
Set(ByVal value As Encoding)
enc = value
End Set
End Property
Public Sub BuildString(ByVal b As IntPtr)
If b <> 0 Then
Dim tempB(tempA.Length) As Byte
tempA.CopyTo(tempB, 0)
tempB(tempA.Length) = b
ReDim tempA(tempB.Length - 1)
tempB.CopyTo(tempA, 0)
Else
Dim s As String
If enc Is Encoding.UTF8 Then
s = Encoding.UTF8.GetString(tempA)
ElseIf enc Is Encoding.Unicode Then
s = Encoding.Unicode.GetString(tempA)
ElseIf enc Is Encoding.ASCII Then
s = Encoding.ASCII.GetString(tempA)
Else
s = Encoding.Default.GetString(tempA)
End If
RaiseEvent StringOK(s)
ReDim tempA(-1)
End If
End Sub
Public Sub PostString(ByVal hwnd As Integer, ByVal wMsg _
As Integer, ByVal wParam As Integer, ByVal lParam As String)
Me.hwnd = hwnd
Me.wMsg = wMsg
Me.wParam = wParam
Me.lParam = lParam
Dim t As Threading.Thread
t = New Threading.Thread(AddressOf SendString)
t.Start()
End Sub
Private Sub SendString()
Dim ba() As Byte
If enc Is Encoding.UTF8 Then
ba = Encoding.UTF8.GetBytes(lParam)
ElseIf enc Is Encoding.Unicode Then
ba = Encoding.Unicode.GetBytes(lParam)
ElseIf enc Is Encoding.ASCII Then
ba = Encoding.ASCII.GetBytes(lParam)
Else
ba = Encoding.Default.GetBytes(lParam)
End If
Dim i As Integer
For i = 0 To ba.Length - 1
PostMessage(hwnd, wMsg, wParam, ba(i))
Next
PostMessage(hwnd, wMsg, wParam, 0)
End Sub
End Class
To use the component:
The sending end
Private WithEvents BS As New BuildString
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim hwnd As Integer = FindWindow(vbNullString, "Receive")
If hwnd <> 0 And TextBox1.Text <> "" Then
BS.PostString(hwnd, &H400, 0, TextBox1.Text)
End If
End Sub
The receiving end
Private WithEvents BS As New BuildString
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case &H400
BS.BuildString(m.LParam)
Case Else
MyBase.WndProc(m)
End Select
End Sub
Private Sub SB_StringOK(ByVal Result As String) Handles BS.StringOK
TextBox1.AppendText(Result & vbNewLine)
End Sub
Points of interest
If you are searching for a simple way to communicate with other applications, this article is for you.
History