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