我正在开发一个应用程序,其中我有一个相对于我的应用程序根目录的图像文件夹。我希望能够在 Properties -> Settings 设计器中指定这个相对路径,例如。“\图片\”。我遇到的问题是在 Environment.CurrentDirectory 通过 OpenFileDialog 更改的情况下,相对路径无法解析到正确的位置。有没有办法在设置文件中指定一个路径,该路径意味着始终从应用程序目录而不是当前目录开始?我知道我总是可以动态地将应用程序路径连接到相对路径的前面,但我希望我的 Settings 属性能够自行解析。
6 回答
据我所知,没有允许这种类型的路径解析的内置功能。您最好的选择是动态确定应用程序执行目录并将您的图像路径连接到它。由于您提到的原因,您不想Environment.CurrentDirectory
专门使用 - 当前目录对于这种情况可能并不总是正确的。
我发现找到执行程序集位置的最安全的代码是:
public string ExecutingAssemblyPath()
{
Assembly actualAssembly = Assembly.GetEntryAssembly();
if (this.actualAssembly == null)
{
actualAssembly = Assembly.GetCallingAssembly();
}
return actualAssembly.Location;
}
您在寻找 Application.ExecutablePath 吗?这应该告诉您应用程序的可执行文件在哪里,删除可执行文件名称,然后将您的路径附加到它。
2个选项:
- 使用该设置的代码可以针对当前执行程序集的目录解析该设置。
- 您可以创建自己的类型,将其序列化为相对于正在执行的程序集的字符串,并具有完整路径的访问器,该路径将针对当前正在执行的程序集的目录进行解析。
代码示例:
string absolutePath = Settings.Default.ImagePath;
if(!Path.IsPathRooted(absolutePath))
{
string root = Assembly.GetEntryAssembly().Location;
root = Path.GetDirectoryName(root);
absolutePath = Path.Combine(root, absolutePath);
}
这段代码的好处是它允许在您的设置中使用完全限定的路径或相对路径。如果您需要相对于不同程序集的路径,您可以更改您使用的程序集的位置 -GetExecutingAssembly()
将为您提供程序集的位置以及您正在运行的代码,GetCallingAssembly()
如果您使用选项 2 会很好。
这似乎在 WinForms 和 ASP.NET 中都有效(提供配置文件的路径):
new System.IO.FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile).Directory;
对于 Windows 和控制台应用程序,显而易见的方法是使用:
Application.StartupPath
我建议你使用Assembly.CodeBase,如下图:
public static string RealAssemblyFilePath()
{
string dllPath=Assembly.GetExecutingAssembly().CodeBase.Substring(8);
return dllPath;
}
您可以尝试Application.ExecutablePath。但是您需要参考 System.Windows.Forms。如果您希望您的类库避开表单和 UI 内容,这可能不是一个好主意。
您可以尝试Assembly.GetExecutingAssembly().Location。但是,如果您在运行应用程序之前以某种方式执行“影子复制”(如默认的 NUnit 行为),那么此属性将返回影子复制位置,而不是真实的物理位置。
最好的方法是实现一个调用 Assembly 对象的 CodeBase 属性的函数,并去掉字符串中不相关的部分。
我使用以下两种方法来帮助解决这个问题:
public static IEnumerable<DirectoryInfo> ParentDirs(this DirectoryInfo dir) {
while (dir != null) {
yield return dir;
dir = dir.Parent;
}
}
public static DirectoryInfo FindDataDir(string relpath, Assembly assembly) {
return new FileInfo((assembly).Location)
.Directory.ParentDirs()
.Select(dir => Path.Combine(dir.FullName + @"\", relpath))
.Where(Directory.Exists)
.Select(path => new DirectoryInfo(path))
.FirstOrDefault();
}
当各种构建脚本最终将内容粘贴在bin\x64\Release\NonsensePath\
.