使用C#获取解决方案文件的父文件夹路径

29

我是C#的初学者,我有一个文件夹,我正在从中读取一个文件。

我想要读取位于解决方案文件的父文件夹中的文件。我该怎么做?

string path = "";
StreamReader sr = new StreamReader(path);

如果我的文件XXX.sln位于C:\X0\A\XXX\,那么请读取位于C:\X0\A\.txt文件。


父文件是指什么? - Thilina H
.txt文件是文件类型。 - User1204501
@Leez的父文件夹。因此,它位于解决方案文件所在的文件夹上方。 - User1204501
你是指 .sln 文件夹对吧?但是你部署它然后呢? - Thilina H
如果您想要确切的解决方案文件夹,请查看以下链接: https://stackoverflow.com/a/67492470/15343165 - Mauricio U
我从Visual Studio环境中获取了路径,链接在这里:https://stackoverflow.com/a/67492470/15343165 - Mauricio U
7个回答

38

您可能更喜欢这种更通用的解决方案,它取决于通过扫描当前或选定目录的所有父目录来找到解决方案*.sln文件,并涵盖找不到解决方案目录的情况!

public static class VisualStudioProvider
{
    public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = null)
    {
        var directory = new DirectoryInfo(
            currentPath ?? Directory.GetCurrentDirectory());
        while (directory != null && !directory.GetFiles("*.sln").Any())
        {
            directory = directory.Parent;
        }
        return directory;
    }
}

使用方法:

// get directory
var directory = VisualStudioProvider.TryGetSolutionDirectoryInfo();
// if directory found
if (directory != null)
{
    Console.WriteLine(directory.FullName);
}

针对您的情况:

// resolve file path
var filePath = Path.Combine(
    VisualStudioProvider.TryGetSolutionDirectoryInfo()
    .Parent.FullName, 
    "filename.ext");
// usage file
StreamReader reader = new StreamReader(filePath);

享受吧!

现在,警告一下...你的应用程序应该是无解决方案依赖的 - 除非这是一个处理某些解决方案的个人项目,我不介意。要理解的是,你的应用程序一旦分发给用户将会居住在没有解决方案的文件夹中。现在,你可以使用一个“锚”文件。例如搜索父文件夹并检查是否存在一个空文件app.anchormySuperSpecificFileNameToRead.ext;P如果你想让我写这个方法,只要告诉我。

现在,你可能真的很享受!:D


2
迄今为止是最好的答案,因为目录输出协调随时都会发生变化,这样我们就可以始终获取解决方案文件夹而不受其他情况的影响(例如,当构建从AnyCPU更改为x86时,默认路径将从bin \ Debug更改为bin \ x86 \ Debug)。 - Rzassar

32

试一试:

string startupPath = Path.Combine(Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.Parent.FullName,"abc.txt");

// Read the file as one string. 
string text = System.IO.File.ReadAllText(startupPath);

8
只有在解决方案文件夹中进行调试时才有效。如果将exe复制到另一个位置,这将会失败。 - RvdK
7
@RvdK好的,肯定会失败。但他的问题非常具体,是关于解决方案文件的位置,请仔细阅读问题。 - Thilina H
12
有时候最好的答案是解释可能出现的问题并提供更好的答案。(尽管目前它在解决方案文件中,最好的解决方案是将文件放在与可执行文件相同的文件夹中,以避免复制等问题。) - RvdK
2
在这种情况下,使用@"....\abc.txt"会更容易得多。这也取决于项目设置,但似乎不那么复杂。 - Vitaly Filatenko
这在Visual Studio中运行良好,但在Visual Studio Code中却不行。当我使用控制台记录“startupPath”时,它只显示D:\ abc.txt。有人知道原因吗? - joekevinrayan96

9

如果你的应用程序依赖于文件路径和解决方案路径之间的关系来确定文件位置,那么我认为这是不足够的。虽然你的程序可能会在 Solution/Project/Bin/$(ConfigurationName)/$(TargetFileName) 路径下执行,但这仅适用于在Visual Studio中执行的情况。在其他场景下,这并不一定成立。

我看到两个选项:

  1. Include the file as part of your project, and in its' properties, have it copied to the output folder. You can then access the file thusly:

    string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Yourfile.txt");
    

    Note, during deployment you'll have to ensure that this file is also deployed alongside your executable.

  2. Use command line arguments to specify the absolute path to the file on startup. This can be defaulted within Visual Studio (see Project Properties -> Debug Tab -> Command line arguments". e.g:

    filePath="C:\myDevFolder\myFile.txt"
    

    There's a number of ways and libraries concerning parsing the command line. Here's a Stack Overflow answer on parsing command line arguments.


1
@User1204501,我已经看到了你的编辑。让你的程序根据解决方案目录的位置加载文本文件是在自找麻烦。 - Moo-Juice

4
我认为这就是你想要的。不过在发布时是否是个好主意还不确定。
string dir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.FullName;

需要使用 System.IO


1
只有在解决方案文件夹中调试时才有效。如果将exe文件复制到另一个位置,这将失败。 - RvdK
1
我不明白为什么会被踩。他的问题非常具体,关于解决方案文件的位置。 - stevepkr84
1
有时候最好的答案是解释会出现哪些陷阱,并提供更好的答案。 - RvdK
1
他自己说这只是一项学术练习,依赖于解决方案文件。在我看来,它并不真正涉及到实际的分发问题。 - stevepkr84

2

如果出于某些原因,您想将解决方案路径编译到您的项目中,您可以使用 T4 模板来实现。

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ parameter name="model" type="System.String" value=""#>
<#
    IServiceProvider serviceProvider = (IServiceProvider)this.Host;
    DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
#>
using System;
using System.IO;

namespace SolutionInfo
{
    public static class Paths
    {
        static string solutionPath = @"<#= Path.GetDirectoryName(dte.Solution.FullName) #>";
    }
}

我认为 Tah 只能在 Visual Studio 中工作。


1
一个小更新,以符合C# 7.0+中的null类型约定,基于@Demetris Leptos的方法:
 public static DirectoryInfo? TryGetSolutionDirectoryInfo(string? currentPath = null)
        {
            DirectoryInfo? directory = new (
                currentPath ?? Directory.GetCurrentDirectory());
            while (directory != null && !directory.GetFiles("*.sln").Any())
            {
                directory = directory.Parent;
            }
            return directory;
        }

(我本来想直接评论那个答案的,但是评论需要更多的声望才能提交。)

-1
string path = Application.StartupPath;

1
完整的命名空间是什么?我找不到它。 - Kellen Stuart
@KolobCanyon 在 System.Windows.Forms 中 - Cesario

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