2010-04-22 77 views
0

編輯:在c中訪問一個com對象的vtable#

我試圖在.net類中封裝第三方com對象,同時修復它的錯誤。我希望能夠通過調用我自己的方法來替換com對象的vtable中的一個方法,從而提供該方法的無bug實現。

我試圖在非常基本的東西上測試這一點,但給出下面的答案我完全是錯誤的軌道。通過創建一個對我的com對象的引用,我假設我已經創建了一個運行時可調用的包裝器,有什麼方法可以獲得一個指向真正的基礎com對象的指針嗎?


我試圖訪問一個com對象的vtable在內存中,並越來越無處。

從我讀到的內容中,com對象的前4個字節應該是指向vtableptr的指針,而vtableptr又是指向vtable的指針。

儘管我不確定我是否期望在這個com對象的槽7中找到我的測試方法,但我已經試過了它們,沒有看起來像我的函數的地址。

如果任何人都可以對此示例進行必要的更改以使其正常工作(目的只是嘗試通過訪問com對象的vtable並在其中找到該行的方法來調用Tester類上的Test方法) )我會很感激。

我知道這是罕見的,任何人都需要做,但請接受我確實需要做的相當類似,並已預先考慮的替代方案

感謝

[ComVisible(true)] 
public class Tester 
{ 
    public void Test() 
    { 
     MessageBox.Show("Here"); 
    } 

} 

public delegate void TestDelegate(); 

private void main() 
{ 

    Tester t = new Tester(); 

    GCHandle objectHandle = GCHandle.Alloc(t); 

    IntPtr objectPtr = GCHandle.ToIntPtr(objectHandle); 

    IntPtr vTable = (IntPtr)Marshal.ReadInt32(objectPtr); 

    IntPtr vTablePtr = (IntPtr)Marshal.ReadInt32(vTable); 

    IntPtr functionPtr = (IntPtr)Marshal.ReadInt32(vTablePtr, 7 * 4); // 7 may be incorrect but i have tried many different values 

    TestDelegate func = (TestDelegate)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(TestDelegate)); 

    func(); 

    objectHandle.Free(); 
} 

回答

3

你完全在這個錯誤的軌道上。 t對象是而不是的一個COM接口指針,它是一個.NET對象引用。直到非託管代碼創建CCW(COM可調用包裝器),纔會創建COM接口指針(及其v-表)。它具有爲非託管代碼,CLR互操作層不允許託管代碼創建CCW。

保持這個線程移動的唯一方法是解釋你爲什麼要這麼做。

+0

感謝漢斯的你的解釋,我絕對沒有在這裏深度,這節省了我浪費時間的東西,永遠不會工作。我已更新我的問題,並提供更多信息,以防有人提供建議 – 2010-04-22 22:46:29

0

@Hans有一點。 +1。

這是在任何形式的解決方案,只是一個解釋:

如果你真的想訪問一個COM對象,爲什麼不創建一個簡單的COM DLL,然後嘗試訪問它?

互操作工作的方式有兩種:

  1. .NET組件調用COM組件
  2. COM組件調用.NET組件

當.NET調用COM它需要Runtime Callable Wrapper(Visual Studio將創建爲你)和COM Callable Wrapper(需要裝飾.NET成員ComVisible)爲後者。

要從.NET訪問COM對象的vtable,它需要是您正在訪問的真正COM組件,否則它只是@Hans提到的對象引用。