当创建自定义MSBuild任务时,如何从C#代码中获取当前项目目录?

233

我希望获取当前项目目录而不是在代码中直接写入外部程序路径。我通过自定义任务中的进程来调用外部程序。

如何实现呢?使用AppDomain.CurrentDomain.BaseDirectory仅会返回VS 2008的位置。


嘿 Sean,我觉得在问题标题中提到 MSBuild 是一个转移注意力的话题。这个问题似乎是关于如何通过编程获取项目目录,也就是源代码目录的问题(所有答案都理解为此)。我想编辑一下问题以反映这一点,但我想先确认一下你的意见。 - Mike Nakis
嗨,Mike。提到ProjectDir应该就足够了。但幸运的是,我提到了“自定义构建任务”,因为我已经找到了这个项目,并且看起来需要获取/Scripts文件夹以压缩js文件的任务。奇怪的是,路径仍然是硬编码的。 - sean
在这种情况下,我认为“自定义构建任务”甚至可以在问题结尾处的“为了更好的理解,这是我想要做的事情:”注释中提到。但是,由于现在我不清楚你想要什么,所以我不会干涉。 - Mike Nakis
28个回答

5
using System;
using System.IO;

// Get the current directory and make it a DirectoryInfo object.
// Do not use Environment.CurrentDirectory, vistual studio 
// and visual studio code will return different result:
// Visual studio will return @"projectDir\bin\Release\netcoreapp2.0\", yet 
// vs code will return @"projectDir\"
var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

// On windows, the current directory is the compiled binary sits,
// so string like @"bin\Release\netcoreapp2.0\" will follow the project directory. 
// Hense, the project directory is the great grand-father of the current directory.
string projectDirectory = currentDirectory.Parent.Parent.Parent.FullName;

你确定调用 Parent 三次就足够了吗?或许再加一次? - Mike Nakis

5
string projPath = Path.GetFullPath(@"..\..\..\");
Console.WriteLine(projPath);

这对我来说一直很有效。你也可以试试。


应该是答案。如此简单明了,直截了当。 - BoundForGlory

5

我也在寻找这个。我有一个运行HWC的项目,并且我希望将网站保留在应用程序树之外,但我不想将其保存在调试(或发布)目录中。有关参考价值,接受的解决方案(以及这个解决方案)仅识别可执行文件所在的目录。

为了找到该目录,我一直在使用

string startupPath = System.IO.Path.GetFullPath(".\\").

4
另一种方法是这样做。
string startupPath = System.IO.Directory.GetParent(@"./").FullName;

如果您想获取 bin 文件夹的路径

string startupPath = System.IO.Directory.GetParent(@"../").FullName;

也许有更好的方法 =)

4

又一个不完美的解决方案(但或许比其他一些更接近完美):

    protected static string GetSolutionFSPath() {
        return System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName;
    }
    protected static string GetProjectFSPath() {
        return String.Format("{0}\\{1}", GetSolutionFSPath(), System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
    }

这个版本将返回当前项目的文件夹,即使当前项目不是解决方案的启动项目

首先,我跳过了所有的错误检查。这很容易修复,但只有在您将项目存储在驱动器的根目录中或在路径中使用连接(并且该连接是解决方案文件夹的后代)时才会出现问题,因此这种情况不太可能发生。我不确定Visual Studio是否能够处理这两种设置中的任何一种。

另一个(更有可能的)问题是,项目名称必须与项目的文件夹名称匹配才能找到它。

你可能遇到的另一个问题是,项目必须在解决方案文件夹内。通常这不是问题,但如果您使用添加现有项目到解决方案选项将项目添加到解决方案中,则解决方案的组织方式可能不是这种方式。

最后,如果您的应用程序将修改工作目录,则应在执行此操作之前存储此值,因为该值相对于当前工作目录确定。

当然,这也意味着您不能更改项目的默认值生成->输出路径调试->工作目录选项在项目属性对话框中。


4

试试这个,它很简单

HttpContext.Current.Server.MapPath("~/FolderName/");

3

在我终于完成了有关使用公共字符串来得出答案的第一个答案之后,我意识到你可以从注册表中读取值以获得所需的结果。事实证明,这条路线甚至更短:

首先,您必须包括Microsoft.Win32命名空间,以便可以使用注册表:

using Microsoft.Win32;    // required for reading and / or writing the registry

以下是主要代码:

RegistryKey Projects_Key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\9.0", false);
string DirProject = (string)Projects_Key.GetValue(@"DefaultNewProjectLocation");

关于这个答案的说明:
我正在使用Visual Studio 2008专业版。如果你使用另一个版本(例如2003、2005、2010等),那么你可能需要修改SubKey字符串中的“version”部分(例如8.0、7.0等)。
如果你使用了我的答案,并且如果不介意的话,我想知道你使用了我的哪些方法以及为什么使用它们。祝好运。
  • dm

3

我使用了以下解决方案来完成工作:

string projectDir =
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\.."));

3

好的,虽然有点晚了,但我对许多项目中发现的所有可能性感到非常恼火:

  • bin/Debug
  • bin/x86/Debug
  • bin/Debug/net5.0-windows
  • ...

拜托了...我只需要一个一行代码(或几乎是)来处理测试单元中的一些文件; 我需要在过去、现在和(也许是未来的)所有项目中使用它。

所以,如果项目名称与其所在的相对文件夹名称相同

  1. 使用程序集名称选择项目根文件夹名称;
  2. 向后返回,直到找到该名称为止。

代码示例:

string appName = Assembly.GetExecutingAssembly().GetName().Name;
var dir = new DirectoryInfo(Environment.CurrentDirectory);
while (dir.Name != appName) {
  dir = Directory.GetParent(dir.FullName);
}
return dir.FullName;

3

尝试:

var pathRegex = new Regex(@"\\bin(\\x86|\\x64)?\\(Debug|Release)$", RegexOptions.Compiled);
var directory = pathRegex.Replace(Directory.GetCurrentDirectory(), String.Empty);

这个解决方案与其他解决方案不同,还考虑了可能的x86或x64构建。


这个解决方案对于包含TargetFramework路径的新csproj文件也几乎到位了。 - Glenn Watson
2
对于新的 .netcore 格式,我使用了新的正则表达式:Regex(@"\bin(\x86|\x64)?\(Debug|Release)(\[a-zA-Z0-9.]*)?$", RegexOptions.Compiled)。 - Glenn Watson

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