Як отримати поточний каталог проектів із коду C # під час створення власної задачі MSBuild?


133

Замість запуску зовнішньої програми з твердим кодом, я хотів би отримати поточний проект Dir. Я викликаю зовнішню програму, використовуючи процес у користувацькому завданні.

Як би я це зробив? AppDomain.CurrentDomain.BaseDirectory просто дає мені розташування VS 2008.

Відповіді:


112

Можна спробувати один із цих двох методів.

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

string startupPath = Environment.CurrentDirectory;

Скажіть, хто з вас здається кращим


85
Ці два вище вказують на каталог бін, тому, якщо у вас є, наприклад, один каталог бін для всього вашого рішення, він вкаже вас туди, а НЕ на каталог ваших проектів (або два рівні
ВИДЕ

16
Обидва рішення не працюватимуть, як очікувалося, при використанні Test Explorer.
Gucu112,

264
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;

25
+1 для Directory.GetParent (), тому ми не отримуємо каталог \ bin \ Debug :)
Eystein Bye

5
Що робити, якщо ми використовуємо спеціальний цільовий процесор? Наприклад, якщо я встановив мою збірку для націлювання на x64, вона створює іншу папку між ними.
Самір Агіяр

3
Це правильна відповідь. Прийнята відповідь повертає шлях до каталогу bin, який НЕ є каталогом проекту.
pookie

@ відповідь pookie рекурсивно неправильна для мого випадку. Це дає мені папку * / {project} / bin, тому мені потрібно скласти aparent.
Капітан Принні

1
Добре працюючи, і це має бути прийнята відповідь
Ашок кумар Ганесан

42

Якщо проект працює на експресі IIS, то Environment.CurrentDirectoryможе вказуватись на місце знаходження IIS Express (шлях за замовчуванням буде C: \ Program Files (x86) \ IIS Express ), а не туди, де знаходиться ваш проект.


Це, мабуть, найбільш підходящий шлях до каталогу для різних проектів.

AppDomain.CurrentDomain.BaseDirectory

Це визначення MSDN.

Отримує базовий каталог, який використовує резолютор складання для зондування для складання.


21
Через 9 років і хтось насправді має справжню відповідь.
Джефф Девіс

В .NET Core немає AppDomain. Вам би довелося зробити щось подібне. System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors ();
затримка

Крім того, ви можете використовувати SDK Visual Studio і отримати розташування з макета конфігурації рішення за допомогою DTE2.
Затримка

2
@Latency є в .net core 3 WPF-проект
Олександр

Так, я прочитав специфікації. Нічого подібного 3,0 це точно. Я з цього часу використовую. Дуже задоволений. Я думаю, що я розмістив цю попередню версію 3.0, тому дякую за уточнення.
Затримка

18

Це також дасть вам каталог проектів, перейшовши на два рівні вгору від поточного каталогу виконання (це не повертає каталог проектів для кожної збірки, але це найпоширеніший).

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

Звичайно, ви хочете містити це всередині якоїсь логіки перевірки / помилки.


ІМО це найбільш гнучкий метод. Я використовую це з одиничних тестів та інтеграційних тестів, який шлях насправді знаходиться глибше однієї папки.
Солей - Матьє Превот

Це дає мені кореневий диск з якихось причин.
Капітан Принні

10

Якщо ви хочете знати, що це каталог, де знаходиться ваше рішення, вам потрібно зробити це:

 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()методу, ви отримуєте папку збірки незалежно від того, налагоджуєте чи випускаєте. Я сподіваюся, що це допоможе! Якщо ви забудете про перевірки, було б так:

var startDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;

5

Я теж це шукав. У мене є проект, який працює з HWC, і я хотів би не захищати веб-сайт із дерева додатків, але я не хочу зберігати його в каталозі налагодження (або випуску). FWIW, прийняте рішення (і це також) лише ідентифікує каталог, у якому працює виконуваний файл.

Щоб знайти цей каталог, я використовував

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

5

На основі відповіді Gucu112 , але для програми .NET Core Console / Window, це повинно бути:

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

Я використовую це в проекті xUnit для програми .NET Core Window.


4

Ще один спосіб зробити це

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

Якщо ви хочете отримати шлях до папки бін

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

Ця версія поверне папку поточних проектів, навіть якщо поточний проект не Startup Projectє рішенням.

Перший недолік у цьому полягає в тому, що я пропустив усі перевірки помилок. Це можна виправити досить просто, але це може бути проблемою лише в тому випадку, якщо ви зберігаєте проект у кореневому каталозі для накопичувача або використовуєте перехід у своєму шляху (і цей перехід є нащадком папки рішення), тому цей сценарій малоймовірний . Я не зовсім впевнений, що Visual Studio так чи інакше може обробляти будь-яку з цих установок.

Ще одна (більш вірогідна) проблема, з якою ви можете зіткнутися, полягає в тому, що назва проекту повинна бути відповідати імені папки, щоб проект був знайдений.

Інша проблема, яка може виникнути, полягає в тому, що проект повинен знаходитися всередині папки рішення. Зазвичай це не проблема, але якщо ви використовували Add Existing Project to Solutionопцію, щоб додати проект до рішення, то це може бути не так, як ваше рішення організоване.

Нарешті, якщо ваша програма буде змінювати робочий каталог, вам слід зберегти це значення перед цим, оскільки це значення визначається відносно поточного робочого каталогу.

Звичайно, це все також означає, що ви не повинні змінювати параметри за замовчуванням для ваших проектів ' Build-> Output pathабо Debug-> Working directoryпараметри в діалоговому вікні властивостей проекту.



4

Це рішення добре працює для мене на розробці, а також на серверах TEST і PROD з ASP.NET MVC5 через C # :

var projectDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);

Якщо вам потрібен каталог проектів у файлі конфігурації проекту :

$(ProjectDir)

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 Professional Edition. Якщо ви використовуєте іншу версію (наприклад, 2003, 2005, 2010; тощо), можливо, вам не доведеться змінювати частину 'version' рядка SubKey (тобто 8.0, 7.0; і т.д.).

Якщо ви використовуєте одну з моїх відповідей, і якщо запитання не надто, я хотів би знати, який з моїх методів ви використовували і чому. Удачі.

  • дм

3

У мене була подібна ситуація, і після безрезультатних Googles я оголосив загальнодоступний рядок, який модифікує значення рядка шляху налагодження / випуску, щоб отримати проектний шлях. Перевага використання цього методу полягає в тому, що, оскільки він використовує точний каталог проекту, це не має значення, якщо ви працюєте з каталогу налагодження або каталогу випусків:

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

Це повинно працювати в більшості випадків.


3

Використовуйте це, щоб отримати каталог Project (працював для мене):

string projectPath = 
    Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

3
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;

2

Я використовував таке рішення, щоб виконати роботу:

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

2

Спробуйте:

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

Це рішення, відмінне від інших, також враховує можливі збірки x86 або x64.


Це рішення майже існує для нових файлів csproj, де TargetFramework включений у шлях.
Гленн Уотсон

1
Для нового формату стилю .netcore у мене був новий Regex (@ "\\ bin (\\ x86 | \\ x64)? \ (Налагодження | випуск) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Гленн Уотсон

1

Найкраще рішення

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 працював на мене над минулим проектом, тепер я отримую папку налагодження .... обраний ДОБРИЙ відповідь просто НЕ ПРАЦЮЄ!

//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

0

Якщо ви дійсно хочете переконатися, що ви отримуєте каталог вихідного проекту, незалежно від того, для якого шляху виводу біна встановлено:

  1. Додайте командний рядок події перед побудовою (Visual Studio: Властивості проекту -> Події збірки):

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

  2. Додайте ProjectDirectory.txtфайл до Resources.resx проекту (Якщо він ще не існує, клацніть правою кнопкою миші проект -> Додати новий елемент -> Файл ресурсів)

  3. Доступ з коду за допомогою Resources.ProjectDirectory.

-1

Це працює для VS2017 w / SDK Core MSBuild конфігурацій.

Вам потрібно NuGet в пакетах 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);
    }
  }

-6

Directory.GetParent (Directory.GetCurrentDirectory ()). Parent.Parent.Parent.Parent.FullName

Дасть вам каталог проектів.


77
справді? Я думаю, ти пропускаєш Батька
сеан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.