本帖最后由 ceoguang 于 2011-2-8 06:48 编辑
回复 ceoguang
发送以下消息就失败了
111.111.111.111|111.111.111.111|111.111.111.111|111.111.1 ...
itljl 发表于 2011-2-7 16:19
SendMessage跨进程时LPARAM不能超过32位本身.最后测试了一下,原来是宽字符的问题,修改了一下,转换成单字符.总算能达到了32位的最大限制.
#NoTrayIcon
Opt("GUIOnEventMode", 1)
Opt("GUIResizeMode", 1)
Global Const $WM_COPYDATA = 0x004A
Global Const $WM_NULL = 0x0000
Global Const $WM_GETTEXTLENGTH = 0x000E
Global Const $EM_REPLACESEL = 0xC2
Global Const $EM_SETSEL = 0xB1
Global Const $tagCOPYDATASTRUCT = "dword dwData;dword cbData;ptr lpData;"
;http://msdn.microsoft.com/en-us/library/ms649010
#cs
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
#ce
Global $Mark = Random(1024, 65535, 1) ;广播的标识
$Form1 = GUICreate("进程通讯示例", 484, 351, -1, -1, -2133917696);$GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX
GUISetOnEvent(-3, "_GuiEvent")
$Edit1 = GUICtrlCreateEdit("", 8, 8, 465, 209)
GUICtrlSetLimit(-1, 1e8)
GUICtrlSetResizing(-1, 102)
$Edit2 = GUICtrlCreateEdit("", 8, 225, 465, 81)
GUICtrlSetResizing(-1, 582)
GUICtrlSetLimit(-1, 1e8)
$Button1 = GUICtrlCreateButton("发送", 200, 318, 75, 25)
GUICtrlSetOnEvent(-1, "_GuiEvent")
GUICtrlSetResizing(-1, 840)
GUISetState()
GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA")
GUIRegisterMsg($WM_NULL, "WM_NULL")
#EndRegion ### END Koda GUI section ###
Global $Target
Local $Count = 0
Broadcast_Msg()
While 1
Sleep(100)
$Count += 1
If $Count = 100 Then ;10秒钟.
$Count = 0
If Not IsWindow($Target) Then Broadcast_Msg() ;向系统广播
EndIf
WEnd
Func _GuiEvent()
Switch @GUI_CtrlId
Case -3
Exit
Case $Button1
If GUICtrlRead($Edit2) <> "" Then
If IsWindow($Target) Then
_SendProcessMsg($Target, GUICtrlRead($Edit2))
If @extended Then
$iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH) ;发送消息获取$Edit1的字节
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength) ;将焦点定位到最后
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, "<<发送到进程: (" & WinGetProcess($Target) & ") 的消息 " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF & GUICtrlRead($Edit2) & @CRLF & @CRLF, 0, "wparam", "wstr") ;向$Edit1焦点处写入收到的消息
GUICtrlSetData($Edit2, "")
Else
MsgBox(48, "", "消息发送失败", -1, $Form1)
EndIf
Else
MsgBox(48, "", "找不到接收进程!", -1, $Form1)
EndIf
Else
MsgBox(48, "", "请输入要发送的内容!", -1, $Form1)
EndIf
EndSwitch
EndFunc ;==>_GuiEvent
Func WM_COPYDATA($hWnd, $iMsg, $iwParam, $ilParam)
Local $iBuffer = DllStructCreate($tagCOPYDATASTRUCT, $ilParam)
Local $tBuffer, $iLength, $RecMsg
If DllStructGetData($iBuffer, "dwData") = 0x01234567 Then
$tBuffer = DllStructCreate("char[" & DllStructGetData($iBuffer, 'cbData') & "]", DllStructGetData($iBuffer, 'lpData')) ;cbData保存着数据的大小,lpData接收到的数据,其值可以为空
$RecMsg = BinaryToString(DllStructGetData($tBuffer, 1))
$Target = $iwParam ;保存当前对话者的句柄
$iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH) ;发送消息获取$Edit1的字节
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength) ;将焦点定位到最后
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, ">>收到消息类型 (" & $iMsg & ") 来自进程: (" & WinGetProcess($Target) & ") " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF & $RecMsg & @CRLF & @CRLF, 0, "wparam", "wstr") ;向$Edit1焦点处写入收到的消息
EndIf
Return "GUI_RUNDEFMSG"
EndFunc ;==>WM_COPYDATA
Func WM_NULL($hWnd, $iMsg, $iwParam, $ilParam)
Local $iLength
If $ilParam <> $Mark Then
MsgBox(64, "收到消息", "目标句柄: " & $iwParam, -1, $Form1);挂起线程,终止消息传递
_SendProcessMsg($iwParam, "欢迎")
$iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH)
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength)
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, ">>HWND (" & $iwParam & ") Process: (" & WinGetProcess($iwParam) & ") Msg: (" & $iMsg & ") " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF, 0, "wparam", "wstr")
EndIf
Return "GUI_RUNDEFMSG"
EndFunc ;==>WM_NULL
Func Broadcast_Msg()
_SendMessageTimeout(0xFFFF, $WM_NULL, $Form1, $Mark)
$iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH)
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength)
_SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, "<<广播WM_NULL信息 " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF, 0, "wparam", "wstr")
EndFunc ;==>Broadcast_Msg
Func _SendProcessMsg($hWnd, $sMsg)
;$hWnd: 目标进程的主窗口句柄
;$sMsg: 要发送的消息内容
Local $sBuffer = DllStructCreate("char[" & StringLen(StringToBinary($sMsg)) + 1 & "]")
Local $tBuffer = DllStructCreate($tagCOPYDATASTRUCT)
Local $pBuffer = DllStructGetPtr($tBuffer)
Local $StrLen
DllStructSetData($sBuffer, 1, StringToBinary($sMsg))
DllStructSetData($tBuffer, "dwData", 0x01234567) ;标识。这个数值可以随意定。
$StrLen = DllStructGetSize($sBuffer)
If $StrLen > 2 ^ 32 - 1 Then
MsgBox(16, "", "消息内容超出lParam限制", -1, $hWnd)
Return SetError(1, 0)
EndIf
DllStructSetData($tBuffer, "cbData", $StrLen) ;数据大小
DllStructSetData($tBuffer, "lpData", DllStructGetPtr($sBuffer)) ;发送的数据
_SendMessageTimeout($hWnd, $WM_COPYDATA, $Form1, $pBuffer)
;对应消息函数的($hWnd, $iMsg, $iwParam, $ilParam)
;这里使用SendMessageTimeout是为了防止因目标线程繁忙或挂起导致返回时间过长(或无返回)从而导致当前调用的线程挂起(不再向下执行),当然你可以使用PostMessage,但PostMessage是没有结果返回的.
Return SetExtended(@extended)
EndFunc ;==>_SendProcessMsg
Func _SendMessageTimeout($hWnd, $iMsg, $wparam = 0, $lparam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult", $iTimeout = 1000, $iFlags = 3)
;这个参数结构是根据封装好的_SendMessage修改而来.可以完全替换_SendMessage.默认超时设置$iTimeout = 1000(单位毫秒),$iFlags是(SMTO_BLOCK , SMTO_ABORTIFHUNG)的组合
;http://msdn.microsoft.com/en-us/library/ms644952(VS.85).aspx
Local $Ret = DllCall("user32.dll", $sReturnType, "SendMessageTimeoutW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wparam, $lParamType, $lparam, "uint", $iFlags, "uint", $iTimeout, "dword_ptr*", $iReturn)
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, "")
EndIf
Return SetError(0, 1, $Ret[7])
EndFunc ;==>_SendMessageTimeout
Func IsWindow($hWnd)
Local $aResult = DllCall("user32.dll", "bool", "IsWindow", "hwnd", $hWnd)
If @error Then Return SetError(@error, @extended, 0)
Return $aResult[0]
EndFunc ;==>IsWindow
回复 pusofalse
请问P版,内存共享可以是一个数组吗?
如A.exe中的
$arr1
与B.exe中的
$arr ...
itljl 发表于 2011-2-7 16:27
首先你得去了解CreateProcess的工作过程.
但是对于autoit而言这些都是白费力.因为你很难找到所谓的变量地址.真正要这样做的话必须调用汇编来实现.
回复 pusofalse
P版能不能写个你的源码的示例:
ShareMemory.au3 (3.13 KB)
10楼
itljl 发表于 2011-2-7 16:29
这个UDF仅仅是使用读写及关闭部份.
要实现全功能,还得添加两个步骤.
1.创建内核对象.(createfile)
2.创建文件映射对象(createfilemapping) |