PyWin SendMessage

G

g.franzkowiak

Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


# get the window handle
hwnd = win32ui.FindWindow(None, "special window")

# print just for fun
print hwnd

cds = packCopyData(1, '1')
print cds

# try to send it a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
cds)

#########################################################################

The last parameter shut be an integer, but I think it must be a pointer ?

Any experience or a tip for me ?


gf
 
T

Thomas Heller

g.franzkowiak said:
Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct

After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas
 
G

g.franzkowiak

Thomas said:
Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas

Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array
from ctypes import *

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"


gerd
 
T

Thomas Heller

g.franzkowiak said:
Thomas said:
Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas

Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array
from ctypes import *

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"

That error refers to the first argument - win32ui.FindWindow returns a
PyCWnd object, which is not accepted by win32api.SendMessage.
Changing this brings you one step further. win32api.SendMessage accepts
an integer for the last element, so addressof(cds) should work now.

win32gui.SendMessage is more tolerant in what it accepts as 4th
argument, according to the error message you get when you try it it
expects a string, a buffer, or an integer. So you could use addressof()
or pointer(), what you like best.

Thomas
 
G

g.franzkowiak

Thomas said:
Thomas said:
Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas

Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array
from ctypes import *

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"


That error refers to the first argument - win32ui.FindWindow returns a
PyCWnd object, which is not accepted by win32api.SendMessage.
Changing this brings you one step further. win32api.SendMessage accepts
an integer for the last element, so addressof(cds) should work now.

win32gui.SendMessage is more tolerant in what it accepts as 4th
argument, according to the error message you get when you try it it
expects a string, a buffer, or an integer. So you could use addressof()
or pointer(), what you like best.

Thomas

Hi Thomas,

crazy, operates :))
Only 'addressof' is possible and
merely the data types on the receiver side are not correct.
I want use an int and char[256], must play...

Thanks
gerd
 
G

g.franzkowiak

Thomas said:
Thomas said:
Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas

Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array
from ctypes import *

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"


That error refers to the first argument - win32ui.FindWindow returns a
PyCWnd object, which is not accepted by win32api.SendMessage.
Changing this brings you one step further. win32api.SendMessage accepts
an integer for the last element, so addressof(cds) should work now.

win32gui.SendMessage is more tolerant in what it accepts as 4th
argument, according to the error message you get when you try it it
expects a string, a buffer, or an integer. So you could use addressof()
or pointer(), what you like best.

Thomas

Super, operates :))

My last answer must be in the Nirvana, strange ?

Ok, only the version with 'addressof' generates a message and I must
play with the data types. The receiver becomes a wrong data formate.
Expect (int=1, char[256]='1\00'), but the int is 0x31 and the string
somewhat. Must play with my data.

Thanks
gerd
 
?

=?ISO-8859-1?Q?Gonzalo_Monz=F3n?=

g.franzkowiak escribió:
Thomas Heller schrieb:

Thomas Heller schrieb:








Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################
#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas


Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array


from ctypes import *

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"
That error refers to the first argument - win32ui.FindWindow returns a
PyCWnd object, which is not accepted by win32api.SendMessage.
Changing this brings you one step further. win32api.SendMessage accepts
an integer for the last element, so addressof(cds) should work now.

win32gui.SendMessage is more tolerant in what it accepts as 4th
argument, according to the error message you get when you try it it
expects a string, a buffer, or an integer. So you could use addressof()
or pointer(), what you like best.

Thomas

Super, operates :))

My last answer must be in the Nirvana, strange ?

Ok, only the version with 'addressof' generates a message and I must
play with the data types. The receiver becomes a wrong data formate.
Expect (int=1, char[256]='1\00'), but the int is 0x31 and the string
somewhat. Must play with my data.

Thanks
gerd

Hi Gerd,

I'm not really sure of, but I think you must use a message value in
range of WM_USER or WM_APP so this fact maybe let the receiver window
getting bad data... have a look to this:

http://msdn.microsoft.com/library/d.../messagesandmessagequeuesmessages/wm_user.asp

0 through WM_USER
<http://msdn.microsoft.com/library/e.../messagesandmessagequeuesmessages/wm_user.asp>
0x0400
Messages reserved for use by the system.
*WM_USER* through 0x7FFF Integer messages for use by private window
classes.
*WM_APP* through 0xBFFF Messages available for use by applications.
0xC000 through 0xFFFF String messages for use by applications.
Greater than 0xFFFF Reserved by the system.



I've done the same with PHP GTK and achieved random results sending low
Msg values... until used WM_USER and above. Also, in my case only
PostMessage work fine... try using both... but expect this doesn't
happen with python,

Hope it helps.

Gonzalo
 
G

g.franzkowiak

Gonzalo said:
g.franzkowiak escribió:
Thomas Heller schrieb:

Thomas Heller schrieb:








Hello everybody,

I've tryed to use an interprocess communication via
SendMessage on Windows.
Unfortunately, nothing goes on

#########################################################################

#! /usr/bin/env python

import win32api, win32ui, win32con
import struct, array

"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

def packCopyData(nNum, sString):
int_buffer = array.array("L",[nNum])
char_buffer = array.array('c', sString)
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address = char_buffer.buffer_info()[0]
char_buffer_size = char_buffer.buffer_info()[1]
copy_struct = struct.pack("pLp", # dword*, dword, char*
int_buffer_address,
char_buffer_size,
char_buffer)
return copy_struct


After packCopyData(...) returns, the arrays are destroyed, which will
probably void their contents. You must keep them alive until you
don't
need the COPYDATASTRUCT instance any longer. For this kind of stuff,
ctypes may be easier to use than pywin32.

Thomas


Hmm, have read something in <<http://aspn.activestate.com>>
and the script changed to this:

#---------------------------------------------------------
#! /usr/bin/env python

import win32api, win32ui, win32con, win32gui
import struct, array

from ctypes import *



"""
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
"""

class COPYDATATYPE(Structure):
_fields_ = [("nNum", c_ulong),
("szData", c_char_p)]

class COPYDATASTRUCT(Structure):
_fields_ = [("dwData", c_ulong),
("cbData", c_ulong),
("lpData", POINTER(COPYDATATYPE))]

# get the window handle
hwnd = win32ui.FindWindow(None, "target window")

# print just for fun
# ##print hwnd

# prepare copydata structure for sending data
cpyData = COPYDATATYPE(1, '1')
cds = COPYDATASTRUCT(c_ulong(1),
c_ulong(sizeof(cpyData)),
pointer(cpyData))

# try to send a message
win32api.SendMessage(hwnd,
win32con.WM_COPYDATA,
0,
pointer(cds))

#---------------------------------------------------------
and the message for the last line is:
==> TypeError: an integer is required"

This message comes with "pointer(cds)" and with "addressof(cds)"


That error refers to the first argument - win32ui.FindWindow returns a
PyCWnd object, which is not accepted by win32api.SendMessage.
Changing this brings you one step further. win32api.SendMessage accepts
an integer for the last element, so addressof(cds) should work now.

win32gui.SendMessage is more tolerant in what it accepts as 4th
argument, according to the error message you get when you try it it
expects a string, a buffer, or an integer. So you could use addressof()
or pointer(), what you like best.

Thomas


Super, operates :))

My last answer must be in the Nirvana, strange ?

Ok, only the version with 'addressof' generates a message and I must
play with the data types. The receiver becomes a wrong data formate.
Expect (int=1, char[256]='1\00'), but the int is 0x31 and the string
somewhat. Must play with my data.

Thanks
gerd

Hi Gerd,

I'm not really sure of, but I think you must use a message value in
range of WM_USER or WM_APP so this fact maybe let the receiver window
getting bad data... have a look to this:

http://msdn.microsoft.com/library/d.../messagesandmessagequeuesmessages/wm_user.asp


0 through WM_USER
<http://msdn.microsoft.com/library/e.../messagesandmessagequeuesmessages/wm_user.asp>
0x0400
Messages reserved for use by the system.
*WM_USER* through 0x7FFF Integer messages for use by private window
classes.
*WM_APP* through 0xBFFF Messages available for use by applications.
0xC000 through 0xFFFF String messages for use by applications.
Greater than 0xFFFF Reserved by the system.



I've done the same with PHP GTK and achieved random results sending low
Msg values... until used WM_USER and above. Also, in my case only
PostMessage work fine... try using both... but expect this doesn't
happen with python,

Hope it helps.

Gonzalo


Hi Gonzalo,

thank you for your interest and for your tips.
With your links was it possible to learn something over messages in user
applications. I'm not the windows guru, like the open source scene.

My problem was not the message type and I think the WM_COPYDATA is the
right thing for interprocess communication between python and C++.
I've changed in my script the COPYDATATYPE field szData from c_char_p to
c_char * 256 and the memory is correct initialized. The first situation
was according to **data and in consequence the wrong content on the
receiver side.
Now is it a good thing :)

gerd
 
T

Tim Roberts

Gonzalo Monzón said:
Hi Gerd,

I'm not really sure of, but I think you must use a message value in
range of WM_USER or WM_APP so this fact maybe let the receiver window
getting bad data...

No. WM_COPYDATA is designed specifically for his use case -- interprocess
communication. The WM_USER range is only if you are inventing a custom
message for some new purpose.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top