Come si ottiene la directory di progetto corrente dal codice C # quando si crea un'attività MSBuild personalizzata?


133

Invece di eseguire un programma esterno con il suo percorso hardcoded, vorrei ottenere l'attuale Project Dir. Sto chiamando un programma esterno utilizzando un processo nell'attività personalizzata.

Come potrei farlo? AppDomain.CurrentDomain.BaseDirectory mi dà solo la posizione di VS 2008.

Risposte:


112

Puoi provare uno di questi due metodi.

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

string startupPath = Environment.CurrentDirectory;

Dimmi, quale ti sembra migliore


85
Questi due punti sopra ti indirizzano alla directory bin, quindi se hai ad esempio una directory bin per l'intera soluzione, ti indirizzerà lì e NON alla directory del tuo progetto (o due livelli SOTTO la directory del tuo progetto)
matcheek

16
Entrambe le soluzioni non funzioneranno come previsto quando si utilizza Test Explorer.
Gucu,

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 per Directory.GetParent (), quindi non otteniamo la directory \ bin \ Debug :)
Eystein Bye

5
Cosa succede se utilizziamo una CPU di destinazione personalizzata? Ad esempio, se imposto la mia build su x64 di destinazione, crea un'altra cartella tra quelle.
Samir Aguiar,

3
Questa è la risposta corretta La risposta accettata restituisce il percorso alla directory bin, che NON è la directory del progetto.
pookie,

La risposta di @ pookie è ricorsivamente sbagliata per il mio caso. Questo mi sta dando la cartella * / {project} / bin, quindi ho bisogno di concatenare un .parent.
Capitano Prinny,

1
Funziona bene e questa dovrebbe essere la risposta accettata
Ashok kumar Ganesan,

42

Se un progetto è in esecuzione su un IIS express, Environment.CurrentDirectorypotrebbe indicare dove si trova IIS Express (il percorso predefinito sarebbe C: \ Programmi (x86) \ IIS Express ), non dove risiede il progetto.


Questo è probabilmente il percorso di directory più adatto per vari tipi di progetti.

AppDomain.CurrentDomain.BaseDirectory

Questa è la definizione MSDN.

Ottiene la directory di base che il resolver di assiemi utilizza per sondare gli assiemi.


21
9 anni dopo e qualcuno ha davvero la vera risposta.
Jeff Davis,

AppDomain non è disponibile in .NET Core. Dovresti fare qualcosa del genere. System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors ();
Latenza

Oltre a ciò, è possibile utilizzare Visual Studio SDK e ottenere la posizione dal layout di configurazione della soluzione utilizzando DTE2.
Latenza

2
@Latency c'è un progetto WPF core 3 .net
Alexander

Sì, ho letto le specifiche. Niente come 3,0 è sicuro. Lo uso da allora. Molto soddisfatto. Penso di aver pubblicato questo pre 3.0 quindi grazie per il chiarimento.
Latenza

18

Questo ti darà anche la directory di progetto spostandoti di due livelli dalla directory di esecuzione corrente (questo non restituirà la directory di progetto per ogni build, ma questa è la più comune).

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

Naturalmente vorrai contenerlo all'interno di una sorta di logica di convalida / gestione degli errori.


IMO questo è il metodo più flessibile. Sto usando questo da test unitari e test di integrazione, il cui percorso è in realtà più profondo di una cartella.
Soleil - Mathieu Prévot,

Questo mi sta dando il root drive per qualche motivo.
Capitano Prinny,

10

Se vuoi sapere qual è la directory in cui si trova la tua soluzione, devi fare questo:

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

Se lo lasci solo con il GetCurrrentDirectory()metodo, otterrai la cartella di build indipendentemente dal fatto che tu stia eseguendo il debug o rilasciando. Spero che questo aiuto! Se dimentichi le convalide sarebbe così:

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

5

Lo stavo cercando anch'io. Ho un progetto che esegue HWC e mi piacerebbe tenere il sito Web fuori dalla struttura dell'app, ma non voglio tenerlo nella directory di debug (o rilascio). FWIW, la soluzione accettata (e anche questa) identifica solo la directory in cui è in esecuzione l'eseguibile.

Per trovare quella directory, ho usato

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

5

Basato sulla risposta di Gucu112 , ma per l'applicazione .NET Core Console / Window, dovrebbe essere:

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

Sto usando questo in un progetto xUnit per un'applicazione .NET Core Window.


4

Un altro modo per farlo

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

Se si desidera ottenere il percorso della cartella bin

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

Forse ci sono modi migliori =)


4

Ancora un'altra soluzione imperfetta (ma forse un po 'più vicina alla perfezione di alcune delle altre):

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

Questa versione restituirà la cartella dei progetti correnti anche se il progetto corrente non è il fileStartup Project adatto alla soluzione.

Il primo difetto di questo è che ho saltato tutto il controllo degli errori. Questo può essere risolto abbastanza facilmente, ma dovrebbe essere un problema solo se stai memorizzando il tuo progetto nella directory principale per l'unità o stai usando un junction nel tuo percorso (e quel junction è un discendente della cartella della soluzione) quindi questo scenario è improbabile . Non sono del tutto sicuro che Visual Studio possa comunque gestire una di queste configurazioni.

Un altro (più probabile) problema che potresti incontrare è che il nome del progetto deve corrispondere al nome della cartella per il progetto per poterlo trovare.

Un altro problema che potresti avere è che il progetto deve trovarsi nella cartella della soluzione. Questo di solito non è un problema, ma se hai usato l' Add Existing Project to Solutionopzione per aggiungere il progetto alla soluzione, questo potrebbe non essere il modo in cui è organizzata la tua soluzione.

Infine, se l'applicazione modificherà la directory di lavoro, è necessario memorizzare questo valore prima di farlo perché questo valore è determinato in relazione alla directory di lavoro corrente.

Ovviamente, tutto ciò significa anche che non è necessario modificare i valori predefiniti per le opzioni ' Build-> Output patho Debug-> Working directorydei progetti nella finestra di dialogo delle proprietà del progetto.


4

Prova questo, è semplice

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

4

Questa soluzione funziona bene per me, su Develop e anche su server TEST e PROD con ASP.NET MVC5 tramite C # :

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

Se è necessaria la directory di progetto nel file di configurazione del progetto, utilizzare:

$(ProjectDir)

3

Dopo aver finalmente finito di lucidare la mia prima risposta riguardo a noi di stringhe pubbliche per ricavarne una risposta, mi sono reso conto che probabilmente avresti potuto leggere un valore dal registro per ottenere il risultato desiderato. A quanto pare, quel percorso era ancora più breve:

Innanzitutto, è necessario includere lo spazio dei nomi Microsoft.Win32 in modo da poter lavorare con il registro:

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

Ecco il codice principale:

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

Una nota su questa risposta:

Sto usando Visual Studio 2008 Professional Edition. Se si utilizza un'altra versione (ad esempio 2003, 2005, 2010; ecc.), Potrebbe non essere necessario modificare la parte "versione" della stringa SubKey (ad es. 8.0, 7.0; ecc.).

Se usi una delle mie risposte e se non è chiedere troppo, vorrei sapere quale dei miei metodi hai usato e perché. In bocca al lupo.

  • dm

3

Ho avuto una situazione simile, e dopo Googles infruttuosi, ho dichiarato una stringa pubblica, che modifica un valore di stringa del percorso di debug / rilascio per ottenere il percorso del progetto. Un vantaggio dell'utilizzo di questo metodo è che, poiché utilizza la directory del progetto currect, non importa se si sta lavorando da una directory di debug o da una directory di rilascio:

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

Saresti quindi in grado di chiamarlo quando vuoi, usando solo una linea:

string MyProjectDir = DirProject();

Questo dovrebbe funzionare nella maggior parte dei casi.


3

Usa questo per ottenere la directory del progetto (ha funzionato per me):

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

Ho usato la seguente soluzione per completare il lavoro:

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

2

Provare:

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

Questa soluzione diversa dalle altre tiene conto anche di possibili build x86 o x64.


Questa soluzione è quasi disponibile anche per i nuovi file csproj in cui TargetFramework è incluso nel percorso.
Glenn Watson,

1
Per il nuovo formato di stile .netcore ho avuto il nuovo Regex (@ "\\ bin (\\ x86 | \\ x64)? \ (Debug | Release) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson,

1

La migliore soluzione

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

Altra soluzione

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

Provalo, AppDomain.CurrentDomain.BaseDirectory ha funzionato per me sul progetto passato, ora ottengo la cartella di debug .... la BUONA risposta selezionata NON FUNZIONA !.

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

Se vuoi davvero assicurarti di ottenere la directory del progetto di origine, indipendentemente dal percorso di output del bin impostato su:

  1. Aggiungi una riga di comando dell'evento pre-build (Visual Studio: Proprietà progetto -> Eventi build):

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

  2. Aggiungi il ProjectDirectory.txtfile al Resources.resx del progetto (se non esiste ancora, fai clic con il pulsante destro del mouse sul progetto -> Aggiungi nuovo elemento -> File delle risorse)

  3. Accesso dal codice con Resources.ProjectDirectory.

-1

Funziona su VS2017 con configurazioni MSBuild Core SDK.

È necessario NuGet nei pacchetti EnvDTE / EnvDTE80.

Non utilizzare COM o interoperabilità. niente .... spazzatura !!

 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

Ti darà la directory del progetto.


77
veramente? Penso che ti manchi un genitore
sean il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.