Bagaimana Anda mendapatkan direktori proyek saat ini dari kode C # saat membuat tugas MSBuild kustom?

133

Alih-alih menjalankan program eksternal dengan jalurnya hardcoded, saya ingin mendapatkan Project Dir saat ini. Saya memanggil program eksternal menggunakan proses dalam tugas kustom.

Bagaimana saya melakukannya? AppDomain.CurrentDomain.BaseDirectory hanya memberi saya lokasi VS 2008.

sean
sumber

Jawaban:

112

Anda dapat mencoba salah satu dari dua metode ini.

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

string startupPath = Environment.CurrentDirectory;

Katakan padaku, mana yang menurutmu lebih baik

Iralda Mitro
sumber
85
Kedua poin di atas mengarahkan Anda ke direktori bin, jadi jika Anda memiliki, misalnya, satu direktori bin untuk seluruh solusi Anda, ia akan mengarahkan Anda ke sana dan TIDAK ke direktori proyek Anda (atau dua tingkat DI BAWAH direktori proyek Anda)
matcheek
16
Kedua solusi tidak akan berfungsi seperti yang diharapkan saat menggunakan 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;
mohammed sameeh
sumber
25
+1 untuk Directory.GetParent () jadi kami tidak mendapatkan direktori \ bin \ Debug :)
Eystein Bye
5
Bagaimana jika kita menggunakan CPU target khusus? Misalnya, jika saya menetapkan build saya ke target x64, ia membuat folder lain di antaranya.
Samir Aguiar
3
Ini jawaban yang benar. Jawaban yang diterima mengembalikan path ke direktori bin, yang BUKAN direktori proyek.
pookie
@ pookie menjawab secara rekursi salah untuk kasus saya. Ini memberi saya * / {project} / folder bin, jadi saya perlu untuk concat .tua.
Kapten Prinny
1
Bekerja dengan baik dan ini harus menjadi jawaban yang diterima
Ashok kumar Ganesan
42

Jika suatu proyek berjalan pada IIS express, Environment.CurrentDirectorybisa menunjuk ke tempat IIS Express berada (jalur default adalah C: \ Program Files (x86) \ IIS Express ), bukan ke tempat proyek Anda berada.


Ini mungkin jalur direktori yang paling cocok untuk berbagai jenis proyek.

AppDomain.CurrentDomain.BaseDirectory

Ini adalah definisi MSDN.

Mendapat direktori basis yang digunakan resolver majelis untuk menyelidiki majelis.

hina10531
sumber
21
9 tahun kemudian dan seseorang benar-benar memiliki jawaban yang sebenarnya.
Jeff Davis
Tidak ada AppDomain di .NET Core. Anda harus melakukan sesuatu seperti ini. System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors ();
Latency
Selain itu, Anda dapat menggunakan Visual Studio SDK dan mendapatkan lokasi dari tata letak konfigurasi solusi menggunakan DTE2.
Latency
2
@Latency ada dalam proyek .net core 3 WPF
Alexander
Ya, saya membaca spesifikasi. Tidak seperti 3,0 yang pasti. Saya telah menggunakannya sejak itu. Sangat tersanjung. Saya pikir saya memposting pra 3.0 ini jadi terima kasih atas klarifikasi.
Latensi
18

Ini juga akan memberi Anda direktori proyek dengan menavigasi dua tingkat dari direktori eksekusi saat ini (ini tidak akan mengembalikan direktori proyek untuk setiap bangunan, tetapi ini adalah yang paling umum).

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

Tentu saja Anda ingin memuat ini di dalam semacam logika validasi / penanganan kesalahan.

nh43de
sumber
IMO ini adalah metode yang paling fleksibel. Saya menggunakan ini dari tes unit dan tes integrasi, jalur mana yang sebenarnya lebih dalam dari satu folder.
Soleil - Mathieu Prévot
Ini memberi saya root drive untuk beberapa alasan.
Kapten Prinny
10

Jika Anda ingin tahu apa direktori tempat solusi Anda berada, Anda perlu melakukan ini:

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

Jika Anda hanya membiarkan dengan GetCurrrentDirectory()metode, Anda mendapatkan folder build tidak masalah jika Anda sedang debug atau melepaskan. Semoga bantuan ini! Jika Anda lupa validasi, maka akan menjadi seperti ini:

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

Saya juga mencari ini. Saya punya proyek yang menjalankan HWC, dan saya ingin menjaga situs web dari pohon aplikasi, tetapi saya tidak ingin menyimpannya di direktori debug (atau lepaskan). FWIW, solusi yang diterima (dan yang ini juga) hanya mengidentifikasi direktori yang dapat dijalankan.

Untuk menemukan direktori itu, saya telah menggunakan

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

Berdasarkan jawaban Gucu112 , tetapi untuk aplikasi .NET Core Console / Window, seharusnya:

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

Saya menggunakan ini dalam proyek xUnit untuk .NET Core Window Application.

zwcloud
sumber
4

Cara lain untuk melakukan ini

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

Jika Anda ingin mendapatkan path ke folder bin

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

Mungkin ada cara yang lebih baik =)

Tret
sumber
4

Namun solusi lain yang tidak sempurna (tapi mungkin sedikit lebih dekat dengan sempurna daripada yang lain):

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

Versi ini akan mengembalikan folder proyek saat ini bahkan jika proyek saat ini bukan Startup Projectuntuk solusinya.

Kelemahan pertama dengan ini adalah bahwa saya telah melewatkan semua pemeriksaan kesalahan. Itu bisa diperbaiki cukup mudah tetapi seharusnya hanya menjadi masalah jika Anda menyimpan proyek Anda di direktori root untuk drive atau menggunakan persimpangan di jalur Anda (dan persimpangan itu adalah turunan dari folder solusi) sehingga skenario ini tidak mungkin . Saya tidak sepenuhnya yakin bahwa Visual Studio dapat menangani salah satu dari pengaturan ini.

Masalah lain (lebih mungkin) yang mungkin Anda temui adalah bahwa nama proyek harus temui cocok dengan nama folder agar proyek dapat ditemukan.

Masalah lain yang mungkin Anda miliki adalah bahwa proyek tersebut harus berada di dalam folder solusi. Ini biasanya bukan masalah tetapi jika Anda telah menggunakan Add Existing Project to Solutionopsi untuk menambahkan proyek ke solusi maka ini mungkin bukan cara solusi Anda diatur.

Terakhir, jika aplikasi Anda akan memodifikasi direktori yang berfungsi, Anda harus menyimpan nilai ini sebelum melakukannya karena nilai ini ditentukan relatif terhadap direktori kerja saat ini.

Tentu saja, ini semua juga berarti bahwa Anda tidak boleh mengubah nilai default untuk opsi ' Build-> Output pathatau Debug-> Working directoryproyek Anda dalam dialog properti proyek.

Krowe
sumber
4

Coba ini, ini sederhana

HttpContext.Current.Server.MapPath("~/FolderName/");
Hardeep Singh
sumber
4

Solusi ini bekerja dengan baik untuk saya, pada Pengembangan dan juga pada server TEST dan PROD dengan ASP.NET MVC5 melalui C # :

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

Jika Anda memerlukan direktori proyek dalam penggunaan file konfigurasi proyek :

$(ProjectDir)
Jan Sršeň
sumber
3

Setelah saya akhirnya selesai memoles jawaban pertama saya tentang kami dari string publik untuk mendapatkan jawaban, saya sadar bahwa Anda mungkin bisa membaca nilai dari registri untuk mendapatkan hasil yang Anda inginkan. Ternyata, rute itu bahkan lebih pendek:

Pertama, Anda harus memasukkan namespace Microsoft.Win32 sehingga Anda dapat bekerja dengan registri:

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

Ini kode utamanya:

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

Catatan tentang jawaban ini:

Saya menggunakan Visual Studio 2008 Professional Edition. Jika Anda menggunakan versi lain, (yaitu 2003, 2005, 2010; dll.), Maka Anda mungkin harus memodifikasi bagian 'versi' dari string SubKey (yaitu 8.0, 7.0; dll).

Jika Anda menggunakan salah satu jawaban saya, dan jika tidak terlalu banyak bertanya, maka saya ingin tahu metode saya yang Anda gunakan dan mengapa. Semoga berhasil.

  • dm
digitalmythology
sumber
3

Saya memiliki situasi yang serupa, dan setelah Google tidak menghasilkan, saya mendeklarasikan string publik, yang mengubah nilai string dari jalur debug / rilis untuk mendapatkan path proyek. Manfaat menggunakan metode ini adalah karena menggunakan direktori proyek arus, tidak masalah jika Anda bekerja dari direktori debug atau direktori rilis:

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

Anda kemudian dapat memanggilnya kapan saja Anda mau, hanya menggunakan satu baris:

string MyProjectDir = DirProject();

Ini seharusnya bekerja dalam banyak kasus.

digitalmythology
sumber
3

Gunakan ini untuk mendapatkan direktori Proyek (berfungsi untuk saya):

string projectPath = 
    Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
pengguna5219877
sumber
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;
JeffreyYe_THU
sumber
2

Saya telah menggunakan solusi berikut untuk menyelesaikan pekerjaan:

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

Mencoba:

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

Ini adalah solusi yang berbeda dari yang lain juga memperhitungkan kemungkinan membangun x86 atau x64.

David Desmaisons
sumber
Solusi ini hampir ada untuk file csproj baru juga di mana TargetFramework termasuk dalam path.
Glenn Watson
1
Untuk format .netcore style baru saya punya Regex baru (@ "\\ bin (\\ x86 | \\ x64)? \ (Debug | Release) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson
1

Solusi terbaik

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

Solusi lain

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

Uji, AppDomain.CurrentDomain.BaseDirectory bekerja untuk saya di proyek sebelumnya, sekarang saya mendapatkan folder debug .... jawaban BAIK yang dipilih TIDAK BEKERJA !.

//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
Eduardo Chávez
sumber
0

Jika Anda benar-benar ingin memastikan Anda mendapatkan direktori proyek sumber, apa pun jalur keluaran bin diatur ke:

  1. Tambahkan baris perintah acara pra-bangun (Visual Studio: Properti proyek -> Buat Acara):

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

  2. Tambahkan ProjectDirectory.txtfile ke Resources.resx proyek (Jika belum ada, klik kanan proyek -> Tambahkan item baru -> file Resources)

  3. Akses dari kode dengan Resources.ProjectDirectory.
FunctorSalad
sumber
-1

Ini berfungsi pada konfigurasi VS2017 w / SDK Core MSBuild.

Anda perlu NuGet dalam paket EnvDTE / EnvDTE80.

Jangan gunakan COM atau interop. apapun .... sampah !!

 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);
    }
  }
Latensi
sumber
-6

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

Akan memberi Anda direktori proyek.

brian kitcehner
sumber
77
Betulkah? Saya pikir Anda kehilangan Orangtua
sean