Win32 App插件如何将其DLL加载到自己的目录中 [英] how can a Win32 App plugin load its DLL in its own directory

查看:220
本文介绍了Win32 App插件如何将其DLL加载到自己的目录中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码是使用Visual Studio 8以C ++编写的特定应用程序的插件。它使用来自外部提供程序的两个DLL。不幸的是,我的插件无法启动,因为没有找到DLL(我把它们放在与插件本身相同的目录中)。

My code is a plugin for a specific Application, written in C++ using Visual Studio 8. It uses two DLL from an external provider. Unfortunately, my plugin fails to start because the DLLs are not found (I put them in the same directory as the plugin itself).

当我手动移动或复制DLL到主机应用程序目录,然后插件加载正常。对于最终用户来说,这种移动被认为是不可接受的麻烦,我正在寻找一种让我的插件透明地加载其DLL的方法。我可以做什么?

When I manually move or copy the DLLs to the host application directory, then the plugin loads fine. This moving was deemed unacceptably cumbersome for the end user, and I am looking for a way for my plugin to load its DLLs transparently. What can I do?

相关详细信息:


  • 主机应用程序插件是位于主机应用程序所授权的目录中。该目录不在DLL搜索路径中,我没有控制它。

  • 该插件本身打包为插件目录的子目录,持有插件代码本身,也可以是任何与插件相关联的资源(例如图像,配置文件...)。我控制那个子目录里面叫做bundle,而不是它的所在。

  • 该应用程序的通用插件安装习惯是为最终用户将插件包复制到插件目录。

此插件是插件的Macintosh版本的端口。在Mac上没有问题,因为每个二进制包含自己的动态库搜索路径,我根据需要设置我的插件二进制文件。要在Mac上设置它只需要在Xcode IDE中进行项目设置。这就是为什么我希望在Visual Studio中类似的东西,但我找不到任何相关的。此外,Visual Studio的帮助是什么,而且也不是Google。

This plugin is a port from the Macintosh version of the plugin. On the Mac there is no issue because each binary contains its own dynamic library search path, which I set as I needed to for my plugin binary. To set that on the Mac simply involves a project setting in the Xcode IDE. This is why I would hope for something similar in Visual Studio, but I could not find anything relevant. Moreover, Visual Studio's help was anything but, and neither was Google.

可能的解决方法是我的代码明确告诉Windows哪里可以找到DLL,但是我不知道如何,无论如何,由于我的代码甚至没有启动,没有机会这样做。

A possible workaround would be for my code to explicitly tell Windows where to find the DLL, but I don't know how, and in any case, since my code is not even started, it hasn't got the opportunity to do so.

作为一名Mac开发人员,我意识到我可能要求一些非常基本的东西。如果是这样的话,我很抱歉,但是我已经用尽了头发了。

As a Mac developer, I realize that I may be asking for something very elementary. If such is the case, I apologize, but I have run out of hair to pull out.

推荐答案

你不是要求一些非常小的东西Windows只是不支持你想要的。

You are not asking for something very elementary. Windows simply does not support what you want.

您可以选择解决此问题:

You have some options to work around this issue:


  • 创建两个DLL。你的插件实现dll,静态地链接到你需要的任何其他DLL。还有一个由托管应用程序加载的简单外观dll。外观dll调用SetDllDirectory然后LoadLibrary加载您的实现dll与所需的搜索路径,然后,对于每个插件导出函数,它实现一个存根功能,使用GetProcAddress直接传递给您的实现dll。 li>
  • Create two DLLs. Your plugin implementation dll, that statically links against whatever other dlls you need. And a simple "facade" dll that is loaded by the hosting app. The facade dll gets to call SetDllDirectory then LoadLibrary to load your implementation dll with the required search path, and then, for each plugin exported function, it implements a stub function that uses GetProcAddress to just pass the call straight to your implementation dll.

如果插件接口很复杂,但是您使用的dll界面不是,那么:

If the plugin interface is complicated, but the dll interface you are using is not, then:


  • 放弃并使用LoadLibrary(使用显式路径)和GetProcAddress访问您的卫星dll的功能。疼痛。

  • Give up and just use LoadLibrary (with an explicit path) and GetProcAddress to access the functionality in your satellite dll(s). Pain.

最终的选择是Windows程序员记录最少,最不了解的。基本上我们使用Windows版本的技术构建来支持.NET:并排程序集。不要害怕并排组合非常简单的是一个常规的旧版本,但附带一个.manifest文件,提供了一些额外的信息。

The final option is the least documented and most badly understood by windows programmers. Basically we use the windows version of a technology built to support .NET: Side by Side assemblies. Don't be frightened. A "Side by Side assembly" is very simply a regular old dll, but with a accompanying .manifest file that provides some extra information about it.

我们想要这样做的原因是通过SxS技术链接的dll的搜索顺序与常规dll搜索顺序不同: - 即 - 在搜索c:\windows\WinSxS ,Windows将搜索与引用dll的DLL相同的文件夹,而不是exe的文件夹。

The reason we want to do this is the search order for dlls that are linked in via the SxS technology is different to the regular dll search order :- Namely - after searching c:\windows\WinSxS, windows will search the same folder as the dll that references the dll, NOT the folder of the exe.

从您的插件dll的所有卫星DLL的清单开始需要链接到它们并创建一个程序集。这意味着:创建一个.manifest文件与一堆文件=节点。你需要给大会一个名字。让我们称之为MyAssembly。

Start by taking an inventory of all the satellite dlls your plugin dll needs to link to, and create an "assembly" from them. Which means: create a .manifest file with a bunch of file= nodes. You need to give the assembly a name. Lets call it "MyAssembly".

在dll的文件夹中创建文件MyAssembly.manifest,其内容类似于以下内容:(列出您需要的每个dll包含)

Create the file "MyAssembly.manifest" in your dll's folder, with contents similar to the following: (listing each of the dlls you need to include)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="MyAssembly" processorArchitecture="*" type="win32" version="1.0.0.1"/>
    <file name="firstrequireddll.dll"/>
    <file name="2ndrequireddll.dll"/>
</assembly>

现在,这是您的程序集清单。我们已经完成了一半。

Now, thats your assembly manifest. We are half done.

接下来的一半是实际获取你的dll来使用程序集,为了做到这一点,你需要添加一个清单资源到你的Dll文件。该清单最终需要包含以下内容: -

The next half is to actually get your dll to use the assembly, and to do that you need to add a manifest resource to your Dll file. That manifest ultimately needs to contain the following content :-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="MyAssembly" version="1.0.0.1" processorArchitecture="*"/>
        </dependentAssembly>
    </dependency>
</assembly>






显然应用程序清单(这是一个令人困惑的名称嵌入在一个dll中)也被允许使用一个< file> 节点,所以可能跳过创建一个程序集,然后与


Apparently application manifests (which is a confusing name when embedded in a dll), are also allowed to use a <file> node, so it might be possible to skip creating an assembly, and just go with

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <file name="firstrequireddll.dll"/>
    <file name="2ndrequireddll.dll"/>
</assembly>

作为dll的清单。我没有玩过这个迭代,所以我不知道如何改变正常的dll搜索路径(如果有的话)。

as the dll's manifest. I havn't toyed with that iteration yet, so Im not sure how that alters the normal dll search path (if at all).

在不了解开发环境的情况下,很难知道如何向dll添加清单。如果您正在编辑.rc文件并手动输入清单,请知道在Dll中,要使用的资源ID为2,而不是1,通常用于exe示例。

Without knowing your development environment, its hard to know how to advise you how to add a manifest to a dll. If you are editing a .rc file and entering the manifest by hand, know that in Dlls the resource id to use is 2, not 1, which it typically used in exe examples.

如果您使用的是DevStudio 2005或更高版本,则可以使用一个方便的#pragma指令,使所有奇迹中的所有内容都具有正确的ID,并在正确的位置。

If you are using DevStudio 2005 or higher, there is a handy #pragma directive that will make everything magically have the correct id's and be in the correct places.

如果项目设置为默认值,VS2005及以上版本将自动生成并根据需要嵌入清单。这个#pragma将在生成的清单中添加额外的程序集依赖项
: -

If the project settings are on their defaults, VS2005 and up will automatically generate, and embed a manifest as appropriate. this #pragma will add additional assembly dependencies to the generated manifest :-

#if _MSC_VER >= 1400 // VS2005 added this directive
#pragma comment(linker, \
    "\"/manifestdependency:type='Win32' "\
    "name='Company.Product.Subsystem' "\
    "version='6.0.0.0' "\
    "processorArchitecture='*' "\
    "language='*'\"")
#endif

这篇关于Win32 App插件如何将其DLL加载到自己的目录中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆