代码之家  ›  专栏  ›  技术社区  ›  sean

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

  •  94
  • sean  · 技术社区  · 16 年前

    我不想运行一个硬编码路径的外部程序,而是希望得到当前的项目目录。我正在使用自定义任务中的进程调用外部程序。

    我该怎么做?appdomain.currentdomain.basedirectory只给出了vs 2008的位置。

    19 回复  |  直到 6 年前
        1
  •  94
  •   Iralda Mitro    16 年前

    你可以试试这两种方法中的一种。

    string startupPath = System.IO.Directory.GetCurrentDirectory();
    
    string startupPath = Environment.CurrentDirectory;
    

    告诉我,你觉得哪个更好

        2
  •  199
  •   JohnB    6 年前
    using System;
    using System.IO;
    
    // This will get the current WORKING directory (i.e. \bin\Debug)
    string workingDirectory = Environment.CurrentDirectory;
    // or: Directory.GetCurrentDirectory() gives the same result
    
    // This will get the current PROJECT directory
    string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;
    
        3
  •  16
  •   nh43de    9 年前

    这还将通过从当前执行目录向上导航两个级别来为您提供项目目录(这不会为每个生成返回项目目录,但这是最常见的)。

    System.IO.Path.GetFullPath(@"..\..\")
    

    当然,您希望在某种验证/错误处理逻辑中包含此内容。

        4
  •  8
  •   abel406    12 年前

    如果您不想知道解决方案所在的目录,则需要执行以下操作:

     var parent = Directory.GetParent(Directory.GetCurrentDirectory()).Parent;
                if (parent != null)
                {
                    var directoryInfo = parent.Parent;
                    string startDirectory = null;
                    if (directoryInfo != null)
                    {
                        startDirectory = directoryInfo.FullName;
                    }
                    if (startDirectory != null)
                    { /*Do whatever you want "startDirectory" variable*/}
                }
    

    如果你只让 GetCurrrentDirectory() 方法,无论您是在调试还是在释放,都将获取build文件夹。希望能帮上忙!如果您忘记了验证,将是这样的:

    var startDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;
    
        5
  •  8
  •   hina10531    6 年前

    如果项目正在IIS Express上运行,则 Environment.CurrentDirectory 可能指向IIS Express所在的位置(默认路径为 C:\程序文件(x86)\IIS Express ,而不是项目所在的位置。


    这可能是最适合各种项目的目录路径。

    AppDomain.CurrentDomain.BaseDirectory
    

    这是msdn定义。

    获取程序集冲突解决程序用于探测程序集的基目录。

        6
  •  5
  •   Brett    13 年前

    我也在找这个。我有一个运行hwc的项目,我想让网站远离应用程序树,但我不想把它保存在debug(或release)目录中。fwiw,接受的解决方案(以及这个解决方案)只标识运行可执行文件的目录。

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

    string startupPath = System.IO.Path.GetFullPath(".\\").
    
        7
  •  4
  •   Tret    9 年前

    另一种方法

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

    如果要获取bin文件夹的路径

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

    也许还有更好的办法=)

        8
  •  4
  •   krowe    9 年前

    另一个不完美的解决方案(但可能比其他一些更接近完美):

        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);
        }
    

    此版本将返回 当前项目' 即使当前项目不是 Startup Project 解决方案。

    第一个缺陷是我跳过了所有的错误检查。这可以很容易地解决,但只有当您将项目存储在驱动器的根目录中或在路径中使用连接(该连接是解决方案文件夹的后代)时,这才是一个问题,因此这种情况不太可能发生。我不完全确定Visual Studio是否可以处理这些设置。

    您可能遇到的另一个(更可能的)问题是项目名称 必须 匹配要找到的项目的文件夹名称。

    您可能遇到的另一个问题是项目必须在解决方案文件夹中。这通常不是问题,但是如果你使用了 Add Existing Project to Solution 选项将项目添加到解决方案中,那么这可能不是解决方案的组织方式。

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

    当然,这也意味着你不能改变项目的默认值。 Build -gt; Output path Debug -gt; Working directory 项目属性对话框中的选项。

        9
  •  3
  •   digitalmythology    13 年前

    在我最后完成了我关于美国公共字符串的第一个答案的润色以得到一个答案之后,我意识到你可能可以从注册表中读取一个值来获得你想要的结果。事实证明,这条路线甚至更短:

    首先,必须包含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等),那么您可能不需要修改子项字符串的“版本”部分(即8.0、7.0等)。

    如果你用我的一个答案,如果不是问太多,那么我想知道你用了我的哪种方法,为什么。祝你好运。

    • 糖尿病
        10
  •  3
  •   Rob    12 年前

    我也遇到过类似的情况,在没有结果的Google之后,我声明了一个公共字符串,它修改了调试/发布路径的字符串值以获取项目路径。使用此方法的一个好处是,由于它使用了当前项目的目录,因此如果您使用的是调试目录或发布目录,则不重要:

    public string DirProject()
    {
        string DirDebug = System.IO.Directory.GetCurrentDirectory();
        string DirProject = DirDebug;
    
        for (int counter_slash = 0; counter_slash < 4; counter_slash++)
        {
            DirProject = DirProject.Substring(0, DirProject.LastIndexOf(@"\"));
        }
    
        return DirProject;
    }
    

    然后,您可以随时调用它,只需使用一行:

    string MyProjectDir = DirProject();
    

    这个应该可以用 病例。

        11
  •  3
  •   perror    9 年前

    使用此项获取项目目录(适用于我):

    string projectPath = 
        Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
    
        12
  •  3
  •   Hardeep Singh    6 年前

    试试这个,很简单

    HttpContext.Current.Server.MapPath("~/FolderName/");
    
        13
  •  2
  •   zwcloud    6 年前

    基于 Gucu112's answer ,但对于.NET核心控制台/窗口应用程序,它应该是:

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

    我在.NET核心窗口应用程序的XUnit项目中使用这个。

        14
  •  1
  •   zwcloud    6 年前

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

    string projectDir =
        Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\.."));
    
        15
  •  1
  •   David Desmaisons    6 年前

    尝试:

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

    这与其他解决方案不同,也考虑了可能的x86或x64版本。

        16
  •  0
  •   Eduardo Chávez    6 年前

    最佳解决方案

    string PjFolder1 =
        Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).
            Parent.Parent.FullName;
    

    其他解决方案

    string pjFolder2 = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(
                    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)));
    

    测试一下,appdomain.currentdomain.basedirectory在过去的项目中为我工作过,现在我得到了debug文件夹……选定的好答案不起作用!.

    //Project DEBUG folder, but STILL PROJECT FOLDER
    string pjDebugFolder = AppDomain.CurrentDomain.BaseDirectory;
    
    //Visual studio folder, NOT PROJECT FOLDER
    //This solutions just not work
    string vsFolder = Directory.GetCurrentDirectory();
    string vsFolder2 = Environment.CurrentDirectory;
    string vsFolder3 = Path.GetFullPath(".\\");   
    
    //Current PROJECT FOLDER
    string ProjectFolder = 
        //Get Debug Folder object from BaseDirectory ( the same with end slash)
        Directory.GetParent(pjDebugFolder).
        Parent.//Bin Folder object
        Parent. //Project Folder object
        FullName;//Project Folder complete path
    
        17
  •  0
  •   FunctorSalad    6 年前

    如果您真的想确保获得源项目目录,不管bin输出路径设置为什么:

    1. 添加预生成事件命令行(Visual Studio:项目属性->生成事件):

      echo $(MSBuildProjectDirectory) > $(MSBuildProjectDirectory)\Resources\ProjectDirectory.txt

    2. 添加 ProjectDirectory.txt 文件到项目的resources.resx(如果该文件尚不存在,请右键单击项目->添加新项->资源文件)

    3. 从代码访问 Resources.ProjectDirectory .
        18
  •  -1
  •   Latency    6 年前

    这适用于VS2017 w/sdk核心msbuild配置。

    您需要使用envdte/envdte80包。

    不要使用COM或Interop。任何东西…垃圾!!

     internal class Program {
        private static readonly DTE2 _dte2;
    
        // Static Constructor
        static Program() {
          _dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
        }
    
    
        private static void FindProjectsIn(ProjectItem item, List<Project> results) {
          if (item.Object is Project) {
            var proj = (Project) item.Object;
            if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
              results.Add((Project) item.Object);
            else
              foreach (ProjectItem innerItem in proj.ProjectItems)
                FindProjectsIn(innerItem, results);
          }
    
          if (item.ProjectItems != null)
            foreach (ProjectItem innerItem in item.ProjectItems)
              FindProjectsIn(innerItem, results);
        }
    
    
        private static void FindProjectsIn(UIHierarchyItem item, List<Project> results) {
          if (item.Object is Project) {
            var proj = (Project) item.Object;
            if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
              results.Add((Project) item.Object);
            else
              foreach (ProjectItem innerItem in proj.ProjectItems)
                FindProjectsIn(innerItem, results);
          }
    
          foreach (UIHierarchyItem innerItem in item.UIHierarchyItems)
            FindProjectsIn(innerItem, results);
        }
    
    
        private static IEnumerable<Project> GetEnvDTEProjectsInSolution() {
          var ret = new List<Project>();
          var hierarchy = _dte2.ToolWindows.SolutionExplorer;
          foreach (UIHierarchyItem innerItem in hierarchy.UIHierarchyItems)
            FindProjectsIn(innerItem, ret);
          return ret;
        }
    
    
        private static void Main() {
          var projects = GetEnvDTEProjectsInSolution();
          var solutiondir = Path.GetDirectoryName(_dte2.Solution.FullName);
    
          // TODO
          ...
    
          var project = projects.FirstOrDefault(p => p.Name == <current project>);
          Console.WriteLine(project.FullName);
        }
      }
    
        19
  •  -8
  •   brian kitcehner    14 年前

    directory.getParent(directory.getcurrentdirectory()).parent.parent.parent.fullname

    会给你项目目录。