Delphi有沒有辦法替換一個Object的public method? |
答題得分者是:aftcast
|
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
各位大大,小弟向各位請教一個問題,如果有個class :
TTest = class ... public procedure DoSomething(aParam: string); .... end; 另一個class: THook = class ... public procedure DoSomething(aParam: string); .... end; TTest 和THook,有一個一樣的method, DoSomething. 現在有兩個TTest和THook 的Instance, Test := TTest.Create; Hook:=THook.Create; 在程式中,有沒有辦法可以用Hook的DoSomething替換Test的DoSomething呢? 我在網上找了很久都沒找到,不知道有沒有大大高人可以指點一下~~萬分感謝~~!!! |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
|
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
很好奇會有這樣的應用? 你最終目的到底是什麼?
你這個想法是一定到不了,我極度肯定! 但若改個做法,也許可以達成你最終的目的,但重點是你的最終目的你沒說… ===================引 用 marklai 文 章=================== 多謝sryang,確實兩具class是沒有任何關係,我祇是想試試有沒有類似Hook,或其它方法,可以做到類似的效果,替換掉一個class object的method. ===================引 用 sryang 文 章=================== 找不到方法是正常的,因為沒有辦法做 因為這兩個 class 是彼此獨立的,沒有任何的關係
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
多謝aftcast 的關注!
我之所以會有這個想法,其實是因為我的專案是用delphi 2007做的,要求support unicode,所以用了比較舊的免費版Tnt controls。 專案裡有不少地方直接用了raise Exception.create,來raise exception,這樣會有一個messagebox。但是後來要求這些exception message都要support widestring。 我在VCL sources裡跟蹤了好久,發現有些地方會直接用 Application.ShowException將Exception顯示出來。但是TApplication.ShowException祇是一個普通的method,無法修改。 因為我記得以前在網上曾經看到過,有人可以用特殊的方法,修改一個Object的Private的資料,所以我就想有沒有可能能過某種方法將這個Application.ShowException替換掉。 正如aftcast 你所說的,因為找不到這樣的方法,所以我最後還是放棄了這個想法,另外找方法去代替。 現在我純粹是好奇,想知道有沒有什麼方法可以把一個object的method替換掉。我知道這不是一個正常的需求,這樣其實也是不符合OO的,我祇是好奇,想和大家分享而已。 ===================引 用 aftcast 文 章=================== 很好奇會有這樣的應用? 你最終目的到底是什麼? 你這個想法是一定到不了,我極度肯定! 但若改個做法,也許可以達成你最終的目的,但重點是你的最終目的你沒說… ===================引 用 marklai 文 章=================== 多謝sryang,確實兩具class是沒有任何關係,我祇是想試試有沒有類似Hook,或其它方法,可以做到類似的效果,替換掉一個class object的method. ===================引 用 sryang 文 章=================== 找不到方法是正常的,因為沒有辦法做 因為這兩個 class 是彼此獨立的,沒有任何的關係 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
瞭解了!
method不能換掉最主要的原因是 物件導向的方法,它隱含了self (在c 叫this) 這個指標參數。 它不像一般的 function pointer 僅4bytes檔指標就可,它至少要是 8bytes,一個是法方的位置,一個是將被帶入的 self 的實例(instance)。換方法的位置可能還有可行性,若要連 instance 的位置也換了,恐不是易事。即時我不敢說100%不行,但只能說若要達成恐要相當的心力去做低階的動態的切換instance 的所在。我對組語熟,都覺得超級的難到可說是近不可能了。 以上也是純討論。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
樓主,您的問題是有解的。請看以下程式碼:
這是 TApplication.HandleException 的程式碼[code delphi] procedure TApplication.HandleException(Sender: TObject); begin if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0); if ExceptObject is Exception then begin if not (ExceptObject is EAbort) then if Assigned(FOnException) then // 當 OnException 事件有處理程式時 FOnException(Sender, Exception(ExceptObject)) // 就執行 OnException 事件 else ShowException(Exception(ExceptObject)); // 否則執行 ShowException end else SysUtils.ShowException(ExceptObject, ExceptAddr); end; [/code] 所以您只要撰寫一個 Application.OnException 事件處理程式就可以了。例如:[code delphi] TMainForm = class(TForm) procedure OnCreate(Sender: TObject); public procedure ApplicationOnException(Sender: TObject; E: Exception); end; implementation // Application.OnException 處理程式 procedure TMainForm.ApplicationOnException(Sender: TObject; E: Exception); begin // 在這裡就可以自己顯示例外訊息,例如: ShowMessage('應用程式出現例外狀況:'#10 E.Message); end; procedure TMainForm.OnCreate(Sender: TObject); begin // 幫 Application 掛上 OnException 事件 Application.OnException := ApplicationOnException; end; [/code]
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
編輯記錄
sryang 重新編輯於 2011-05-05 06:21:26, 註解 無‧
|
herbert2
尊榮會員 發表:58 回覆:640 積分:894 註冊:2004-04-16 發送簡訊給我 |
|
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
|
herbert2
尊榮會員 發表:58 回覆:640 積分:894 註冊:2004-04-16 發送簡訊給我 |
|
syntax
尊榮會員 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
有試過直接修改 物件的成員 Table 嗎?
Table 相關資訊可參考 Inside VCL 或是 Google 一下,若帶入參數不相同的話,會需要額外的處理 ===================引 用 aftcast 文 章=================== 瞭解了! method不能換掉最主要的原因是 物件導向的方法,它隱含了self (在c 叫this) 這個指標參數。 它不像一般的 function pointer 僅4bytes檔指標就可,它至少要是 8bytes,一個是法方的位置,一個是將被帶入的 self 的實例(instance)。換方法的位置可能還有可行性,若要連 instance 的位置也換了,恐不是易事。即時我不敢說100%不行,但只能說若要達成恐要相當的心力去做低階的動態的切換instance 的所在。我對組語熟,都覺得超級的難到可說是近不可能了。 以上也是純討論。 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
syntax 好久不見,好像一陣子沒看到你了…
想透過vmt解決這個問題,就如我原來說的,幾乎是不可能。因原就是我說的 self 這個instance該怎麼去取代? 除非把整個process的memory裡,關於doSomething呼叫前的move EAX, [....] (虛碼) 的部份全取代成自己的instance 的self。否則,光是把法方的位址換掉是沒用的。 順便借這個機會讓大家也知道一下,我發現李維的 Inside VCL 講到關於vmt 與self的部份,他寫錯了。page 2-68 中他說 「看到ClassType回傳的結果就是Self指到的目的地」這是錯的,而這個錯還相印證在他page 2-65 圖2-19 上。(註2) 依我的研究,正確的是 : 「看到ClassType回傳的結果就是Self指到的目的地的地址」,差三個字整個觀念就差很多,而且他有點不像是誤寫,因為連他的圖2-19也印證他當時想法"也許"是錯的。(註2) 圖2-19應該改成 Foo : ptrToVmt : Pointer // 隱藏的 aStr aField instance(或有人喜歡叫object)的self是指向instance的開頭位址,而那個開頭的地方其實放的是一個指標(就是上面我打的 ptrToVmt,這個名稱是我自己說的,文件上沒有看到)。而這個隱形指標則指向vmt的開始位址。 所以圖應該是 self --> ptrToVmt -> vmt 而不是李維所畫的,self--> vmt 。 如果是self --> vmt 那整個物件的概念就全會亂掉,錯掉。 self 當然是指向 instance 本身的。 註1: 事實上 delphi的 self 比較機車一點,他還有另一個意思,是用在class function的,在那裡,self 就是指向 vmt 的所在。然而,instance上的觀念則不一樣,不能混為一談! 註2: 剛打完後,突有個想法,也許李維的那個圖是沒錯的。是否他用self 來表我所講的ptrToVmt,若是如此,太容易混淆。 雖然他也許交插的用註1的觀念,但該圖講的是instance,而非class。加上他在page 2-68上的文字部份,會讓人有很大的誤會! ===================引 用 syntax 文 章=================== 有試過直接修改 物件的成員 Table 嗎? Table 相關資訊可參考 Inside VCL 或是 Google 一下,若帶入參數不相同的話,會需要額外的處理
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
多謝 sryang 的回覆,你所說的方法,其實我已經試過。這個方法可以在一定程度上解決問題,但其實有點小問題,我覺得並不是完美的方法。
當在專案的某個地方,例如MainForm,加上一個TApplicationEvents的component,在TAppliationEvents的OnException寫入程式碼,想另外特別處理Exception的時候,會發現這個OnException根本就用不到,仍然會跑到MainForm的ApplicationOnException中。 原因在於,AppEvnts這個unit在initialization的部分,會create一個TMultiCaster的object,所有TAppliationEvents在Create的時候,都會將自己加入到MultiCaster中.而MulitCaster恰恰就是會替換掉Application.OnException event。 [code delphi] constructor TMultiCaster.Create(AOwner: TComponent); begin inherited Create(AOwner); FAppEvents := TComponentList.Create(False); with Application do begin OnActionExecute := DoActionExecute; OnActionUpdate := DoActionUpdate; OnActivate := DoActivate; OnDeactivate := DoDeactivate; OnException := DoException; OnHelp := DoHelp; OnHint := DoHint; OnIdle := DoIdle; OnMessage := DoMessage; OnMinimize := DoMinimize; OnRestore := DoRestore; OnShowHint := DoShowHint; OnShortCut := DoShortcut; OnSettingChange := DoSettingChange; OnModalBegin := DoModalBegin; OnModalEnd := DoModalEnd; end; end; [/code] 而在TMultiCaster的DoException可以看到,TMultiCaster會檢查所有的ApplicationEvents有否有處理OnException,如果有就會Call ApplicationEvents的OnException,否則,就直接Call Application.ShowException。 [code delphi] procedure TMultiCaster.DoException(Sender: TObject; E: Exception); var I: Integer; FExceptionHandled: Boolean; begin BeginDispatch; FExceptionHandled := False; try for I := Count - 1 downto 0 do begin if Assigned(AppEvents[I].OnException) then begin FExceptionHandled := True; AppEvents[I].DoException(Sender, E); if FCancelDispatching then Break; end; end; finally if not FExceptionHandled then if not (E is EAbort) then Application.ShowException(E); EndDispatch; end; end; [/code] 所以,如果使用這個方法的話,日後如果在專案的其它地方使用了TApplicationEvents,想另外處理Exception的話,可能就會無法處理。 因為TMulitcaster是在AppEvnts的Implementation中。在其它unit根本無法得到TMulticaster,所以MainForm上的ApplicationOnException也無法由Multicaster去找到專案中的其它TApplicationEvents。我曾經嘗試過這樣做,不過最終都不成功。或者有前輩可以指點一下是不是有方法可以這樣做。 另外,如果日後在專案的某個地方,如果加入的TApplicationEvents是在MainForm Create之後,那麼,可能就會出現,MainForm上的AppliationOnException反而無效,因為已經被後來的MultiCaster替換掉Application.OnException。 這樣的話,其實是有點混亂的。 我最後使用的方法,是在專案開始的地方,先加入一個TApplicationEvents,用這個TApplicationEvents的OnException去處理,我始終覺得這並不是一個完美的方法。 因為看到TMulticaster對於未被處理的Exception會直接call Application.ShowException,所以我就想,最好是能替換掉Application.ShowException這個Method。這樣的話,我們可以放心的使用類似下面的程式碼: [code delphi] procedure ABC; begin if ..... then raise EUniCodeException.Create('UniCode Message') end; procedure CallABC; begin ABC; ShowMessage('OK'); end; [/code] 在CallABC中,沒有用try except去處理exception,不管有沒有用TApplicationEvents,或者有沒有替換Application.OnException,user都可以正常看到的ABC中產生的unicode Exception message。 我想,如果能夠替換了Application.ShowException,那麼應該是最徹底,最一勞永逸的方法。所有才有這樣一個問題想和大家一起討論分享 |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
marklai 網友,這種狀況的話,要請您在掛上 Application.OnException 時儲存原來的 Application.OnException (例如叫做 OldAppOnException)
而在你的 ApplicationOnException 處理常式中,要檢查 OldAppOnException 是否被 Assigned 如果有就執行他,這樣就會接回 TMultiCaster 的處理了 [code delphi] TMainForm = class(TForm) procedure FormCreate(Sender: TObject); private OldAppOnException: TExceptionEvent; // 儲存舊的 Application.OnException 處理常式 public procedure ApplicationOnException(Sender: TObject; E: Exception); end; implementation // Application.OnException 處理程式 procedure TForm1.ApplicationOnException(Sender: TObject; E: Exception); begin // 在這裡就可以自己顯示例外訊息,例如: ShowMessage('應用程式出現例外狀況:'#10 E.Message); // 接回原先的例外處理常式 if Assigned(OldAppOnException) then OldAppOnException(Sender, E); end; procedure TForm1.FormCreate(Sender: TObject); begin // 幫 Application 掛上 OnException 事件 OldAppOnException := Application.OnException; Application.OnException := ApplicationOnException; end; [/code]
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
非常感謝aryang你的關注,你說得很對。 但是如果當我們指定Application.OnException的時候,TMulticaster還沒有被create,而是後來才create的,那我們儲存的那個OldApplicationOnException就會無效了,因為TMulitcaster替換前並不會檢查是否已經Assigned Application.OnException。
還有一個,就是如果有其它地方直接Call Appliation.ShowException的情況,當然,可能這種情況非常少見。 正如之前說的,解決一個問題可能可以有多種上途徑,其實,對於我最初的Exception處理的問題,論用Assign Application.OnException或者TApplicationEvents都可以解決大部分的問題,這已經足夠了,哪種方法其實都可以選擇使用。我祇是覺得,替換掉Application.OnException要比替換掉Application.ShowException容易得多(當然,我是假設可以替換掉ShowException ),如果可以替換掉ShowException,那麼,我們的處理方法就比較不容易被破壞了。 我最後祇是想知道有沒有可能去替換一個Object的Method,這個問題,其實或許沒有什麼實用價值,祇是我覺得挺有趣而已。
編輯記錄
marklai 重新編輯於 2011-05-19 22:41:33, 註解 無‧
|
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
TMulticaster 的 Create 動作,是放在 AppEvnts 單元的 initialization 區段
[code delphi] initialization GroupDescendentsWith(TCustomApplicationEvents, Controls.TControl); MultiCaster := TMultiCaster.Create(Application); [/code] 只要你的主程式有 uses AppEvnts,就會在主程式載入記憶體時,執行到 initialization 區段中的程式 所以,在 Form 執行 OnCreate 事件時,MultiCaster 物件就是已經建立好的了
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
多謝sryang,我當然知道uses Appevnts就會建立MultiCaster,但是如果是專案不祇一個Exe,是由Exe和bpl,dll組成, 而exe 並沒有用TApplicationEvents,而是有其它runtime時在後期再加入的package中才用到TApplicationEvents,是不是有可能在MainForm create之後再有TMultiCaster.Create 呢?我沒有試過這種情況,所以我不確定會不會出現我說的情況,當然這些都可以處理。例如,在Exe中uses AppEvnts就可以確保不會了出現。我想說,替換Application.OnException要做哪些善後處理,我們都可以做得好好,可以慢慢完善,所以這些並不是主要的問題。
我很多謝sryang你的關注,但是我現在關心的並不是怎樣處理Application.OnException去處理Exception,祇是想知道有沒有辦法去替換一個Object的Method. 我記得好久之前曾經在網上看到過,用特別的方法,好像是用pointer,再用直接read / write memory的方法去取得和修改某個Object 的Private 內容。 如果是在一般的物件導向層面上我覺得應該是不可能去替換Method的,祇是好奇想知道有沒有網友知道方法而已。 我不熟悉組語,前面看aftcast從組語的層面說到不可能做到,我想可能真是不可能做到的。呵呵 |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
多謝syntax和affcast ,我曾經想過可能要從vmt上做手腳,不過不知道怎麼試驗。我很喜歡Inside VCL這本書,到無奈對組語不熟悉,所以書中很多用組語的地方,都只是部分看得懂,部分看不懂。曾經都想學一下組語,但總是覺得太過難,太多細節的東西要記住,所以最的都沒學會,就是知道一點皮毛。有機會一定要好好向affcast你請教呀!
===================引 用 aftcast 文 章=================== syntax 好久不見,好像一陣子沒看到你了… 想透過vmt解決這個問題,就如我原來說的,幾乎是不可能。因原就是我說的 self 這個instance該怎麼去取代? 除非把整個process的memory裡,關於doSomething呼叫前的move EAX, [....] (虛碼) 的部份全取代成自己的instance 的self。否則,光是把法方的位址換掉是沒用的。 順便借這個機會讓大家也知道一下,我發現李維的 Inside VCL 講到關於vmt 與self的部份,他寫錯了。page 2-68 中他說 「看到ClassType回傳的結果就是Self指到的目的地」這是錯的,而這個錯還相印證在他page 2-65 圖2-19 上。(註2) 依我的研究,正確的是 : 「看到ClassType回傳的結果就是Self指到的目的地的地址」,差三個字整個觀念就差很多,而且他有點不像是誤寫,因為連他的圖2-19也印證他當時想法"也許"是錯的。(註2) 圖2-19應該改成 Foo : ptrToVmt : Pointer // 隱藏的 aStr aField instance(或有人喜歡叫object)的self是指向instance的開頭位址,而那個開頭的地方其實放的是一個指標(就是上面我打的 ptrToVmt,這個名稱是我自己說的,文件上沒有看到)。而這個隱形指標則指向vmt的開始位址。 所以圖應該是 self --> ptrToVmt -> vmt 而不是李維所畫的,self--> vmt 。 如果是self --> vmt 那整個物件的概念就全會亂掉,錯掉。 self 當然是指向 instance 本身的。 註1: 事實上 delphi的 self 比較機車一點,他還有另一個意思,是用在class function的,在那裡,self 就是指向 vmt 的所在。然而,instance上的觀念則不一樣,不能混為一談! 註2: 剛打完後,突有個想法,也許李維的那個圖是沒錯的。是否他用self 來表我所講的ptrToVmt,若是如此,太容易混淆。 雖然他也許交插的用註1的觀念,但該圖講的是instance,而非class。加上他在page 2-68上的文字部份,會讓人有很大的誤會! ===================引 用 syntax 文 章=================== 有試過直接修改 物件的成員 Table 嗎? Table 相關資訊可參考 Inside VCL 或是 Google 一下,若帶入參數不相同的話,會需要額外的處理 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
如果方法要可以被取代,前題是你必需還是要用TApplication 來實作另一個方法。但這與你開始說的,用不同的物件的方法來取代,我想幾近不可能(不是做不到,而是要做到可能花上浩大的程式)。
如果你可以接受不使用別的物件,而是使用TApplication,那解法就有,而且算不是很難。 宣告一個類似如下的函式(非方法喔,前面沒有 類別:: ) int __fastcall MyNewException(TApplication *self, Exception* E) { //這裡搞自己的做法 } 然後用將原來的方法的thunk換成上面的那個thunk。 註: thunk由 oxE9 法方位移值 組成的 5個bytes結構,0xE9 這個機器碼表是組語之 JMP 註2: 我已對delphi的語法不熟了,用的是c 的用法,但原理是同樣的。 ===================引 用 marklai 文 章=================== 我記得好久之前曾經在網上看到過,用特別的方法,好像是用pointer,再用直接read / write memory的方法去取得和修改某個Object 的Private 內容。 如果是在一般的物件導向層面上我覺得應該是不可能去替換Method的,祇是好奇想知道有沒有網友知道方法而已。 我不熟悉組語,前面看aftcast從組語的層面說到不可能做到,我想可能真是不可能做到的。呵呵
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
marklai
一般會員 發表:2 回覆:8 積分:2 註冊:2007-09-03 發送簡訊給我 |
非常感激aftcast你的回覆,不好意思,有些地方我不是太懂。希望你不要介意。
“如果你可以接受不使用別的物件,而是使用TApplication,"<--不用別的物件當然沒有問題,能用一般的函式其實我覺得更好。因為我知道instance的方法,和一般的函式不一樣,所以我想當然的以為同樣用一個instance的方法去替換另一個instance的方法會比較容易。可能是我想錯了。聽到你說不算很難我覺得看到希望了,呵呵。 另外,比如我要替換的就是Application.ShowException這個方法, “然後用將原來的方法的thunk換成上面的那個thunk。“<-----“原來方法”是指原來的Appliatino.ShowException這個方法嗎?我不明白怎麼樣“換thunk”呢 “註: thunk由 oxE9 法方位移值 組成的 5個bytes結構,0xE9 這個機器碼表是組語之 JMP”<---這個我猜想,你是不是要jump到我們自己的MyNewException裡?這個是要用組語來實做嗎?這個在什麼時候去做呢?怎麼實做呢? C 也沒問題,主要是我不太懂這兩行的意思, 這個對我來說似乎有點深奧哦。 另外,請問MyNewException這個函式在哪裡使用呢? ===================引 用 aftcast 文 章=================== 如果方法要可以被取代,前題是你必需還是要用TApplication 來實作另一個方法。但這與你開始說的,用不同的物件的方法來取代,我想幾近不可能(不是做不到,而是要做到可能花上浩大的程式)。 如果你可以接受不使用別的物件,而是使用TApplication,那解法就有,而且算不是很難。 宣告一個類似如下的函式(非方法喔,前面沒有 類別:: ) int __fastcall MyNewException(TApplication *self, Exception* E) { //這裡搞自己的做法 } 然後用將原來的方法的thunk換成上面的那個thunk。 註: thunk由 oxE9 法方位移值 組成的 5個bytes結構,0xE9 這個機器碼表是組語之 JMP 註2: 我已對delphi的語法不熟了,用的是c 的用法,但原理是同樣的。 ===================引 用 marklai 文 章=================== 我記得好久之前曾經在網上看到過,用特別的方法,好像是用pointer,再用直接read / write memory的方法去取得和修改某個Object 的Private 內容。 如果是在一般的物件導向層面上我覺得應該是不可能去替換Method的,祇是好奇想知道有沒有網友知道方法而已。 我不熟悉組語,前面看aftcast從組語的層面說到不可能做到,我想可能真是不可能做到的。呵呵 |
中雨
一般會員 發表:8 回覆:5 積分:7 註冊:2006-07-09 發送簡訊給我 |
这个其实不难实现,替换掉方法的内存地址就可以了。
我写了一段测试代码,你看下是不是你想要的:-) [code delphi] type TTest = class public procedure DoSomething(aParam: string); end; THook = class public procedure DoSomething(aParam: string); end; TJMPCode = packed record JMP: Byte; Distance: Integer; end; procedure ReplaceMethod(AOldMethod, ANewMethod: Pointer); var AProtect: Cardinal; ANewCode: TJMPCode; begin if not VirtualProtect(AOldMethod, 5, PAGE_EXECUTE_READWRITE, AProtect) then RaiseLastOSError; ANewCode.JMP := $E9; ANewCode.Distance := PChar(ANewMethod) - PChar(AOldMethod) - 5; Move(ANewCode, AOldMethod^, 5); if not VirtualProtect(AOldMethod, 5, AProtect, AProtect) then RaiseLastOSError; end; procedure TForm1.Button1Click(Sender: TObject); var ATest: TTest; AHook: THook; begin ATest := TTest.Create; AHook := THook.Create; try ATest.DoSomething(''); ReplaceMethod(@TTest.DoSomething, @THook.DoSomething); ATest.DoSomething(''); finally ATest.Free; AHook.Free; end; end; { TTest } procedure TTest.DoSomething(aParam: string); begin ShowMessage('TTest.DoSomething!'); end; { THook } procedure THook.DoSomething(aParam: string); begin ShowMessage('THook.DoSomething!'); end; [/code] |
inungh
初階會員 發表:0 回覆:27 積分:25 註冊:2011-06-19 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |