Visual studio .NET设置相对路径

Visual studio .NET设置相对路径,visual-studio,configuration,properties,settings,Visual Studio,Configuration,Properties,Settings,我正在处理一个应用程序,其中有一个相对于我的应用程序根目录的图像文件夹。我希望能够在属性->设置设计器中指定此相对路径,例如“\Images\”。我遇到的问题是,如果Environment.CurrentDirectory通过OpenFileDialog更改,则相对路径无法解析到正确的位置。有没有办法在设置文件中指定一个路径,该路径意味着始终从应用程序目录而不是当前目录开始?我知道我总是可以将应用程序路径动态连接到相对路径的前面,但我希望我的设置属性能够自行解析。据我所知,没有允许这种类型的路径

我正在处理一个应用程序,其中有一个相对于我的应用程序根目录的图像文件夹。我希望能够在属性->设置设计器中指定此相对路径,例如“\Images\”。我遇到的问题是,如果Environment.CurrentDirectory通过OpenFileDialog更改,则相对路径无法解析到正确的位置。有没有办法在设置文件中指定一个路径,该路径意味着始终从应用程序目录而不是当前目录开始?我知道我总是可以将应用程序路径动态连接到相对路径的前面,但我希望我的设置属性能够自行解析。

据我所知,没有允许这种类型的路径解析的内置功能。最好的选择是动态确定执行目录的应用程序,并将图像路径连接到该目录。您不想使用
Environment.CurrentDirectory
,具体原因是您提到的-对于这种情况,当前目录可能并不总是正确的

找到执行程序集位置的最安全代码如下:

public string ExecutingAssemblyPath()
{
   Assembly actualAssembly = Assembly.GetEntryAssembly();
   if (this.actualAssembly == null)
   {
      actualAssembly = Assembly.GetCallingAssembly();
   }
   return actualAssembly.Location;
}
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就好了。

您正在寻找Application.ExecutablePath吗?这应该会告诉您应用程序的可执行文件在哪里,删除可执行文件名,然后将路径附加到其中。

这似乎在WinForms和ASP.NET中都有效(提供了配置文件的路径)

对于Windows和控制台应用程序,显而易见的方法是使用:

Application.StartupPath
要使用Assembly.CodeBase,如下所示:

public static string RealAssemblyFilePath()
{
   string dllPath=Assembly.GetExecutingAssembly().CodeBase.Substring(8);
   return dllPath;
}
你可以试试。但您需要参考System.Windows.Forms。如果希望类库避开表单和UI内容,这可能不是一个好主意

你可以试试这个。但是,如果在运行应用程序之前执行了“卷影复制”(如默认的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();
}
公共静态IEnumerable ParentDirs(此目录信息目录){
while(dir!=null){
收益回报率;
dir=dir.Parent;
}
}
公共静态DirectoryInfo FindDataDir(字符串relpath,程序集){
返回新文件信息((程序集).Location)
.Directory.ParentDirs()
.Select(dir=>Path.Combine(dir.FullName+@“\”,relpath))
.Where(目录.Exists)
.选择(路径=>新建目录信息(路径))
.FirstOrDefault();
}

在开发过程中,当各种构建脚本最终在目录(如
bin\x64\Release\NonsensePath\

)中粘贴内容时,查看父目录的原因是为了更易于使用,而这些目录只有在Windows窗体应用程序中才起作用。它还返回启动应用程序的可执行文件的路径,包括可执行文件名,因此您只需要去掉路径部分。由于提到Environment.CurrentDirectory,.NET应用程序并不一定意味着它是WinForms应用程序,因此我假设这是一个.NET应用程序。您可以编写命令行应用程序的.NET应用程序,这些应用程序将无法访问应用程序类。ASP.NET中是否也会出现这种情况?Chris,是的,我相信出于同样的原因也会出现这种情况。应用程序类是System.Windows.Forms程序集的一部分,ASP.NET应用程序也不能使用该程序集。您有一个
这个。
看起来像个bug-在什么情况下您实际需要该
if
语句?顺便说一句,请注意,如果概念调用程序被运行时内联,那么
GetCallingAssembly
可能会做出令人惊讶的事情。出于这个原因,我避免使用该方法,而只需通过
类型
查找程序集。那至少是安全的。
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();
}