我是.NET用户,我的目标就像找到主执行程序集(EXE文件)目录的绝对路径一样简单。
我有几位候选人:
Assembly.GetExecutingAssembly().CodeBase
Assembly.GetExecutingAssembly().Location
AppDomain.CurrentDomain.BaseDirectory
如果要通过.NET文档判断 - 我倾向于CodeBase
。
任何人都可以用比.NET文档更具体的术语来解释这三个问题吗?举例来证明这种差异?
答案 0 :(得分:16)
我会使用GetEntryAssembly()
代替GetExecutingAssembly()
。
要了解原因,请执行以下操作:
ClassLibrary1
)添加到解决方案中,并从控制台项目中引用它。将其放入ClassLibrary1
:
namespace ClassLibrary1
{
using System;
using System.IO;
using System.Reflection;
public class Class1
{
public void GetInfo(int n)
{
Assembly asm = Assembly.GetEntryAssembly();
Console.WriteLine("[GetEntryAssembly {0}] Location:{1}", n, Path.GetDirectoryName(asm.Location));
asm = Assembly.GetExecutingAssembly();
Console.WriteLine("[GetExecutingAssembly() {0}] Location:{1}", n, Path.GetDirectoryName(asm.Location));
}
}
}
将其放入控制台的Program.cs
:
namespace ConsoleApplication4
{
using System;
using System.IO;
using System.Reflection;
using ClassLibrary1;
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.GetEntryAssembly();
Console.WriteLine("[GetEntryAssembly() 1] Location:{0}", Path.GetDirectoryName(asm.Location));
asm = Assembly.GetExecutingAssembly();
Console.WriteLine("[GetExecutingAssembly() 1] Location:{0}", Path.GetDirectoryName(asm.Location));
Class1 obj1 = new Class1();
obj1.GetInfo(2);
asm = Assembly.LoadFile(@"C:\temp\ClassLibrary1.dll");
Type t = asm.GetType("ClassLibrary1.Class1");
object obj2 = asm.CreateInstance("ClassLibrary1.Class1");
t.GetMethod("GetInfo").Invoke(obj2, new object[] { 3 });
Console.ReadKey();
}
}
}
构建解决方案,将ClassLibrary1.dll
复制到c:\temp
并运行。
正如您将看到的,GetExecutingAssembly()
可能会在某些条件下欺骗您。
最后一点,如果您的应用是Windows窗体版,则可以使用Application.ExecutablePath
。
答案 1 :(得分:12)
我不确定AppDomain.CurrentDomain.BaseDirectory
,但解释Assembly.GetExecutingAssembly().CodeBase
和Assembly.GetExecutingAssembly().Location
之间的差异in this blog post。
CodeBase是找到文件的地方的URL,而Location是实际加载文件的路径。例如,如果程序集是从Internet下载的,则其CodeBase可能以“http://”开头,但其位置可能以“C:\”开头。如果文件是影子复制的,则位置将是影子副本目录中文件副本的路径。
知道不保证为GAC中的程序集设置CodeBase也是很好的。但是,总是会为从磁盘加载的程序集设置位置。
如果您需要执行文件的真实目录,那么最好的选择是Location
。
答案 2 :(得分:8)
不幸的是,如果您使用像XenoCode postbuild这样的虚拟化,上面的所有方法都会失败。 我测试了很多方法并找到了另一个解决方案here。 我发现只有
System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe"
返回可执行文件的正确文件名。
因此,将文件名与Assembly.GetEntryAssembly().Location
的路径相结合,您将获得可执行文件的正确路径。
答案 3 :(得分:0)
来自:http://msdn.microsoft.com/en-us/library/system.reflection.assembly.codebase.aspx
<强> Assembly.CodeBase 强>
获取加载的绝对路径 包含清单的文件,使用 而是
Assembly.Location
财产。如果程序集作为一个字节加载 数组,使用Load的重载 采用字节数组的方法, 此属性返回的位置 方法的调用者,而不是 加载组件的位置。
对于AppDomain.CurrentDomain.BaseDirectory
,老实说我从实际的角度来看并不知道这些差异。
答案 4 :(得分:-3)
使用System.Linq
string MainExecutablePath= (System.Diagnostics.Process.GetProcesses().First(P =>P.MainWindowTitle == "MainExecutable'sWindowName")).MainModule.FileName.ToString();