HintPath vs ReferencePath en Visual Studio

120

¿Cuál es exactamente la diferencia entre HintPathen un archivo .csproj y ReferencePathen un .csproj.userarchivo? Estamos tratando de comprometernos con una convención donde las DLL de dependencia se encuentran en un repositorio svn de "versiones" y todos los proyectos apuntan a una versión en particular. Dado que los diferentes desarrolladores tienen diferentes estructuras de carpetas, las referencias relativas no funcionarán, por lo que se nos ocurrió un esquema para usar una variable de entorno que apunta a la carpeta de versiones del desarrollador en particular para crear una referencia absoluta. Entonces, después de agregar una referencia, editamos manualmente el archivo del proyecto para cambiar la referencia a una ruta absoluta usando la variable de entorno.

Me di cuenta de que esto se puede hacer tanto con el HintPathcomo con el ReferencePath, pero la única diferencia que pude encontrar entre ellos es que HintPathse resuelve en el momento de la compilación y ReferencePathcuando el proyecto se carga en el IDE. Sin embargo, no estoy seguro de cuáles son las ramificaciones de eso. He notado que VS a veces reescribe el .csproj.usery tengo que reescribirlo ReferencePath, pero no estoy seguro de qué lo desencadena.

Escuché que es mejor no registrar el .csproj.userarchivo ya que es específico del usuario, así que me gustaría apuntar a eso, pero también escuché que la HintPathDLL especificada no está "garantizada" para ser cargada si la misma DLL se encuentra, por ejemplo, en el directorio de salida del proyecto. Tiene alguna idea sobre esto?

horno tostador
fuente

Respuestas:

133

Según este blog de MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Hay un orden de búsqueda para ensamblajes al construir. El orden de búsqueda es el siguiente:

  • Archivos del proyecto actual, indicados por $ {CandidateAssemblyFiles}.
  • $ (ReferencePath) propiedad que proviene del archivo .user / targets.
  • % (HintPath) metadatos indicados por el elemento de referencia.
  • Directorio de marco de destino.
  • Directorios encontrados en el registro que utiliza el registro AssemblyFoldersEx.
  • Carpetas de ensamblaje registradas, indicadas por $ {AssemblyFolders}.
  • $ (OutputPath) o $ (OutDir)
  • GAC

Por lo tanto, si HintPath encuentra el ensamblado deseado , pero se puede encontrar un ensamblado alternativo usando ReferencePath , preferirá el ensamblado ReferencePath 'd al de HintPath .

ajs410
fuente
2
Excepto que cambiaron esto en VS2019; hemos estado usando esta configuración durante años. ya no. Los archivos del repositorio ahora tienen mayor prioridad que los archivos dll de compilación de soluciones; vaya a la figura :(
Christian
@Christian: ¿Qué son los archivos de repositorio? ¿Tienes más información sobre esto?
prueba el
@testing Estoy hablando de las rutas de referencia externas, puede establecer en la configuración de su proyecto de VS. Desafortunadamente, esta loca configuración importante para el entorno del proyecto (tenemos tres entornos diferentes), no se puede guardar en la configuración del proyecto; por lo que debe agregarlo explícitamente como parámetro al script de compilación de la línea de comandos.
Christian
31

Busque en el archivo Microsoft.Common.targets

La respuesta a la pregunta está en el archivo Microsoft.Common.targetsde la versión de su marco de destino.

Para .Net Framework versión 4.0 (¡y 4.5!), El elemento AssemblySearchPaths se define así:

    <!--
    The SearchPaths property is set to find assemblies in the following order:

        (1) Files from current project - indicated by {CandidateAssemblyFiles}
        (2) $(ReferencePath) - the reference path property, which comes from the .USER file.
        (3) The hintpath from the referenced item itself, indicated by {HintPathFromItem}.
        (4) The directory of MSBuild's "target" runtime from GetFrameworkPath.
            The "target" runtime folder is the folder of the runtime that MSBuild is a part of.
        (5) Registered assembly folders, indicated by {Registry:*,*,*}
        (6) Legacy registered assembly folders, indicated by {AssemblyFolders}
        (7) Resolve to the GAC.
        (8) Treat the reference's Include as if it were a real file name.
        (9) Look in the application's output folder (like bin\debug)
    -->
<AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == ''">
  {CandidateAssemblyFiles};
  $(ReferencePath);
  {HintPathFromItem};
  {TargetFrameworkDirectory};
  {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
  {AssemblyFolders};
  {GAC};
  {RawFileName};
  $(OutDir)
</AssemblySearchPaths>

Para .Net Framework 3.5, la definición es la misma, pero el comentario es incorrecto. La definición 2.0 es ligeramente diferente, usa $ (OutputPath) en lugar de $ (OutDir).

En mi máquina tengo las siguientes versiones del archivo Microsoft.Common.targets:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework64\v3.5\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets

Esto es con Visual Studio 2008, 2010 y 2013 instalados en Windows 7.

El hecho de que se busque en el directorio de salida puede ser un poco frustrante (como señala el póster original) porque puede ocultar una HintPath incorrecta. La solución se construye bien en su máquina local, pero se rompe cuando se construye en una estructura de carpetas limpia (por ejemplo, en la máquina de construcción).

Nils Lande
fuente
Tengo un problema similar, en este caso, ¿dónde debo colocar los archivos dll? Framework o Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev
5

Mi propia experiencia ha sido que es mejor ceñirse a uno de los dos tipos de referencias de ensamblaje:

  • Un ensamblado 'local' en el directorio de compilación actual
  • Una asamblea en el GAC

He encontrado (al igual que ha descrito) otros métodos que se rompen con demasiada facilidad o tienen requisitos de mantenimiento molestos.

Cualquier ensamblado que no quiera para GAC, tiene que vivir en el directorio de ejecución. Cualquier ensamblado que no esté o no pueda estar en el directorio de ejecución I GAC (administrado por eventos de compilación automáticos).

Esto no me ha dado ningún problema hasta ahora. Si bien estoy seguro de que hay una situación en la que no funcionará, la respuesta habitual a cualquier problema ha sido "¡oh, solo GAC!". 8 D

¡Espero que ayude!

Tarea
fuente
1

Aunque este es un documento antiguo, me ayudó a resolver el problema de que 'HintPath' se ignorara en otra máquina. Fue porque la DLL referenciada también necesitaba estar en el control de código fuente:

https://msdn.microsoft.com/en-us/library/ee817675.aspx#tdlg_ch4_includeoutersystemassemblieswithprojects

Extracto:

Para incluir y luego hacer referencia a un ensamblaje de sistema externo
1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto que necesita hacer referencia al ensamblaje y luego haga clic en Agregar elemento existente.
2. Busque el ensamblaje y haga clic en Aceptar. Luego, el ensamblaje se copia en la carpeta del proyecto y se agrega automáticamente a VSS (asumiendo que el proyecto ya está bajo control de código fuente).
3. Utilice el botón Examinar en el cuadro de diálogo Agregar referencia para establecer una referencia de archivo al ensamblaje en la carpeta del proyecto.
nkanani
fuente