获取动态加载程序集的位置

4

假设我有一个应用程序:C:\MyPrograms\App.exe

这个应用程序不引用library.dll。App.exe可以动态加载程序集。

假设DLL的路径是C:\MyPrograms\DLLs\library.dll

无论我尝试什么方法,我都可以获取执行程序(App.exe)的路径。

GetExecutingAssembly()

GetEntryAssembly()

AppDomain.CurrentDomain.BaseDirectory

是否有一种方法可以获取动态加载的DLL的位置?对于该示例,所有内容都只返回App.exe的位置。

编辑1: 重述OP ...

MyApp.exe可以通过传递DLL的路径来调用任何DLL。用户可以将此DLL放在任何地方。排除硬编码路径或类似方法。

我想做的是能够获取动态加载的DLL的当前位置。即为了处理错误,我想能够将错误日志写入与DLL相同的目录中。

我找到并尝试了一些方法来获取加载的DLL所在的位置,但这要么返回调用程序集(MyApp.exe)的目录,要么根本没有返回。


能获取到路径还是不能获取到路径? - Muhammad Saqlain
听起来你想处理 AssemblyResolve 事件... - Heretic Monkey
假设您正在记录错误,您如何检测错误源自哪个 dll?您能编写一段代码示例来说明此功能吗?在需要路径的行中,只需放置 var path = MagicFunctionThatGetsPath(sourceDll),我想知道您是如何确定 sourceDll 并且该对象的类型是什么。 - Scott Chamberlain
在被调用的 DLL 中,我会处理错误。从调用应用程序中,有一个功能可以让用户输入程序集的路径,无论您将其放在哪里。然后,稍后,这个调用应用程序会获取您输入的路径并尝试加载 DLL。一旦 DLL 被加载,我只想能够检测到它所在的目录...因为正如我提到的,它可以放置在任何地方,我正在寻找一种“自我感知”的功能来确定它的位置。 - CleverNameHere
我没有实际进行调用的应用程序的源代码。 - CleverNameHere
2个回答

4

System.Reflection.Assembly 类具有 Location 属性,用于获取包含清单的已加载文件的路径或 UNC 位置。因此,例如,如果您以这种方式加载程序集:

var assembly = System.Reflection.Assembly.Load(@"<assembly name>");

assembly.Location会返回您要求的内容。

对编辑1的回答:为了做到这一点

处理错误,我想能够将错误日志写入与DLL相同的目录中

您可以

  1. 将程序集加载到应用程序域并订阅AppDomain.UnhandledException,在其中可以放置错误日志记录代码。该代码将知道当前域及其基本目录。
  2. 在调用程序集方法时传递某种上下文,并在日志记录逻辑中使用它。如果您只在一个线程中调用程序集方法,则可以是线程上下文。

DLL 的路径未知(当然我知道我放在哪里)。但是调用应用程序被设计为接受 DLL 的路径,用户可以将 DLL 放置在任何位置。我也没有调用应用程序的源代码。当我试图在将要被动态调用的 DLL 中使用 assembly.Location 时,它返回空值。 - CleverNameHere
在这个问题中,我们有“可以动态加载程序集”的说法。有几种方法可以做到这一点https://msdn.microsoft.com/en-us/library/25y1ya39(v=vs.110).aspx。但无论如何,应用程序都应该引用已加载的程序集实例。或者,“可以动态加载程序集”是指其他什么? - Vasyl Zvarydchuk
调用应用程序确实有某种引用。问题在于,到目前为止,无论我尝试了什么,我只能获取调用应用程序的目录。我想找到一种方法,在动态加载的 DLL 中,获取它当前所在的目录,以便我可以做一些类似将日志写入相同位置或查找配置文件之类的事情。无论 DLL 在 Windows 中放置在哪里,我都在寻找一种获取其当前位置的方法。就像当它被加载时,将当前目录存储在字符串或其他东西中。 - CleverNameHere
请在您的代码问题部分添加加载程序集的代码,以便更清楚地了解您的情况。 - Vasyl Zvarydchuk
我稍微改了一下我的问题 - 但是我没有调用这些DLL的应用程序的源代码。如果这就是你想问的。 - CleverNameHere
哦,这改变了事情。当然你不能获取程序集的位置。我也会更正我的答案。 - Vasyl Zvarydchuk

0
如果您在动态加载的程序集内部,其中定义了一个名为MyDynLoadObject的类,则可以执行以下操作:
Assembly assem = Assembly.GetAssembly(typeof(MyDynLoadObject));

编辑:另一种方法:

public class MyDynLoadObject
{
    public MyDynLoadObject()
    {

      Assembly assem = this.GetType().Assembly;

    }
}

assem.Location 属性返回空值。我将获取该属性的代码放在了要动态调用的 DLL 内部。 - CleverNameHere
@CleverNameHere:奇怪——这对我来说是有效的。请查看我的编辑。 - user1562155

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接