我试图把我的头脑集中在平台调用服务、组件对象模型等概念上,但是我发现很难理解什么是什么,什么是不同的职责。我一直在学习代码,其中包含以下内容:
[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
internal static extern object SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, ref Guid riid);
[ComImport]
[Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IShellItem据我所知,前者导入一个创建shell项的函数,后者导入创建它们所需的类型(接口)。
我不明白的是为什么其中一个使用DllImport而另一个使用ComImport。它们各自的文档中没有说明使用哪种方法的文档,文档也没有为COM对象提供GUID。我唯一的猜测是,区别因素是前者是一个函数,后者是一个接口。
发布于 2017-10-15 14:26:34
IShellItem是一个COM接口。COM与调用外部代码的DllImport方法相比一般不太好。COM更有吸引力,接口声明了一整套可以调用的方法,就像在C#语言中使用interface关键字所做的那样。
在实践中,您总是需要一个实现接口的具体类,无论是在C#中还是在COM中。在COM术语中称为coclass,这些类完全隐藏在视图中。通常是用C++编写的,这是一种通常支持互操作很差的语言,但是COM提供了一种协议,使得几乎任何语言都可以调用C++代码。隐藏类实现是关键的要素,完全隐藏了讨厌的小C++细节。与构造函数一样,内存管理、继承、对象布局、异常、从一种语言移植到另一种语言的功能非常差。
您总是需要使用工厂函数来创建类对象。一种通用的方法就是您正在讨论的方法,CoCreateInstance()助手函数是非常常用的。您只需要提供CLSID,也就是coclass的guid。然后,COM运行时负责查找实现coclass的EXE或DLL,加载它并获得IClassFactory接口以获得创建的对象。必须注册COM服务器是至关重要的,注册表中的键告诉它哪个可执行文件负责该工作。
还有第二种方法,一个由库显式导出的工厂函数,如SHCreateItemFromParsingName()。它避免了我在上一段中提到的所有goo。DirectX并不常见,但并不少见,它是使用工厂函数(如D3D11CreateDevice() )的库的另一个很好的例子。与coclass相比,微软更喜欢工厂函数并不是很明显,除了可能不鼓励从脚本语言使用这样的库。
如果接口是由coclass实现的,那么只需使用new IShellItem()来创建对象。请注意创建接口实例的奇妙之处,这在C#中是没有意义的。但对COM客户端代码却是有意的。C#编译器在引擎盖下生成代码,以使对象工厂管道正常运行。
但是,由于SHCreateItemFromParsingName工厂函数是从DLL导出的正常函数,与任何其他函数一样,现在需要使用DllImport来声明它。
发布于 2017-10-15 12:38:47
DllImport与ComImport无关。
DllImport从本质上定义了.NET中的函数原型,以便稍后在本机DLL中调用函数。这种类型的方法调用通常称为P/Invoke (平台调用的缩写)。
ComImport 并没有真正地导入任何东西.它是在c#中定义COM接口的手动方式,是用于自定义/ IUnknown接口或自动化不兼容类型的典型使用。
我唯一的猜测是,区别因素是前者是一个函数,后者是一个接口。
不,ComImport也可以应用到类中。
编辑:我想我看到你现在想要的东西了,见下面
有什么区别?
最后,我们有两种可能调用本机代码的方法(假设目前我们的COM示例是用本机代码编写的)。为什么有两种不同的方式?
一个很大的区别是,这些方法(或功能)是如何向世界公开或宣传的。
Windows上典型的 .dll 文件导出了.dll文件中EXPORTS表中的函数。通过在中打开DLL,您可以看到DLL中导出了哪些函数。

这包括以下内容:
PeekMessage in User32.dllDeleteFile和SHCreateItemFromParsingName in friend 32.dll现在,为了调用上面的内容,您必须使用我们已经讨论过的[DllImport]。
COM是不同的, COM类和方法不是在导出表中列出的,所以它不能用于[DllImport] /p调用它们。COM在很大程度上依赖于WindowsRegistry.com类型库或后期绑定来完成工作。
COM既可以用.EXEs实现,也可以用.DLLs实现(只是为了混淆轻轻松松的事情)。在依赖项查看器中打开COM .dll只列出所有COM服务器必须实现的COM注册/注销功能。
例如,查看mapishell.dll COM服务器( MS的一部分),我们看到(除了注册之外)没有任何东西被导出,尽管我们知道存在一些功能。

更多
如果您想了解更多关于COM工作方式的信息,请查看我的另一个答案获取更多信息。
https://stackoverflow.com/questions/46754843
复制相似问题