Sending strings between win32 applications with python (WM_COPYDATA)
While developing a small application for windows in python I realized that it was rather hard to send strings between different programs. I eventually got it running so I thought I’d post them here as examples.
I found out that the best path to choose is by using the windows message event-thingies. I’m not really much of a windows user so I have no clue about how they actually work but at least I kind of know how to use them now.
Basically to pass a string between two applications, you pass the memory address of a structure containing a string among other things (a pointer that is) to the target window by using it’s window handle (hWnd).
This is probably rather easy in c++ but since python doesn’t really have pointers you have to use the ctypes, array and struct modules to construct/deconstruct the things to send.
To get this running you need the win32 modules (win32con, win32gui, win32api) as well as ctypes. I used wxpython for the GUI but you can use anything you want. If you want my examples to run you need it installed though…
Anyways, I tried to document the code heavily so that I won’t have to explain much more…
Here is the code for the reciever
################
######reciever.py
############
import wx
import win32gui
import win32con
import struct
import ctypes
import sys
#Make an app with a static text
app = wx.PySimpleApp()
frame = wx.Frame( None, -1, "Message Reciever", size = ( 200, 50 ) )
result = wx.StaticText(frame, -1, "No text yet!",wx.Point(10,10))
#Write the windows hWnd to a file for the other app to read
fil = open( "hWnd", "w" )
fil.write( "%d" % frame.GetHandle() )
fil.close()
#Custom message handler
def MyWndProc( hWnd, msg, wParam, lParam ):
# if we get any message from other app
if msg == win32con.WM_COPYDATA:
#get the struct-string from the memory address
structure = ctypes.string_at( lParam, 12 )
#unpack the data
data = struct.unpack("IIP", structure)
unused, str_len, str_adr = data
#and finally get the real string from the memory
my_string = ctypes.string_at( str_adr, str_len )
#update the static text
result.SetLabel( my_string )
#handles program termination
elif msg == win32con.WM_DESTROY:
win32gui.DestroyWindow( frame.GetHandle() )
win32gui.PostQuitMessage(0)
return win32gui.CallWindowProc( oldWndProc, hWnd, msg, wParam, lParam )
#Use the custom handler
oldWndProc = win32gui.SetWindowLong(
frame.GetHandle() ,
win32con.GWL_WNDPROC ,
MyWndProc )
#show it!
frame.Show()
app.MainLoop()
By default running this displays a small window containing a static text that looks like this

Then we have the code for the sender
################
######sender.py
############
import win32con
import win32api
import struct, array
import sys
# get text to send
if len( sys.argv ) > 1:
text_to_send = sys.argv[1]
else:
sys.exit( 1 )
#get the hWnd to send to
#we have stored it in a file
hwnd = int( open( "hWnd", "rb" ).read() )
#create a char array from the string
my_data = array.array( 'c', text_to_send )
#get the memory address to the array
data_ad, data_len = my_data.buffer_info()
#create a struct with length and address to the data
my_struct = array.array( 'c', struct.pack( "IIP", data_len, data_len, data_ad ) )
#and make a pointer to it
struct_ad = my_struct.buffer_info()[0]
#now send it to the hWnd
win32api.SendMessage(
hwnd ,
win32con.WM_COPYDATA ,
0 ,
struct_ad )
This doesnt use any GUI. It is just a console application that takes an argument and sends it to the other app. If you’d like you could let this application take input through a fancy GUI or whatever.
Since the reciever writes its hWnd to a file that the sender reads it knows where to send the data. You could also find the window through other means in the windows API.
Anyways, calling the sender with an argument results in the text in the other window changing!

Pretty basic examples that shouldn’t be too hard to build upon. Please leave a comment if it was helpful!
Many thanks for this! Just need to convert the sender bit to Delphi and I’m all set.