DLL dependente não está sendo copiada para a pasta de saída de compilação no Visual Studio


188

Eu tenho uma solução de estúdio visual. Eu tenho muitos projetos na solução. Há um projeto principal que atua como a inicialização e usa outros projetos. Há um projeto que diz "ProjetoX". Sua referência é adicionada ao projeto principal. O ProjectX faz referência a outra DLL do .NET (por exemplo, abc.dll) que não faz parte da solução.

Agora, este abc.dll deve ser copiado para a pasta bin / debug do projeto principal, mas não está sendo copiado para lá. Por que não está sendo copiado, por algum motivo conhecido?


se você não conseguir descobrir isso, copie-o em sua pré-construção.
precisa

Como você usa o seu 'ProjectX' no projeto principal - o que é o tipo de projeto, alvo etc.
NSGaga-principalmente-inativa

Eu tive o mesmo problema e esta resposta resolveu o meu problema: stackoverflow.com/a/8213977/174469
Gordon Tucker


existe RestoreProjectStyle solução disponível . A idéia é definir <RestoreProjectStyle>PackageReference</RestoreProjectStyle>para cada projeto do .Net Framework na solução.
oleksa

Respostas:


105

Descobri que, se o ProjectX referenciasse o abc.dll, mas não usasse diretamente nenhum dos tipos DEFINED em abc.dll, o abc.dll NÃO seria copiado para a pasta de saída principal. (Ele seria copiado para a pasta de saída do ProjectX, para torná-lo extremamente confuso.)

Portanto, se você não estiver usando explicitamente nenhum dos tipos de abc.dll em qualquer lugar do ProjectX, coloque uma declaração fictícia em algum lugar de um dos arquivos do ProjectX.

AbcDll.AnyClass dummy006; // this will be enough to cause the DLL to be copied

Você não precisa fazer isso para todas as classes - apenas uma vez será suficiente para fazer a cópia da DLL e tudo funcionará conforme o esperado.

Adendo: Observe que isso pode funcionar no modo de depuração, mas NÃO na liberação. Veja a resposta da @ nvirth para detalhes.


7
Isso parece um hack. Adicionar a referência ao projeto principal parece ser suficiente.
Mike K

3
É um truque, mas como as notícias do CodeProject de hoje nos ensinaram, mesmo os compiladores podem estar errados!
Overlord Zurg

4
Como as coisas podem ser loucas. @OverlordZurg sua solução funcionou, pois eu tinha uma referência à dll dependente no meu XAML (WPF) e ela não copiou a DLL para o projeto principal até eu adicionar uma referência fictícia simples como você disse ... Obrigado de qualquer maneira
Mohsen Afshin

5
@MohsenAfshin Eu tive o mesmo problema --- eu estava fazendo referência a uma DLL dependente em XAML. Em vez de declarar uma variável dummy, no entanto, simplesmente nomeei o componente que estava usando no XAML, e isso foi suficiente para fazer com que seu assembly fosse copiado.
Redcurry #

5
@MikeK Adicioná-lo ao projeto principal (que na verdade não depende diretamente dele) é um hack ainda maior, imo. Em seguida, você deve gerenciá-lo em dois locais ("gerenciar", como na atualização ou remoção). Com esse hack, pelo menos você recebe um bom erro em tempo de compilação, lembrando-o de remover esse hack quando você remove a dependência, e você ainda precisa atualizá-lo em um só lugar.
Jpmc26 21/09/16

71

Apenas uma nota de rodapé da resposta do Overlord Zurg.

Adicionei a referência fictícia dessa maneira e funcionou no modo de depuração:

public class DummyClass
{
    private static void Dummy()
    {
        var dummy = typeof(AbcDll.AnyClass);
    }
}

Mas no modo Release, a dll dependente ainda não foi copiada.
Isso funcionou no entanto:

public class DummyClass
{
    private static void Dummy()
    {
        Action<Type> noop = _ => {};
        var dummy = typeof(AbcDll.AnyClass);
        noop(dummy);
    }
}

Na verdade, essas informações me custaram horas para descobrir, então pensei em compartilhá-las.


7
no modo de liberação, o otimizador supõe que "fictício" não seja usado, portanto esta linha é desnecessária e deve ser removida. mas quando você usa "fictício" no código, o otimizador não assume que é desnecessário.
Yucel

1
Isso não funciona para mim.AbcDll.AnyClass ainda não foi copiado para outro projeto
Matthew Lock

3
Certifique-se de que AbcDll.AnyClassseja usado como um campo público ou propriedade em uma classe pública, para que funcione. Se você o usar em um corpo de método como este, o compilador não o verá . Isso atrasará o carregamento desta montagem, não o que você deseja que aconteça.
John Leidegren

52

Sim, você precisará definir Copy Localcomo true. No entanto, tenho certeza de que você também precisará fazer referência a essa montagem do projeto principal e configurá Copy Local-la truetambém - ela não é apenas copiada de uma montagem dependente.

Você pode chegar à Copy Localpropriedade clicando na montagem abaixo Referencese pressionando F4.


2
@Brij, a montagem é referenciada no projeto principal em que você deseja? Como afirmei, tenho certeza de que você também precisa fazer referência a esse projeto - os assemblies dependentes não são copiados dessa maneira. Se fosse esse o caso, você não precisaria adicionar as montagens a todos os projetos relevantes ao usar o NuGet.
Mike Perrenoud #

1
qual foi a conclusão aqui? Parece-me que você tem razão - as referências dependentes não são copiadas, mesmo que CopyLocal esteja definido como verdadeiro - qual é a lógica por trás disso?
Mcmillab

29
@mcmillab, em suma, o Visual Studio não infere dependências de outros projetos dependentes. Se o projeto A fizer referência ao projeto B, o projeto A precisará ter todas as referências do projeto B. Funciona bem quando tudo o que o projeto B precisa é de assemblies .NET, mas se for um assembly de terceiros, você deverá adicionar a referência aos dois projetos.
21813 Mike Perrenoud

12
@MichaelPerrenoud Não acho que isso seja verdade. Se você observar uma saída detalhada do MSBuild, verá chamadas para ResolveAssemblyReference, que afirma que "inclui dependências de segunda e de ordem n". Isso também concorda com o que vejo nas minhas pastas bin (as enésimas dependências são copiadas). A questão é que existem algumas advertências sobre o que é copiado, principalmente ao redor GAC e referências indiretas (Add Reference, por vezes, não é suficiente)
Jack Ukleja

2
Minha experiência atual é que isso funcionará, exceto para dependências 'copiadas': o projeto A.net faz referência a DLLs externas do C ++ como arquivos que são 'sempre copiados'. Referências do Project B.net Projeto A. Na compilação, B / Debug inclui as DLLs do C ++. No entanto, quando eu construo o Aplicativo X, que faz referência ao Projeto B, as dlls do C ++ às vezes são copiadas (parece ser apenas se eu fizer uma Reconstrução).
Benjol 11/02

34

Parece liso quando você o torna um atributo de montagem

[AttributeUsage(AttributeTargets.Assembly)]
public class ForceAssemblyReference: Attribute
{        
    public ForceAssemblyReference(Type forcedType)
    {
        //not sure if these two lines are required since 
        //the type is passed to constructor as parameter, 
        //thus effectively being used
        Action<Type> noop = _ => { };
        noop(forcedType);
    }
}

O uso será:

[assembly: ForceAssemblyReference(typeof(AbcDll.AnyClass))]

Obrigado, mas para mim isso só faz algo quando adiciono o atributo assembly à dependência (Projeto X), que já faz referência ao AbcDll.AnyClass. E então, ele não faz mais do que normalmente, onde copia o AbcDll para o diretório de saída da dependência. Ele ainda não o copia para a saída do projeto dependente principal. E não posso adicionar o atributo ao assembly dependente, a menos que eu também adicione uma referência ao AbcDll. Quando faço isso, o AbcDll já é copiado sem o atributo.
JS

25

Encontrei esse mesmo problema. Informações básicas: antes da construção, eu adicionei um novo projeto X à solução. O projeto Y dependia do projeto X e o projeto A, B, C dependia do projeto Y.

Os erros de compilação foram que as DLLs do Projeto A, B, C, Y e X não foram encontradas.

A causa principal foi que o Projeto X recém-criado tinha como alvo o .NET 4.5, enquanto o restante dos projetos de solução tinha como alvo o .NET 4.5.1. O Projeto X não foi construído, fazendo com que o restante dos Projetos também não fosse construído.

Certifique-se de que os projetos adicionados recentemente tenham como destino a mesma versão do .NET que o restante da solução.


1
Projetos referenciados podem ser uma versão mais antiga do .NET. Consigo fazer referência a um projeto criado para o .NET 4 por um projeto criado para o .NET 4.5.
Redcurry #

18

Não tenho certeza se isso ajuda, mas para mim, muitas vezes faço referência a uma DLL (que automaticamente a adiciona à pasta bin). No entanto, essa DLL pode precisar de DLLs adicionais (dependendo das funções que estou usando). NÃO quero referenciar aqueles no meu projeto porque eles simplesmente precisam terminar na mesma pasta que a DLL que estou realmente usando.

Consigo isso no Visual Studio "Adicionando um arquivo existente". Você deve poder adicioná-lo em qualquer lugar, exceto na pasta Add_data. pessoalmente, apenas adiciono-o à raiz.

Em seguida, altere as propriedades desse arquivo para ...

Ação de compilação = Nenhuma (definir esse item como algo como Conteúdo, na verdade, copia a versão "raiz" para a raiz, além de uma cópia na lixeira).

Copiar para pasta de saída = Copiar se mais recente (basicamente o coloca na pasta BIN apenas se estiver ausente, mas não o faz depois disso)

Quando publico .. minhas DLLs adicionadas existem apenas na pasta BIN e em nenhum outro lugar no local de publicação (que é o que eu quero).


10

Você também pode verificar se as DLLs que você está procurando não estão incluídas no GAC. Acredito que o Visual Studio esteja sendo esperto em não copiar esses arquivos, se eles já existirem no GAC na máquina de compilação.

Recentemente, corri nessa situação em que estava testando um pacote SSIS que precisava de assemblies para existir no GAC. Eu já tinha esquecido isso e queria saber por que essas DLLs não foram lançadas durante uma compilação.

Para verificar o que há no GAC (em um prompt de comando do desenvolvedor do Visual Studio):

gacutil -l

Ou envie para um arquivo para facilitar a leitura:

gacutil -l > output.txt
notepad.exe output.txt

Para remover uma montagem:

gacutil -u MyProjectAssemblyName

Devo observar também que, uma vez removidos os arquivos do GAC, eles foram gerados corretamente no diretório \ bin após uma compilação (mesmo para assemblies que não foram diretamente referenciados no projeto raiz). Isso foi no Visual Studio 2013 Update 5.


Obrigado, você está certo, o MSBuild não copiará a dll para a pasta de saída se os encontrar no GAC.
John-Philip

3

No meu caso, foi a coisa mais estúpida, causada por um comportamento padrão do TFS / VS com o qual não concordo.

Como a adição da dll como referência ao projeto principal não funcionou, decidi adicioná-la como um "Item Existente", com Copiar Local = Sempre. Mesmo assim, o arquivo não estava lá.

Acontece que, embora o arquivo esteja presente na solução VS e tudo compilado localmente e no servidor, o VS / TFS não adicionou realmente o arquivo ao controle de origem. Não foi incluído nas "Alterações pendentes". Eu tive que ir manualmente para o Source Control Explorer e clicar explicitamente no ícone "Adicionar itens à pasta".

Estúpido porque estou desenvolvendo há 15 anos no VS. Eu já me deparei com isso antes, simplesmente não me lembro e, de alguma forma, perdi porque tudo ainda foi compilado por causa do arquivo ser uma referência regular, mas o arquivo que foi adicionado como Item Existente não estava sendo copiado porque não existia no o servidor de controle de origem.

Espero que isso economize alguém, já que perdi 2 dias da minha vida por isso.


1
Não posso agradecer o suficiente ... você me salvou muito tempo. Esta foi a solução para mim. Também expôs o problema raiz, a DLL que adicionei como referência correspondia a um gitignorepadrão; portanto, ao adicionar como referência, ela não foi adicionada ao projeto. Você DEVE adicionar manualmente o arquivo ao controle de origem !!!
Mattkwish 6/03/19

2

Este é um pequeno ajuste no exemplo de nvirth

internal class DummyClass
{
    private static void Dummy()
    {
        Noop(typeof(AbcDll.AnyClass));
    }
    private static void Noop(Type _) { }
}

2

Eu o adicionaria aos eventos do Postbuild para copiar as bibliotecas necessárias para os diretórios de saída. Algo como o diretório de bibliotecas de caminhos XCopy

Você pode encontrá-los nas propriedades do projeto -> Construir Eventos.


Isso funcionou para mim e acho que essa é a melhor resposta. A solução de referência fictícia funciona, mas é um hack, enquanto uma regra pós-compilação é uma maneira limpa de obter o mesmo resultado.
Kevin Fichter

2

Questão:

Foi encontrado um problema semelhante para uma DLL do pacote NuGet (Newtonsoft.json.dll) onde a saída da compilação não inclui a DLL referenciada. Mas a compilação vai bem.

Consertar:

Percorra seus projetos em um editor de texto e procure por referências com tags. Como verdadeiro ou falso. "Privado" é sinônimo de "Copiar local". Em algum lugar das ações, o MSBuild está adotando para localizar dependências, encontrando sua dependência em outro lugar e decidindo não copiá-la.

Portanto, passe por cada arquivo .csproj / .vbproj e remova as tags manualmente. Reconstrua e tudo funciona no Visual Studio e no MSBuild. Depois de ter esse trabalho, você pode voltar e atualizar para onde você acha que eles precisam estar.

Referência:

https://www.paraesthesia.com/archive/2008/02/13/what-to-do-if-copy-local-works-in-vs-but.aspx/


1

NECESSIDADE DE MANEQUIM NO CÓDIGO
Apenas:

adicionar uma referência ao projeto executável

ou / e verifique se a referência no projeto executável foi "Copy Local"definida como TRUE(que foi minha " falha ") parece que isso "substituiu" a configuração no projeto de biblioteca de referência referenciado ...


1

Se você clicar com o botão direito do mouse na montagem referenciada, verá uma propriedade chamada Copiar Local . Se Copiar local estiver definido como verdadeiro, a montagem deverá ser incluída na bandeja. No entanto , pode haver um problema no Visual studio, que às vezes não inclui a dll referenciada na pasta bin ... esta é a solução alternativa que funcionou para mim:

insira a descrição da imagem aqui


1
Cópia loal foi desativado, isso ajudou stackoverflow.com/questions/15526491/...
CodeMirror

1

TLDR; O Visual Studio 2019 pode simplesmente precisar de uma reinicialização.

Encontrei essa situação usando projetos baseados no projeto Microsoft.NET.Sdk.

<Project Sdk="Microsoft.NET.Sdk">

Especificamente:

  • Project1: metas .netstandard2.1
    • referências Microsoft.Extensions.Logging.Consolevia Nuget
  • Project2: metas .netstandard2.1
    • referências Project1por meio de uma referência de projeto
  • Project2Tests: metas .netcoreapp3.1
    • referências Project2por meio de uma referência de projeto

Na execução do teste, recebi a mensagem de erro indicando que Microsoft.Extensions.Logging.Consolenão foi possível encontrar e, de fato, não estava no diretório de saída.

Decidi solucionar o problema adicionando Microsoft.Extensions.Logging.Consolea Project2, apenas para descobrir que o Nuget Manager do Visual Studio não estava listado Microsoft.Extensions.Logging.Consolecomo instalado Project1, apesar da presença no Project1.csprojarquivo.

Um simples desligamento e reinicialização do Visual Studio resolveram o problema sem a necessidade de adicionar uma referência extra. Talvez isso poupe a alguém 45 minutos de produtividade perdida :-)


Na verdade, reiniciei todo o PC na minha maneira de testar as coisas, mas funcionou para mim
Noman_1 18/06

0

Você pode definir o mesmo projeto principal e o caminho de saída de criação do ProjectX para a mesma pasta, para obter todas as dlls necessárias nessa pasta.


0

Verifique se a dll dependente usada por você não possui a estrutura .net de destino superior à estrutura .net de destino do aplicativo do seu projeto.

Você pode verificar isso selecionando seu projeto, pressione ALT + ENTER, selecione Aplicativo no lado esquerdo e selecione Estrutura de Destino do seu projeto.

Suponha que dll Target Framework dependente = 4.0 e Application dll Target Framework = 3.5 e altere isso para 4.0

Obrigado!


0

Além dos comuns acima, eu tinha uma solução de vários projetos para publicar. Aparentemente, alguns arquivos têm como alvo estruturas diferentes.

Então, minha solução: Propriedades> Versão específica (falsa)


0

Adicione a DLL como um item existente a um dos projetos e ela deve ser classificada


0

VS2019 V16.6.3

Para mim, o problema era de alguma forma o arquivo .proj principal que acabou com uma entrada como esta para o projeto cuja DLL não estava sendo copiada para a pasta bin do projeto pai:

<ProjectReference Include="Project B.csproj">
  <Project>{blah blah}</Project>
  <Name>Project B</Name>
  <Private>True</Private>
</ProjectReference>

Excluí manualmente a linha <Private>True</Private>e a DLL foi copiada para a pasta principal do projeto em todas as compilações do projeto principal.

Se você for para a referência do projeto problemático na pasta de referências do projeto principal, clique nele e veja as propriedades. Existe uma configuração "Copiar Local". A marca particular equivale a essa configuração, mas, por algum motivo, a alteração do local da cópia não teve efeito na marca privada no arquivo .proj.

Irritantemente, não alterei o valor local da cópia para a referência, não faço ideia de como foi definido dessa maneira e outro dia desperdiçado rastreando um problema estúpido com o VS.

Obrigado a todas as outras respostas que me ajudaram a entender a causa.

HTH

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.