Pregunta

¿Hay alguna manera de obtener la ruta del ensamblado en el que reside el código actual?No quiero la ruta del ensamblado que llama, solo la que contiene el código.

Básicamente, mi prueba unitaria necesita leer algunos archivos de prueba xml que se encuentran en relación con el dll.Quiero que la ruta siempre se resuelva correctamente, independientemente de si el dll de prueba se ejecuta desde TestDriven.NET, la GUI de MbUnit o cualquier otra cosa.

Editar:La gente parece no entender lo que estoy preguntando.

Mi biblioteca de pruebas se encuentra en decir

C:\projects\myapplication\daotests\bin\Debug\daotests.dll

y me gustaría obtener este camino:

C:\proyectos\miaplicación\daotests\bin\Debug\

Las tres sugerencias hasta ahora me fallan cuando ejecuto desde MbUnit Gui:

  • Environment.CurrentDirectoryda c:\Archivos de programa\MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Locationda C: Documentos y configuraciones George Local Settings Temp .... Daotests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().LocationDa lo mismo que el anterior.

¿Fue útil?

Solución

He definido la siguiente propiedad ya que la usamos a menudo en las pruebas unitarias.

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

El Assembly.Location La propiedad a veces te da algunos resultados divertidos cuando usas NUnit (donde los ensamblados se ejecutan desde una carpeta temporal), así que prefiero usar CodeBase que le da la ruta en formato URI, luego UriBuild.UnescapeDataString elimina el File:// al principio, y GetDirectoryName lo cambia al formato normal de Windows.

Otros consejos

¿Esto ayuda?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );

Es tan simple como esto:

var dir = AppDomain.CurrentDomain.BaseDirectory;

Igual que la respuesta de John, pero con un método de extensión un poco menos detallado.

public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

Ahora puedes hacer:

var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

o si lo prefieres:

var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();

La única solución que funcionó para mí cuando utilicé recursos compartidos de CodeBase y UNC Network fue:

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

También funciona con URI normales.

Esto debería funcionar, a menos que el ensamblaje esté sombra copiada:

string path = System.Reflection.Assembly.GetExecutingAssembly().Location

¿Qué pasa con esto?

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

Sospecho que el verdadero problema aquí es que su ejecutor de pruebas está copiando su ensamblaje en una ubicación diferente.No hay forma en tiempo de ejecución de saber desde dónde se copió el ensamblaje, pero probablemente pueda activar un interruptor para decirle al ejecutor de pruebas que ejecute el ensamblaje desde donde está y no lo copie en un directorio oculto.

Por supuesto, es probable que este cambio sea diferente para cada corredor de prueba.

¿Ha considerado incorporar sus datos XML como recursos dentro de su ensamblaje de prueba?

AppDomain.CurrentDomain.BaseDirectory

Funciona con la GUI de MbUnit.

var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);

Aquí hay una adaptación VB.NET del código de John Sably.Visual Basic no distingue entre mayúsculas y minúsculas, por lo que un par de nombres de variables chocaban con nombres de tipos.

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property

Qué tal esto ...

string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

Luego simplemente corta lo que no necesitas

El directorio actual donde existe.

Environment.CurrentDirectory;  // This is the current directory of your application

Si copia el archivo .xml con build, debería encontrarlo.

o

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;

He estado usando Assembly.CodeBase en lugar de Ubicación:

Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
    s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");

Ha estado funcionando, pero ya no estoy seguro de que sea 100% correcto.la pagina en http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx dice:

"CodeBase es una URL al lugar donde se encontró el archivo, mientras que Ubicación es la ruta donde realmente se cargó.Por ejemplo, si el ensamblado se descargó de Internet, su CodeBase puede comenzar con "http://", pero su Ubicación puede comenzar con "C:\".Si el archivo fue una instantánea, la Ubicación sería la ruta a la copia del archivo en el directorio de instantáneas.También es bueno saber que no se garantiza que CodeBase esté configurado para asambleas en el GAC.Sin embargo, la ubicación siempre se establecerá para los ensamblajes cargados desde el disco."

puede desea utilizar CodeBase en lugar de Ubicación.

Por lo que puedo decir, la mayoría de las otras respuestas tienen algunos problemas.

La forma correcta de hacer esto para un basado en disco (a diferencia de basado en web), ensamblado sin GAC es utilizar el ensamblado actualmente en ejecución CodeBase propiedad.

Esto devuelve una URL (file://).En lugar de jugar con manipulación de cuerdas o UnescapeDataString, esto se puede convertir con un mínimo esfuerzo aprovechando el LocalPath propiedad de Uri.

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);

En todos estos años, nadie ha mencionado este.Un truco que aprendí de los increíbles. Proyecto de pruebas de aprobación.El truco consiste en utilizar la información de depuración en el ensamblado para encontrar el directorio original.

Esto no funcionará en modo RELEASE, ni con las optimizaciones habilitadas, ni en una máquina diferente a aquella en la que fue compilado.

Pero esto te llevará a caminos que son relativo a la ubicación del archivo de código fuente desde el que lo llama

public static class PathUtilities
{
    public static string GetAdjacentFile(string relativePath)
    {
        return GetDirectoryForCaller(1) + relativePath;
    }
    public static string GetDirectoryForCaller()
    {
        return GetDirectoryForCaller(1);
    }


    public static string GetDirectoryForCaller(int callerStackDepth)
    {
        var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
        return GetDirectoryForStackFrame(stackFrame);
    }

    public static string GetDirectoryForStackFrame(StackFrame stackFrame)
    {
        return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
    }
}

Puede obtener la ruta bin por appdomain.currentdomain.relativesearchpath

Todas las respuestas propuestas funcionan cuando el desarrollador puede cambiar el código para incluir el fragmento requerido, pero si desea hacer esto sin cambiar ningún código, puede usar Process Explorer.

Enumerará todos los archivos DLL en ejecución en el sistema; es posible que deba determinar la identificación del proceso de la aplicación en ejecución, pero eso generalmente no es demasiado difícil.

He escrito una descripción completa de cómo hacer esto para un dll dentro de II: http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/

en una aplicación de formulario de Windows, simplemente puede usar Application.StartupPath

pero para las DLL y las aplicaciones de consola el código es mucho más difícil de recordar...

string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

root += slash;
string settingsIni = root + "settings.ini"
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);

Obtendrá un directorio incorrecto si una ruta contiene el símbolo '#'.Entonces uso una modificación de la respuesta de John Sably que es una combinación de UriBuilder.Path y UriBuilder.Fragment:

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/", "\\") + 
          uri.Fragment.Replace("/", "\\"));
        return Path.GetDirectoryName(path);
     }
}

Esto es lo que se me ocurrió. Entre proyectos web, pruebas unitarias (nunit y resharper test runner);Descubrí que esto funcionó para mí.

He estado buscando código para detectar en qué configuración se encuentra la compilación, Debug/Release/CustomName.¡Ay, el #if DEBUG. Entonces si alguien puede mejorar eso.!

Siéntete libre de editar y mejorar.

Obteniendo carpeta de aplicaciones.Útil para raíces web, pruebas unitarias para obtener la carpeta de archivos de prueba.

public static string AppPath
{
    get
    {
        DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

        while (appPath.FullName.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
                || appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            appPath = appPath.Parent;
        }
        return appPath.FullName;
    }
}

Obteniendo la carpeta bin:Útil para ejecutar ensamblajes mediante reflexión.Si los archivos se copian allí debido a propiedades de compilación.

public static string BinPath
{
    get
    {
        string binPath = AppDomain.CurrentDomain.BaseDirectory;

        if (!binPath.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
            && !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            binPath = Path.Combine(binPath, "bin");
            //-- Please improve this if there is a better way
            //-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
            if (Directory.Exists(Path.Combine(binPath, "Debug"))) 
                        binPath = Path.Combine(binPath, "Debug");
#else
            if (Directory.Exists(Path.Combine(binPath, "Release"))) 
                        binPath = Path.Combine(binPath, "Release");
#endif
        }
            return binPath;
    }
}

Esto debería funcionar:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
Assembly asm = Assembly.GetCallingAssembly();
String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);

string strLog4NetConfigPath = System.IO.Path.Combine(path, "log4net.config");

Estoy usando esto para implementar bibliotecas de archivos DLL junto con algún archivo de configuración (esto es para usar log4net desde el archivo DLL).

Encuentro que mi solución es adecuada para la recuperación de la ubicación.

var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;

Tuve el mismo comportamiento en el NUnit en el pasado.Por defecto NUnit copia su ensamblaje en el directorio temporal.Puedes cambiar este comportamiento en el NUnit ajustes:

enter image description here

Tal vez TestDriven.NET y MbUnit La GUI tiene la misma configuración.

Utilizo esto para obtener la ruta al directorio Bin:

var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i); 

Obtienes este resultado:

"C: Users ricooley Documents Visual Studio 2010 Projects Windows_test_project Windows_test_project bin"

¿Aplicación web?

Server.MapPath("~/MyDir/MyFile.ext")
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top