HintPath vs ReferencePath no Visual Studio


120

O que exatamente é a diferença entre o HintPathem um arquivo .csproj e ReferencePathem um .csproj.userarquivo? Estamos tentando nos comprometer com uma convenção em que as DLLs de dependência estão em um repositório svn "releases" e todos os projetos apontam para um release específico. Como diferentes desenvolvedores têm estruturas de pastas diferentes, as referências relativas não funcionam, então criamos um esquema para usar uma variável de ambiente apontando para a pasta de releases do desenvolvedor em particular para criar uma referência absoluta. Portanto, depois que uma referência é adicionada, editamos manualmente o arquivo do projeto para alterar a referência para um caminho absoluto usando a variável de ambiente

Percebi que isso pode ser feito com o HintPathe o ReferencePath, mas a única diferença que pude encontrar entre eles é que HintPathé resolvido no momento da construção e ReferencePathquando o projeto é carregado no IDE. Não tenho muita certeza de quais são as ramificações disso. Percebi que o VS às vezes reescreve o .csproj.usere tenho que reescrever o ReferencePath, mas não tenho certeza do que desencadeia isso.

Ouvi dizer que é melhor não fazer o check-in do .csproj.userarquivo, uma vez que é específico do usuário, então gostaria de procurar por isso, mas também ouvi dizer que a HintPathDLL especificada não é "garantida" para ser carregada se a mesma DLL está localizada no diretório de saída do projeto. Alguma idéia sobre isso?

Respostas:


133

De acordo com este blog do MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Há uma ordem de pesquisa para montagens na construção. A ordem de pesquisa é a seguinte:

  • Arquivos do projeto atual - indicados por $ {CandidateAssemblyFiles}.
  • Propriedade $ (ReferencePath) que vem do arquivo .user / target.
  • Metadados% (HintPath) indicados pelo item de referência.
  • Diretório da estrutura de destino.
  • Diretórios encontrados no registro que usa o registro AssemblyFoldersEx.
  • Pastas de montagem registradas, indicadas por $ {AssemblyFolders}.
  • $ (OutputPath) ou $ (OutDir)
  • GAC

Portanto, se o assembly desejado for encontrado pelo HintPath , mas um assembly alternativo puder ser encontrado usando o ReferencePath , ele preferirá o assembly ReferencePath 'd ao HintPath ' d.


2
Exceto que eles mudaram isso no VS2019 - estamos usando essa configuração há anos. não mais. Arquivos do repositório agora têm prioridade maior do que arquivos DLL solução de construção - figura go :(
Christian

@ Christian: O que são arquivos de repositório? Você tem mais informações sobre isso?
testando

@ testing Estou falando dos caminhos de referência externos, você pode definir na configuração do projeto do VS. Infelizmente, essa configuração importante e louca para o ambiente do projeto (temos três ambientes diferentes) não pode ser salva nas configurações do projeto; portanto, você deve adicioná-lo explicitamente como parâmetro ao script de compilação da linha de comando.
Christian

31

Procure no arquivo Microsoft.Common.targets

A resposta para a pergunta está no arquivo Microsoft.Common.targetsda sua versão da estrutura de destino.

Para o .NET Framework versão 4.0 (e 4.5!), O elemento AssemblySearchPaths é definido assim:

    <!--
    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 o .NET Framework 3.5, a definição é a mesma, mas o comentário está errado. A definição 2.0 é um pouco diferente, usa $ (OutputPath) em vez de $ (OutDir).

Na minha máquina, tenho as seguintes versões do arquivo 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

Isso ocorre com o Visual Studio 2008, 2010 e 2013 instalado no Windows 7.

O fato de o diretório de saída ser pesquisado pode ser um pouco frustrante (como o pôster original indica) porque pode ocultar um HintPath incorreto. A solução cria OK na sua máquina local, mas é interrompida quando você cria uma estrutura de pastas limpa (por exemplo, na máquina de compilação).


Eu tenho um problema semelhante, neste caso, onde devo colocar os arquivos DLL? Framework ou Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev

5

Minha própria experiência foi que é melhor manter um de dois tipos de referências de montagem:

  • Um assembly 'local' no diretório de compilação atual
  • Uma assembléia no GAC

Descobri (como você descreveu) outros métodos que podem ser facilmente quebrados ou ter requisitos de manutenção irritantes.

Qualquer montagem que eu não queira que o GAC precise morar no diretório de execução. Qualquer assembly que não esteja ou não possa estar no diretório de execução I GAC (gerenciado por eventos de criação automática).

Isso não me deu nenhum problema até agora. Embora eu tenha certeza de que há uma situação em que não funcionará, a resposta usual para qualquer problema foi "ah, apenas GAC!". 8 D

Espero que ajude!


1

Embora este seja um documento antigo, ele me ajudou a resolver o problema do 'HintPath' sendo ignorado em outra máquina. Isso ocorreu porque a DLL referenciada também precisava estar no controle de origem:

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

Excerto:

Para incluir e referenciar um conjunto de sistema externo
1. No Solution Explorer, clique com o botão direito do mouse no projeto que precisa fazer referência à montagem ,, e clique em Add Existing Item.
2. Navegue até a montagem e clique em OK. A montagem é copiada para a pasta do projeto e automaticamente adicionada ao VSS (assumindo que o projeto já esteja sob controle de origem).
3. Use o botão Procurar na caixa de diálogo Adicionar referência para definir uma referência de arquivo para montagem na pasta do projeto.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.