2012-01-06 61 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,有很多例子。除其他外,它涉及使用清单指向文件,并行程序集和一些互操作程序。

在演练中一个重要的注意的是,报名时需客户端的初始设置,但不晚。