HintPath vs ReferencePath in Visual Studio


120

Qual è esattamente la differenza tra HintPathin un file .csproj e ReferencePathin un .csproj.userfile? Stiamo cercando di impegnarci in una convenzione in cui le DLL delle dipendenze sono in un repository svn "rilasci" e tutti i progetti puntano a una particolare versione. Poiché diversi sviluppatori hanno strutture di cartelle diverse, i riferimenti relativi non funzioneranno, quindi abbiamo escogitato uno schema per utilizzare una variabile di ambiente che punta alla cartella delle versioni dello sviluppatore particolare per creare un riferimento assoluto. Quindi, dopo aver aggiunto un riferimento, modifichiamo manualmente il file di progetto per cambiare il riferimento a un percorso assoluto utilizzando la variabile di ambiente.

Ho notato che questo può essere fatto sia con il HintPathche con il ReferencePath, ma l'unica differenza che ho trovato tra loro è che HintPathviene risolto in fase di compilazione e ReferencePathquando il progetto viene caricato nell'IDE. Non sono davvero sicuro di quali siano le conseguenze di ciò. Ho notato che VS a volte riscrive il .csproj.usere devo riscrivere il ReferencePath, ma non sono sicuro di cosa lo attivi.

Ho sentito che è meglio non .csproj.userarchiviare il file poiché è specifico dell'utente, quindi mi piacerebbe mirare a quello, ma ho anche sentito che la HintPathDLL specificata non è "garantita" per essere caricata se la stessa DLL si trova ad esempio nella directory di output del progetto. Qualche idea su questo?

Risposte:


133

Secondo questo blog MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Esiste un ordine di ricerca per gli assiemi durante la creazione. L'ordine di ricerca è il seguente:

  • File del progetto corrente, indicati da $ {CandidateAssemblyFiles}.
  • $ (ReferencePath) che proviene dal file .user / target.
  • % (HintPath) metadati indicati dall'elemento di riferimento.
  • Directory del framework di destinazione.
  • Directory trovate nel registro che utilizza la registrazione AssemblyFoldersEx.
  • Cartelle di assembly registrate, indicate da $ {AssemblyFolders}.
  • $ (OutputPath) o $ (OutDir)
  • GAC

Quindi, se l'assembly desiderato viene trovato da HintPath , ma è possibile trovare un assembly alternativo utilizzando ReferencePath , preferirà l' assembly d di ReferencePath a quello di HintPath .


2
Tranne che hanno cambiato questo in VS2019: utilizziamo questa configurazione da anni ormai. non più. I file di repository ora hanno una priorità più alta rispetto ai file dll di build della soluzione - vai a capire :(
Christian

@Christian: Cosa sono i file di repository? Hai maggiori informazioni in merito?
test il

@testing Sto parlando dei percorsi di riferimento esterni, che puoi impostare nella configurazione del tuo progetto di VS. Sfortunatamente questa impostazione folle e importante per l'ambiente del progetto (abbiamo tre ambienti diversi), non può essere salvata nelle impostazioni del progetto; quindi devi aggiungerlo esplicitamente come parametro allo script di compilazione della riga di comando.
Christian

31

Cerca nel file Microsoft.Common.targets

La risposta alla domanda è nel file Microsoft.Common.targetsdella versione del framework di destinazione.

Per .Net Framework versione 4.0 (e 4.5!), L'elemento AssemblySearchPaths è definito in questo modo:

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

Per .Net Framework 3.5 la definizione è la stessa, ma il commento è sbagliato. La definizione 2.0 è leggermente diversa, utilizza $ (OutputPath) invece di $ (OutDir).

Sulla mia macchina ho le seguenti versioni del file 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

Questo è con Visual Studio 2008, 2010 e 2013 installati su Windows 7.

Il fatto che venga eseguita la ricerca nella directory di output può essere un po 'frustrante (come sottolinea il poster originale) perché potrebbe nascondere un HintPath errato. La soluzione viene compilata correttamente sulla macchina locale, ma si interrompe quando si crea una struttura di cartelle pulita (ad esempio sulla macchina di compilazione).


Ho un problema simile, in questo caso, dove devo posizionare i file dll? Framework o Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev

5

La mia esperienza personale è stata che è meglio attenersi a uno dei due tipi di riferimenti di assemblaggio:

  • Un assembly "locale" nella directory di build corrente
  • Un'assemblea nel GAC

Ho trovato (proprio come hai descritto) altri metodi che possono essere rotti troppo facilmente o avere fastidiosi requisiti di manutenzione.

Qualsiasi assembly che non voglio GAC, deve risiedere nella directory di esecuzione. Qualsiasi assembly che non è o non può essere nella directory di esecuzione I GAC (gestito da eventi di compilazione automatici).

Questo finora non mi ha dato problemi. Anche se sono sicuro che ci sia una situazione in cui non funzionerà, la solita risposta a qualsiasi problema è stata "oh, solo GAC!". 8 D

Spero che aiuti!


1

Anche se questo è un vecchio documento, ma mi ha aiutato a risolvere il problema di "HintPath" ignorato su un'altra macchina. Era perché la DLL di riferimento doveva essere anche nel controllo del codice sorgente:

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

Estratto:

Per includere e quindi fare riferimento a un assieme del sistema esterno
1. In Esplora soluzioni, fare clic con il pulsante destro del mouse sul progetto che deve fare riferimento all'assembly, quindi fare clic su Aggiungi elemento esistente.
2. Individuare l'assembly e quindi fare clic su OK. L'assembly viene quindi copiato nella cartella del progetto e aggiunto automaticamente a VSS (supponendo che il progetto sia già sotto il controllo del codice sorgente).
3. Utilizzare il pulsante Sfoglia nella finestra di dialogo Aggiungi riferimento per impostare un riferimento al file all'assembly nella cartella del progetto.
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.