全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4458
推到 Plurk!
推到 Facebook!

sendMessage 的 WM_COPYDATA 偷偷做了什麼事?

答題得分者是:aftcast
boy330077
一般會員


發表:39
回覆:59
積分:19
註冊:2009-10-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2015-03-02 14:24:35 IP:211.20.xxx.xxx 訂閱
 EXEA :


[code delphi]
const
WM_MY_MESSAGE = WM_APP 99;

type
Tfrm_EXEA_Main = class(TForm)
Label1: TLabel;
ListBox1: TListBox;
private
{ Private declarations }
procedure CopyData(var Msg: TWMCopyData); message WM_COPYDATA;
procedure MyReceive(var Msg: TWMCopyData); message WM_MY_MESSAGE;
public
{ Public declarations }
end;

procedure Tfrm_EXEA_Main.CopyData(var Msg: TWMCopyData);
begin
ListBox1.Items.Append('CopyData is ' PChar(Msg.CopyDataStruct.lpData));
end;
procedure Tfrm_EXEA_Main.MyReceive(var Msg: TWMCopyData);
begin
ListBox1.Items.Append('MyReceive is ' PChar(Msg.CopyDataStruct.lpData));
end;
[/code]

兩個副程式 幾乎一樣 只有後面的訊息常數 不同

但是 WM_MY_MESSAGE 卻會錯誤(似乎是位置錯誤)

懷疑 是不是
WM_COPYDATA 在哪裡已經被處理過? 我卻找不到

boy330077
一般會員


發表:39
回覆:59
積分:19
註冊:2009-10-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2015-03-02 14:28:24 IP:211.20.xxx.xxx 訂閱
 上方  程式碼區塊有問題

想要修改卻跳出
const

Tfrm_EXEA_Main = class(TForm)
ListBox1: TListBox;
{ Private declarations }
procedure MyReceive(var Msg: TWMCopyData); message WM_MY_MESSAGE;
{ Public declarations }

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2015-03-02 14:48:54 IP:114.32.xxx.xxx 訂閱
關鍵點在 sendmessage/postmessage 是在哪裡發生的?


別的應用程式? 同一隻應用程式不同thread?


不過,先可以簡言之,WM_COPYDATA 之所以叫 WM_COPYDATA 是因為它是 windows系統創的,windows系統怎麼處理它,是windows特有的能力。而你的自訂訊息,是你寫的,問題點極可能是你要傳的訊息是從別的應用程式送來的… ???



------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
boy330077
一般會員


發表:39
回覆:59
積分:19
註冊:2009-10-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2015-03-02 14:58:08 IP:211.20.xxx.xxx 訂閱
 沒錯   EXEA   EXEB 分開

EXEB 有兩個按鈕 分別

procedure Tfrm_EXEB_Main.Button1Click(Sender: TObject);
begin
MySendMessage(WM_COPYDATA);
end;
procedure Tfrm_EXEB_Main.Button2Click(Sender: TObject);
begin
MySendMessage(WM_MY_MESSAGE);
end;
procedure Tfrm_EXEB_Main.MySendMessage(msg: Cardinal);
var
h:HWND;
copyDataStruct:TCopyDataStruct;
begin
h:=FindWindow('Tfrm_EXEA_Main', 'EXEA');
with copyDataStruct do
begin
dwData := 0;
cbData := (Length(str) 1)*2;
lpData := PChar(str);
SendMessage(h, msg, Integer(Handle), Integer(@copyDataStruct));
end;
end;

按鈕1 EXE1 能收到正確字串
按鈕2 錯誤

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2015-03-02 15:13:28 IP:114.32.xxx.xxx 訂閱
ok,你想知道 wm_copydata 偷偷做了什麼? 

我把我所知道的部份讓你知道。但我講的不是全部,全部的細節可能 微軟的工程師才會知道。


因為不同的 process 有著自己的 記憶體空間,原則上是2g (例外不說),就是說一個應用程式有 2g 個門牌號碼,裡面放著程式碼與資料。我們假設

exeA 的 記憶體位址 5000的地方,放了一個字串叫 " hello world"。 而 exeB 的記憶體裡,它的 5000的地方放 "Im nerd"。

當你在 exeB的執行環境下,你copy了 5000的地址,當作要送給 exeA的內容。

發生什麼事? 你在 exeA的地方,收了message,裡面提到 5000的地址有資料,請去拿。但…… 此刻是在 exeA裡,去5000拿,是會拿到 "hello world",不會拿得到 exeB家裡的 im nerd 的。 此 5000地址,不是那個5000的地址!

於是,若不幸的,5000地址之於 exeA 是一個禁區,那就會跳該死的AV。


那麼WM_COPYData它幹了啥? windows 系統自己訂的東西,無非就是要讓 不同 proceess 可以溝通。於是當 exeB的5000的位址送過去時,windows會偷偷的把 exeb 的內容印射到 exeA可以讀到的地址,這裡當然很玄的技巧。但你就想像,windows讓接收訊息的那方可以神奇的去抓別人家裡的資料。

若你真的不想用 windows提供的這個方法。你可以
1/ 寫一個dll,並設定該dll可以分享資料,然後讓 exea 與 exeb 都載入該dll
2/ 也可以用 socket 方式
3/ 也可以用 fiemapping的方式
4/ name pipe 方式


------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
boy330077
一般會員


發表:39
回覆:59
積分:19
註冊:2009-10-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2015-03-02 15:22:43 IP:211.20.xxx.xxx 訂閱
 所以  WM_COPYDATA 訊息 果然 已經被系統動過手腳

我會嘗試已下的方式 感謝您
系統時間:2024-03-29 17:43:31
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!