2012-01-06 64 views
3

我有我目前利用COM類包裝C#調用非託管DLL。編組在通過ComInterop C#非託管的DLL而無需註冊DLL

[ComImport(), Guid("75E81043-CAD5-11D3-800D-00105A5E2FA0")] 
public class MyObject { } 

[ComImport(), Guid("75E81042-CAD5-11D3-800D-00105A5E2FA0"), 
InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface MyInterface 
{ 
    string EncryptString([In, MarshalAs(UnmanagedType.BStr)] string bstrOrginal);  
} 

然後調用:

MyInterface obj = (MyInterface)new MyObject(); 
string crypt = obj.EncryptString("something"); 

這工作,返回值是如我所料。但是,它要求該DLL註冊regsvr32。

我正在尋找一種方式來做到這一點,而無需REGSVR32的要求。最好,只需要有一個可用的DLL的副本。值得注意的是,我有非受管dll的來源,並且有必要修改它。

向正確的方向推,將不勝感激。

+1

這可能有所幫助:http://msdn.microsoft.com/en-us/library/windows/desktop/ms694515(v=vs.85).aspx – 2012-01-06 01:18:23

+0

我有很多的閱讀工作要做,但我會試試這個。謝謝。 – Jon 2012-01-06 01:56:23

回答

3

我自己也想做同樣的事情。正如吉姆所說,有可能獲得DllRegisterServer的地址並稱之爲,但仍然會用各種條目修改您的註冊表。如果您不想這樣做(例如,您可能沒有必要的權限來寫入註冊表),那麼還有另一種方法。

任何DLL,它容納一個或多個過程中的COM對象必須暴露DllGetClassObject功能。此函數用於獲取用於創建COM對象的COM類工廠的實例。你需要做的是:

  1. 加載庫(DLL)的容納所需的COM對象
  2. 找到DllGetClassObject功能
  3. 呼叫DllGetClassObject,傳遞所需的COM對象的CLSID,這將返回一個IClassFactory實例。
  4. 調用類工廠的CreateInstance方法以獲取COM對象的實例。
  5. 將返回的對象轉換爲您希望使用的接口。

請注意,有這種方法的龍 - 這是相當低的水平。如果您遇到任何問題,您將遇到訪問衝突異常或更糟糕的情況。 (例如,你的接口聲明必須與COM接口完全匹配)。

我已經在gist中包含了一些示例代碼,如果您想要這樣做,您可能會喜歡使用它。

使用此代碼會是這個樣子:

// Load the library. You dispose this after you are finished with 
// all of your COM objects. 
var library = new LibraryModule(); 
library.Load("mylibrary.dll"); or whatever your dll is called 

var clsid = new Guid("75E81043-CAD5-11D3-800D-00105A5E2FA0"); 

var myObject = (MyInterface)ComHelper.CreateInstance(library, clsid); 

只是注意,如果處置LibraryModule的對象,那麼這將卸載DLL。根據您的需要,您可能只需將值分配給靜態字段,以便在程序的整個生命週期中都存在。

+0

這正是我所希望的。謝謝。 – Jon 2012-01-06 17:59:37

+0

你好。感謝您提供非常有趣的解決方案。但是,當我嘗試使用您的代碼時,它失敗,說DllGetClassObject不存在於加載的dll中。我加載的DLL是一個.net 4程序集與「註冊COM互操作」選中並使用正確的(我猜)屬性的接口和類。能否請你幫忙? – Elias 2012-06-24 00:45:31

1

如果你的DLL必須是一個COM對象,那麼它必須進行註冊。此註冊不需要由regsvr32執行。所有regsvr32都會加載DLL,獲取DllRegisterServer的地址並將其稱爲它。 DllRegisterServer將必要的條目添加到註冊表以便應用程序使用該對象。

如果你的DLL不需要是一個COM對象,你可以修改它簡單地導出功能(S),你需要和對調用它(它們)。

+0

PInvoke方法會很好,除了dll api幾乎沒有我的例子那麼簡單。我的問題更多是因爲它必須通過外部方法進行註冊...... Boo的建議可能是我最終走向的方式。 – Jon 2012-01-06 01:56:05

+0

不太準確。有[註冊免費COM](http://msdn.microsoft.com/en-us/library/ms973913.aspx)這樣的事情,可能只是爲此而設計的。 – ssube 2012-01-06 02:11:55

2

您需要設置您的非託管DLL用於免註冊COM。有一個非常完整的walkthrough here,有很多例子。除其他外,它涉及使用清單指向文件,並行程序集和一些互操作程序。

在演練中一個重要的注意的是,報名時需客戶端的初始設置,但不晚。