Özel bir MSBuild görevi oluştururken geçerli proje dizinini C # kodundan nasıl alırsınız?


134

Yolu kodlanmış harici bir programı çalıştırmak yerine, mevcut Proje Yönergesini almak istiyorum. Özel görevde bir işlemi kullanarak harici bir programı arıyorum.

Bunu nasıl yaparım? AppDomain.CurrentDomain.BaseDirectory bana sadece VS 2008'in yerini veriyor.

Yanıtlar:


112

Bu iki yöntemden birini deneyebilirsiniz.

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

string startupPath = Environment.CurrentDirectory;

Söyle bana hangisi sana daha iyi geliyor


86
Yukarıdaki bu ikisi sizi bin dizinine işaret eder, bu nedenle örneğin tüm çözümünüz için bir bin dizininiz varsa, bu sizi oraya yönlendirecektir ve proje dizininize (veya proje dizininizin altında iki seviye)
DEĞİL

16
Test Gezgini kullanılırken her iki çözüm de beklendiği gibi çalışmayacaktır.
Gucu112

265
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
Directory.GetParent () için +1, böylece \ bin \ Debug dizinini
alamayız

5
Ya özel bir hedef CPU kullanırsak? Örneğin, yapımı hedef x64 olarak ayarlarsam, bunların arasında başka bir klasör oluşturur.
Samir Aguiar

3
Bu doğru cevap. Kabul edilen yanıt, proje dizini OLMAYAN bin dizininin yolunu döndürür.
pookie

@ pookie'nin cevabı davam için yinelemeli olarak yanlış. Bu bana * / {project} / bin klasörünü veriyor, bu yüzden bir .parent birleştirmem gerekiyor.
Captain Prinny

1
İyi çalışıyor ve kabul edilen cevap bu olmalı
Ashok kumar Ganesan

42

Bir proje bir IIS express üzerinde çalışıyorsa, Environment.CurrentDirectoryIIS Express'in bulunduğu yere işaret edebilir (varsayılan yol C: \ Program Files (x86) \ IIS Express olacaktır ), projenizin bulunduğu yere değil.


Bu, muhtemelen çeşitli projeler için en uygun dizin yoludur.

AppDomain.CurrentDomain.BaseDirectory

Bu, MSDN tanımıdır.

Derleme çözümleyicisinin derlemeleri araştırmak için kullandığı temel dizini alır.


21
9 yıl sonra ve birisinin aslında gerçek cevabı var.
Jeff Davis

.NET Core'da AppDomain yoktur. Bunun gibi bir şey yapmanız gerekecek. System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = bağlam => InvokeBatchProcessors ();
Gecikme

Bunun yanı sıra, Visual Studio SDK'yı kullanabilir ve DTE2'yi kullanarak çözüm yapılandırma düzeninden konumu alabilirsiniz.
Gecikme

2
@Latency bir .net çekirdek 3 WPF projesinde var
Alexander

Evet, özellikleri okudum. Kesinlikle 3,0 gibi bir şey yok. O zamandan beri kullanıyorum. Çok memnun. Sanırım bu 3.0'ı yayınladım, açıklama için teşekkürler.
Gecikme

18

Bu aynı zamanda geçerli yürütme dizininden iki seviye yukarı giderek size proje dizinini verecektir (bu, her derleme için proje dizinini döndürmez, ancak bu en yaygın olanıdır).

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

Elbette bunu bir çeşit doğrulama / hata işleme mantığının içine dahil etmek isteyebilirsiniz.


IMO bu en esnek yöntemdir. Bunu, aslında bir klasörden daha derin olan birim testlerinden ve entegrasyon testlerinden kullanıyorum.
Soleil - Mathieu Prévot

Bu bana bir sebepten dolayı kök sürücüyü veriyor.
Kaptan Prinny

10

Çözümünüzün bulunduğu dizinin ne olduğunu bilmek istiyorsanız, bunu yapmanız gerekir:

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

Yalnızca GetCurrrentDirectory()yöntemle izin verirseniz, hata ayıklama veya yayınlama yapsanız da derleme klasörünü alırsınız. Umarım bu yardımcı olur! Doğrulamaları unutursanız, bu şöyle olur:

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

5

Ben de bunu arıyordum. HWC çalıştıran bir projem var ve web sitesini uygulama ağacının dışında tutmak istiyorum, ancak bunu hata ayıklama (veya sürüm) dizininde tutmak istemiyorum. FWIW, kabul edilen çözüm (ve bu da) yalnızca yürütülebilir dosyanın çalıştığı dizini tanımlar.

Bu dizini bulmak için kullanıyorum

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

5

Dayanarak Gucu112 cevabı , ancak .NET Çekirdek Konsol / Pencere uygulama için, bu olmalıdır:

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

Bunu bir .NET Core Pencere Uygulaması için bir xUnit projesinde kullanıyorum.


4

Bunu yapmanın başka bir yolu

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

Bin klasörüne giden yolu almak istiyorsanız

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

Belki daha iyi bir yol vardır =)


4

Yine başka bir kusurlu çözüm (ama belki de mükemmele diğerlerinden biraz daha yakın):

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

Mevcut proje çözüm için olmasa bile bu sürüm mevcut projelerin klasörünü döndürecektir Startup Project.

Bununla ilgili ilk kusur, tüm hata kontrollerini atlamış olmamdır. Bu yeterince kolay düzeltilebilir, ancak yalnızca projenizi sürücünün kök dizininde depoluyorsanız veya yolunuzdaki bir bağlantı noktasını kullanıyorsanız (ve bu bağlantı, çözüm klasörünün soyundan geliyorsa) bir sorun olacaktır, bu nedenle bu senaryo olası değildir . Yine de Visual Studio'nun bu kurulumlardan herhangi birini halledebileceğinden tam olarak emin değilim.

Karşılaşabileceğiniz başka bir (daha olası) sorun, proje adının , projenin bulunabilmesi için klasör adıyla eşleşmesi gerektiğidir .

Sahip olabileceğiniz bir diğer sorun da projenin çözüm klasörünün içinde olması gerektiğidir. Bu genellikle bir sorun değildir, ancak Add Existing Project to Solutionprojeyi çözüme ekleme seçeneğini kullandıysanız, çözümünüzün organize edilme şekli bu olmayabilir.

Son olarak, eğer uygulama çalışma dizinini değiştirecekseniz, bunu yapmadan önce bu değeri saklamalısınız çünkü bu değer mevcut çalışma dizinine göre belirlenir.

Tabii ki, bu aynı zamanda proje özellikleri iletişim kutusundaki projelerinizin Build-> Output pathveya Debug-> Working directoryseçeneklerinin varsayılan değerlerini değiştirmemeniz gerektiği anlamına da gelir .



4

Bu çözüm benim için, Develop üzerinde ve ayrıca C # aracılığıyla ASP.NET MVC5 ile TEST ve PROD sunucularında iyi çalışıyor :

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

Proje yapılandırma dosyasında proje dizinine ihtiyacınız varsa şunu kullanın:

$(ProjectDir)

3

Bir cevap bulmak için herkese açık dizelerin bize ilişkin ilk cevabımı nihayet bitirdikten sonra, istediğiniz sonucu elde etmek için muhtemelen kayıt defterinden bir değer okuyabileceğinizi anladım. Görünüşe göre bu rota daha da kısaydı:

İlk olarak, kayıt defteriyle çalışabilmek için Microsoft.Win32 ad alanını eklemelisiniz:

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

İşte ana kod:

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

Bu cevapla ilgili bir not:

Visual Studio 2008 Professional Edition kullanıyorum. Başka bir sürüm kullanıyorsanız (ör. 2003, 2005, 2010; vb.), Alt Anahtar dizesinin (ör. 8.0, 7.0; vb.) 'Sürüm' bölümünü değiştirmeniz gerekebilir.

Cevaplarımdan birini kullanırsanız ve sorulacak kadar fazla değilse, o zaman hangi yöntemlerimi ve neden kullandığınızı bilmek isterim. İyi şanslar.

  • dm

3

Benzer bir durum yaşadım ve sonuçsuz Googles'tan sonra, proje yolunu elde etmek için hata ayıklama / yayın yolunun bir dize değerini değiştiren bir genel dize ilan ettim. Bu yöntemi kullanmanın bir yararı, geçerli projenin dizinini kullandığından, bir hata ayıklama dizininden veya yayın dizininden çalışıp çalışmamanızın önemli olmamasıdır:

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

Daha sonra, sadece bir hat kullanarak istediğiniz zaman arayabileceksiniz:

string MyProjectDir = DirProject();

Bu çoğu durumda çalışmalıdır .


3

Proje dizinini almak için bunu kullanın (benim için çalıştı):

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

İşi yapmak için aşağıdaki çözümü kullandım:

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

2

Deneyin:

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

Bu, diğerlerinden farklı bir çözümdür ve olası x86 veya x64 derlemesini de hesaba katar.


Bu çözüm, TargetFramework'ün yola dahil edildiği yeni csproj dosyaları için de neredeyse oradadır.
Glenn Watson

1
Yeni .netcore stili formatı için yeni Regex (@ "\\ bin (\\ x86 | \\ x64)? \ (Hata Ayıklama | Yayın) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson

1

En iyi çözüm

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

Diğer çözüm

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

Test edin, AppDomain.CurrentDomain.BaseDirectory benim için geçmiş projede çalıştı, şimdi hata ayıklama klasörünü alıyorum .... seçilen İYİ cevap sadece ÇALIŞMIYOR !.

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

Kaynak proje dizinini aldığınızdan gerçekten emin olmak istiyorsanız, bin çıktı yolu neye ayarlanmış olursa olsun:

  1. Önceden oluşturulmuş bir olay komut satırı ekleyin (Visual Studio: Proje özellikleri -> Oluşturma Olayları): Add a pre-build event command line (Visual Studio: Project properties -> Build Events):

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

  2. ProjectDirectory.txtDosyayı projenin Resources.resx'ine ekleyin (henüz mevcut değilse, sağ tıklayın proje -> Yeni öğe ekle -> Kaynaklar dosyası)

  3. İle koddan erişim Resources.ProjectDirectory.

-1

Bu, VS2017 w / SDK Core MSBuild yapılandırmalarında çalışır.

EnvDTE / EnvDTE80 paketlerinde NuGet yapmanız gerekir.

COM veya birlikte çalışma kullanmayın. bir şey .... çöp !!

 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

Size proje dizinini verecektir.


77
Gerçekten mi? Sanırım bir
Ebeveyni
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.