我有一个非托管DLL,我目前正在使用COM Class Wrapper从C#调用。
[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");
这样可行,返回值正如我所料。但是,它要求使用regsvr32注册dll。
我正在寻找一种方法,无需使用regsvr32。优选地,通过仅具有可用的dll的副本。值得注意的是,我有非托管dll的源代码,并且必要时可以修改它。
非常感谢正确方向的推动。
答案 0 :(得分:3)
我想自己做同样的事情。正如Jim提到的那样,可以获取DllRegisterServer
的地址并将其调用,但仍然会使用各种条目修改您的注册表。如果您不想这样做(例如,您可能没有必要的权限来写入注册表),那么还有另一种方法。
包含一个或多个进程内COM对象的任何DLL都必须公开DllGetClassObject
函数。此函数用于获取用于创建COM对象的COM类工厂的实例。你需要做的是:
DllGetClassObject
功能DllGetClassObject
,向其传递所需COM对象的CLSID,这将返回IClassFactory
实例。CreateInstance
方法以获取COM对象的实例。请注意,有这种方法的龙 - 它是相当低的水平。如果您遇到任何问题,您将遇到访问冲突异常或更糟。 (例如,您的接口声明必须与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。根据您的需要,您可以将值分配给静态字段,以使其在程序的生命周期内存在。
答案 1 :(得分:2)
您需要为免注册COM设置非托管DLL。有一个非常完整的walkthrough here,有很多例子。除其他外,它涉及使用清单指向文件,并排程序集和一些互操作。
演练中的一个重要注意事项是,客户端的初始设置需要注册,但不能在以后注册。
答案 2 :(得分:1)
如果您的DLL必须是COM对象,则必须注册它。此注册不需要由regsvr32执行。所有regsvr32都会加载DLL,获取DllRegisterServer的地址并将其调用。 DllRegisterServer将必要的条目添加到注册表中,以便应用程序使用该对象。
如果你的DLL不需要是一个COM对象,你可以修改它只是导出你需要的函数并调用它(它们)。