¿Cómo se obtiene el directorio del proyecto actual del código C # al crear una tarea personalizada de MSBuild?

133

En lugar de ejecutar un programa externo con su ruta codificada, me gustaría obtener el Dir del proyecto actual. Estoy llamando a un programa externo utilizando un proceso en la tarea personalizada.

¿Como podría hacerlo? AppDomain.CurrentDomain.BaseDirectory solo me da la ubicación de VS 2008.

sean
fuente

Respuestas:

112

Puedes probar uno de estos dos métodos.

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

string startupPath = Environment.CurrentDirectory;

Dime cual te parece mejor

Iralda Mitro
fuente
85
Estos dos puntos anteriores lo dirigen al directorio bin, por lo que si tiene, por ejemplo, un directorio bin para toda su solución, lo dirigirá allí y NO a su directorio de proyecto (o dos niveles
POR
16
Ambas soluciones no funcionarán como se espera al usar 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
fuente
25
+1 para Directory.GetParent () para que no obtengamos el directorio \ bin \ Debug :)
Eystein Bye
55
¿Qué pasa si usamos una CPU objetivo personalizada? Por ejemplo, si configuro mi compilación para apuntar a x64, crea otra carpeta entre ellas.
Samir Aguiar
3
Esta es la respuesta correcta. La respuesta aceptada devuelve la ruta al directorio bin, que NO es el directorio del proyecto.
pookie
La respuesta de @pookie es recursivamente incorrecta para mi caso. Esto me da la carpeta * / {project} / bin, así que necesito concat un .parent.
Capitán Prinny el
1
Funciona bien y esta debería ser la respuesta aceptada
Ashok kumar Ganesan
42

Si un proyecto se ejecuta en un IIS express, Environment.CurrentDirectorypodría apuntar a dónde se encuentra IIS Express (la ruta predeterminada sería C: \ Archivos de programa (x86) \ IIS Express ), no a dónde reside su proyecto.


Esta es probablemente la ruta de directorio más adecuada para varios tipos de proyectos.

AppDomain.CurrentDomain.BaseDirectory

Esta es la definición de MSDN.

Obtiene el directorio base que utiliza el solucionador de ensamblados para buscar ensamblados.

hina10531
fuente
21
9 años después y alguien realmente tiene la respuesta real.
Jeff Davis
No hay AppDomain en .NET Core. Tendrías que hacer algo como esto. System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors ();
Latencia
Además de eso, puede usar el SDK de Visual Studio y obtener la ubicación del diseño de configuración de la solución usando DTE2.
Latencia
2
@Latency hay en un proyecto .net core 3 WPF
Alexander
Sí, leí las especificaciones. Nada como 3,0 es seguro. Lo he estado usando desde entonces. Muy complacido. Creo que publiqué este pre 3.0, así que gracias por la aclaración.
Latencia del
18

Esto también le dará el directorio del proyecto al navegar dos niveles hacia arriba desde el directorio de ejecución actual (esto no devolverá el directorio del proyecto para cada compilación, pero este es el más común).

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

Por supuesto, querrá contener esto dentro de algún tipo de lógica de validación / manejo de errores.

nh43de
fuente
OMI, este es el método más flexible. Estoy usando esto de pruebas unitarias y pruebas de integración, qué ruta es realmente más profunda de una carpeta.
Soleil - Mathieu Prévot
Esto me está dando la unidad raíz por alguna razón.
Capitán Prinny el
10

Si desea saber cuál es el directorio donde se encuentra su solución, debe hacer esto:

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

Si solo dejas el GetCurrrentDirectory()método, obtienes la carpeta de compilación sin importar si estás depurando o liberando. Espero esta ayuda! Si olvida las validaciones, sería así:

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

Estaba buscando esto también. Tengo un proyecto que ejecuta HWC, y me gustaría mantener el sitio web fuera del árbol de aplicaciones, pero no quiero mantenerlo en el directorio de depuración (o lanzamiento). FWIW, la solución aceptada (y esta también) solo identifica el directorio en el que se ejecuta el ejecutable.

Para encontrar ese directorio, he estado usando

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

Basado en la respuesta de Gucu112 , pero para la aplicación .NET Core Console / Window, debería ser:

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

Estoy usando esto en un proyecto xUnit para una aplicación .NET Core Window.

zwcloud
fuente
4

Otra forma de hacer esto.

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

Si desea obtener la ruta a la carpeta bin

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

Tal vez hay mejor manera =)

Tret
fuente
4

Otra solución imperfecta (pero quizás un poco más cercana a la perfección que algunas de las otras):

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

Esta versión devolverá la carpeta de los proyectos actuales, incluso si el proyecto actual no es Startup Projectpara la solución.

El primer defecto con esto es que me he saltado todas las comprobaciones de errores. Eso puede solucionarse con bastante facilidad, pero solo debería ser un problema si está almacenando su proyecto en el directorio raíz de la unidad o está utilizando una unión en su ruta (y esa unión es un descendiente de la carpeta de la solución), por lo que este escenario es poco probable . No estoy completamente seguro de que Visual Studio pueda manejar cualquiera de estas configuraciones de todos modos.

Otro (más probable) problema con el que se puede encontrar es que el nombre del proyecto debe coincidir con el nombre de la carpeta del proyecto para que se pueda encontrar.

Otro problema que puede tener es que el proyecto debe estar dentro de la carpeta de la solución. Esto generalmente no es un problema, pero si ha utilizado la Add Existing Project to Solutionopción de agregar el proyecto a la solución, entonces esta puede no ser la forma en que está organizada su solución.

Por último, si su aplicación modificará el directorio de trabajo, debe almacenar este valor antes de hacerlo porque este valor se determina en relación con el directorio de trabajo actual.

Por supuesto, todo esto también significa que no debe alterar los valores predeterminados para las opciones de sus proyectos Build-> Output patho Debug-> Working directoryen el cuadro de diálogo de propiedades del proyecto.

krowe
fuente
4

Prueba esto, es simple

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

Esta solución funciona bien para mí, en desarrollo y también en servidores TEST y PROD con ASP.NET MVC5 a través de C # :

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

Si necesita el directorio del proyecto en el archivo de configuración del proyecto, use:

$(ProjectDir)
Jan Sršeň
fuente
3

Después de que finalmente terminé de pulir mi primera respuesta sobre el uso de cadenas públicas para obtener una respuesta, me di cuenta de que probablemente podría leer un valor del registro para obtener el resultado deseado. Como resultado, esa ruta fue aún más corta:

Primero, debe incluir el espacio de nombres Microsoft.Win32 para poder trabajar con el registro:

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

Aquí está el código principal:

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

Una nota sobre esta respuesta:

Estoy usando Visual Studio 2008 Professional Edition. Si está utilizando otra versión (es decir, 2003, 2005, 2010; etc.), es posible que deba modificar la parte de 'versión' de la cadena de la Subclave (es decir, 8.0, 7.0; etc.).

Si usa una de mis respuestas y no es mucho pedir, me gustaría saber cuál de mis métodos utilizó y por qué. Buena suerte.

  • dm
digitalmythology
fuente
3

Tuve una situación similar, y después de los infructuosos Google, declaró una cadena pública, que modifica un valor de cadena de la ruta de depuración / liberación para obtener la ruta del proyecto. Una ventaja de usar este método es que, dado que usa el directorio del proyecto correcto, no importa si está trabajando desde un directorio de depuración o un directorio de publicación:

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

Entonces podrá llamarlo cuando lo desee, utilizando solo una línea:

string MyProjectDir = DirProject();

Esto debería funcionar en la mayoría de los casos.

digitalmythology
fuente
3

Use esto para obtener el directorio del Proyecto (funcionó para mí):

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

He utilizado la siguiente solución para hacer el trabajo:

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

Tratar:

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

Esta es una solución diferente de las demás también tiene en cuenta la posible compilación x86 o x64.

David Desmaisons
fuente
Esta solución ya casi está disponible para los nuevos archivos csproj, donde TargetFramework está incluido en la ruta.
Glenn Watson el
1
Para el nuevo formato de estilo .netcore tuve una nueva expresión regular (@ "\\ bin (\\ x86 | \\ x64)? \ (Debug | Release) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson el
1

La mejor solucion

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

Otra solucion

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

Pruébelo, AppDomain.CurrentDomain.BaseDirectory funcionó para mí en un proyecto anterior, ahora obtengo la carpeta de depuración ... ¡la BUENA respuesta seleccionada NO FUNCIONA !.

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

Si realmente desea asegurarse de obtener el directorio del proyecto de origen, no importa cuál sea la ruta de salida del contenedor configurada en:

  1. Agregue una línea de comando de evento previo a la compilación (Visual Studio: Propiedades del proyecto -> Eventos de compilación):

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

  2. Agregue el ProjectDirectory.txtarchivo a Resources.resx del proyecto (si aún no existe, haga clic con el botón derecho en proyecto -> Agregar nuevo elemento -> Archivo de recursos)

  3. Acceso desde código con Resources.ProjectDirectory.
FunctorSalad
fuente
-1

Esto funciona en VS2017 con configuraciones de SDK Core MSBuild.

Necesita NuGet en los paquetes EnvDTE / EnvDTE80.

No use COM ni interoperabilidad. cualquier cosa ... basura !!

 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);
    }
  }
Latencia
fuente
-6

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

Te dará el directorio del proyecto.

Brian Kitcehner
fuente
77
¿De Verdad? Creo que te estás perdiendo un padre
sean