将非托管 dll 嵌入到托管 C# dll 中
我有一个托管 C# dll,它使用 DLLImport 来使用非托管 C++ dll。 一切都运转良好。 但是,我想将该非托管 DLL 嵌入我的托管 DLL 中,如 Microsoft 所解释的:
所以我将非托管 dll 文件添加到我的托管 dll 中项目,将属性设置为“嵌入式资源”并将 DLLImport 修改为
[DllImport("Unmanaged Driver.dll, Wrapper Engine, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null",
CallingConvention = CallingConvention.Winapi)]
: “Wrapper Engine”是我的托管 DLL 的程序集名称 “Unmanaged Driver.dll”是非托管 DLL
当我运行时,我得到:
访问被拒绝。 (HRESULT 异常:0x80070005 (E_ACCESSDENIED))
我从 MSDN 和 http://blogs.msdn.com/suzcook/ 看到这应该是可能的...
I have a managed C# dll that uses an unmanaged C++ dll using DLLImport. All is working great.
However, I want to embed that unmanaged DLL inside my managed DLL as explain by Microsoft there:
So I added the unmanaged dll file to my managed dll project, set the property to 'Embedded Resource' and modify the DLLImport to something like:
[DllImport("Unmanaged Driver.dll, Wrapper Engine, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null",
CallingConvention = CallingConvention.Winapi)]
where
'Wrapper Engine' is the assembly name of my managed DLL
'Unmanaged Driver.dll' is the unmanaged DLL
When I run, I get:
Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
I saw from MSDN and from http://blogs.msdn.com/suzcook/ that's supposed to be possible...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您在初始化期间自行将非托管 DLL 提取到临时目录,并在使用 P/Invoke 之前使用 LoadLibrary 显式加载它,则可以将非托管 DLL 嵌入为资源。 我已经使用了这个技术并且效果很好。 正如迈克尔所说,您可能更愿意将其作为单独的文件链接到程序集,但将所有内容都放在一个文件中具有其优点。 这是我使用的方法:
You can embed the unmanaged DLL as a resource if you extract it yourself to a temporary directory during initialization, and load it explicitly with LoadLibrary before using P/Invoke. I have used this technique and it works well. You may prefer to just link it to the assembly as a separate file as Michael noted, but having it all in one file has its advantages. Here's the approach I used:
这是我的解决方案,它是 JayMcClellan 答案的修改版本。 将以下文件保存到 class.cs 文件中。
Here is my solution, which is a modified version of JayMcClellan's answer. Save the file below into a class.cs file.
我不知道这是可能的 - 我猜测 CLR 需要在某处提取嵌入的本机 DLL(Windows 需要有一个文件供 DLL 加载它 - 它无法从原始内存加载图像),无论在哪里它正在尝试执行该过程没有权限的操作。
SysInternals 的进程监视器之类的东西可能会为您提供线索,如果问题是创建 DLL 文件失败...
更新:
啊...现在我已经能够阅读 Suzanne Cook 的文章(该页面之前没有出现在我面前),请注意,她并不是在谈论嵌入本机 DLL 作为托管 DLL 内的资源,而不是作为链接资源 - 本机 DLL 仍然需要是文件系统中自己的文件。
请参阅http://msdn.microsoft.com/en-us/library/xawyf94k。 aspx,其中显示:
这似乎是将元数据添加到程序集中,导致本机 DLL 在逻辑上成为程序集的一部分(即使它实际上是一个单独的文件)。 因此,诸如将托管程序集放入 GAC 之类的操作将自动包含本机 DLL 等。
I wasn't aware this is possible - I'd guess that the CLR needs to extract the embedded native DLL somewhere (Windows needs to have a file for the DLL to load it - it cannot load an image from raw memory), and wherever it's trying to do that the process does not have permission.
Something like Process Monitor from SysInternals might give you a clue if the pronblem is that creating the DLL file is failing...
Update:
Ah... now that I've been able to read Suzanne Cook's article (the page didn't come up for me before), note that she is not talking about embedding the native DLL as a resource inside the managed DLL, but rather as a linked resource - the native DLL still needs to be its own file in the file system.
See http://msdn.microsoft.com/en-us/library/xawyf94k.aspx, where it says:
What this seems to do is add metadata to the assembly that causes the native DLL to logically be part of the assembly (even though it's physically a separate file). So things like putting the managed assembly into the GAC will automatically include the native DLL, etc.
您可以尝试 Costura.Fody。 文档称,它能够处理非托管文件。 我只将它用于托管文件,它的作用就像一个魅力:)
You can try Costura.Fody. Documentation says, that it's able to handle unmanaged files. I only used it for managed files, and it works like a charm :)
人们还可以将 DLL 复制到任何文件夹,然后调用 SetDllDirectory 到该文件夹。 则无需调用 LoadLibrary。
One could also just copy the DLLs to any folder, and then call SetDllDirectory to that folder. No call to LoadLibrary is needed then.