Send strings to another application by using Windows messages
A way to send strings to another application by using Windows messages instead of Remoting.
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
'build temp array
Dim tempB(tempA.Length) As Byte
tempA.CopyTo(tempB, 0)
tempB(tempA.Length) = b
ReDim tempA(tempB.Length - 1)
tempB.CopyTo(tempA, 0)
Else
'decode byte array to string
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
'send out result string via event
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
'create a new thread to post window message
Dim t As Threading.Thread
t = New Threading.Thread(AddressOf SendString)
t.Start()
End Sub
Private Sub SendString()
'create byte array
Dim ba() As Byte
'encode string to byte array
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
'start post message
PostMessage(hwnd, wMsg, wParam, ba(i))
Next
'post a terminator message to destination window
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
' "Receive" parameter is the caption of destination window
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
- 02 Aug 2007, fourth version with a new concept; rewrote the whole program.
- 01 Aug 2007, third version with the free memory method and more comments.
- 31 July 2007, second version with a better method to copy strings and also a structure.
- 25 July 2007, the first release.
(The versions below can not be used for inter-process communication.)