DLL phụ thuộc không được sao chép vào thư mục đầu ra xây dựng trong Visual Studio


185

Tôi có một giải pháp phòng thu trực quan. Tôi có nhiều dự án trong giải pháp. Có một dự án chính đóng vai trò khởi động và sử dụng các dự án khác. Có một dự án nói "ProjectX". Tài liệu tham khảo của nó được thêm vào dự án chính. ProjectX tham chiếu một dll .NET khác (giả sử abc.dll) không phải là một phần của giải pháp.

Bây giờ abc.dll này sẽ được sao chép vào thư mục bin / debug của dự án chính, nhưng nó không được sao chép ở đó. Tại sao nó không được sao chép, bất kỳ lý do được biết đến?


nếu bạn không thể tìm ra điều này thì hãy sao chép nó trong prebuild của bạn.
Dilshod

Làm thế nào để bạn sử dụng 'ProjectX' của bạn trong dự án chính - loại dự án, mục tiêu, v.v.
NSGaga-hầu hết không hoạt động

Tôi đã có cùng một vấn đề và câu trả lời này đã giải quyết vấn đề của tôi: stackoverflow.com/a/8213977/174469
Gordon Tucker


RestoreProjectStyle giải pháp có sẵn . Ý tưởng là đặt <RestoreProjectStyle>PackageReference</RestoreProjectStyle>cho từng dự án .Net Framework trong giải pháp.
oleksa

Câu trả lời:


105

Tôi thấy rằng nếu ProjectX tham chiếu abc.dll nhưng không sử dụng trực tiếp bất kỳ loại DEFINED nào trong abc.dll, thì abc.dll sẽ KHÔNG được sao chép vào thư mục đầu ra chính. (Nó sẽ được sao chép vào thư mục đầu ra ProjectX, để làm cho nó thêm khó hiểu.)

Vì vậy, nếu bạn không sử dụng rõ ràng bất kỳ loại nào từ abc.dll ở bất cứ đâu trong ProjectX, thì hãy đặt một khai báo giả ở đâu đó trong một trong các tệp trong ProjectX.

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

Bạn không cần phải làm điều này cho mọi lớp - chỉ một lần là đủ để tạo bản sao DLL và mọi thứ hoạt động như mong đợi.

Phụ lục: Lưu ý rằng điều này có thể hoạt động cho chế độ gỡ lỗi, nhưng KHÔNG để phát hành. Xem câu trả lời của @ nvirth để biết chi tiết.


7
Điều này có vẻ như một hack. Thêm tài liệu tham khảo cho dự án chính dường như là đủ.
Mike K

3
Đây là một hack, nhưng như tin tức CodeProject ngày nay đã dạy chúng ta, ngay cả các trình biên dịch cũng có thể sai!
Overlord Zurg 10/03/2015

4
Làm thế nào những điều điên rồ có thể được. @OverlordZurg giải pháp của bạn đã hoạt động khi tôi có một tham chiếu đến dll phụ thuộc trong XAML (WPF) của tôi và nó đã không sao chép DLL vào dự án chính cho đến khi tôi thêm một tham chiếu giả đơn giản như bạn đã nói ... Dù sao cũng cảm ơn
Mohsen Afshin

5
@MohsenAfshin Tôi gặp vấn đề tương tự --- Tôi đã tham khảo một DLL phụ thuộc trong XAML. Tuy nhiên, thay vì khai báo một biến giả, tôi chỉ đơn giản đặt tên cho thành phần tôi đang sử dụng trong XAML và điều đó đủ để khiến tập hợp của nó bị sao chép.
redcurry

5
@MikeK Thêm nó vào dự án chính (không thực sự phụ thuộc trực tiếp vào nó) là một hack thậm chí còn lớn hơn, imo. Sau đó, bạn phải quản lý hai vị trí ("quản lý" như khi nâng cấp hoặc xóa). Với bản hack này , ít nhất bạn sẽ gặp một lỗi thời gian biên dịch đẹp, nhắc nhở bạn xóa bản hack này khi bạn loại bỏ phần phụ thuộc và bạn vẫn chỉ cần cập nhật nó ở một nơi.
jpmc26

70

Chỉ là một phụ bản cho câu trả lời của Overlord Zurg.

Tôi đã thêm tham chiếu giả theo cách này và nó hoạt động ở chế độ Gỡ lỗi:

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

Nhưng trong chế độ Phát hành, dll phụ thuộc vẫn không được sao chép.
Điều này làm việc tuy nhiên:

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

Thông tin này thực sự đã làm tôi mất hàng giờ để tìm ra, vì vậy tôi nghĩ rằng tôi chia sẻ nó.


6
trong chế độ phát hành, trình tối ưu hóa cho rằng "giả" không được sử dụng nên dòng này là không cần thiết và cần được loại bỏ. nhưng khi bạn sử dụng "hình nộm" trong mã, trình tối ưu hóa không cho rằng nó không cần thiết.
Yucel

1
điều này không hiệu quả với tôi.AbcDll.AnyClass vẫn không được sao chép sang dự án khác
Matthew Lock

3
Đảm bảo AbcDll.AnyClassđược sử dụng như một trường công khai hoặc tài sản trên một lớp công khai, sau đó nó sẽ hoạt động. Nếu bạn sử dụng nó trong một thân phương thức như thế này thì trình biên dịch sẽ không thấy nó . Nó sẽ trì hoãn tải lắp ráp này, không phải những gì bạn muốn xảy ra.
John Leidegren

52

Có, bạn sẽ cần phải đặt Copy Localthành true. Tuy nhiên, tôi khá chắc chắn bạn cũng sẽ cần phải tham khảo lắp ráp từ dự án chính và thiết lập Copy Localđể truecũng - nó không chỉ được sao chép từ một hội đồng phụ thuộc.

Bạn có thể đến Copy Localkhách sạn bằng cách nhấp vào cụm bên dưới Referencesvà nhấn F4.


2
@Brij, hội có được tham chiếu từ dự án chính mà bạn muốn không? Như tôi đã nói, tôi khá chắc chắn rằng bạn cần tham khảo từ dự án đó - các hội đồng phụ thuộc cũng không được sao chép như thế. Nếu đó là trường hợp bạn không cần phải thêm các hội đồng vào tất cả các dự án có liên quan khi sử dụng NuGet.
Mike Perrenoud

1
kết luận ở đây là gì? Dường như với tôi rằng bạn đúng - các tham chiếu phụ thuộc không được sao chép ngay cả khi CopyLocal được đặt thành đúng - logic đằng sau đó là gì?
mcmillab

29
@mcmillab, trong ngắn hạn Visual Studio không suy ra sự phụ thuộc từ các dự án phụ thuộc khác. Nếu dự án A tham chiếu dự án B, dự án A sẽ cần phải có tất cả các tài liệu tham khảo của dự án B. Nó hoạt động độc đáo khi tất cả các nhu cầu của dự án B là các hội đồng .NET, nhưng nếu đó là hội nghị bên thứ 3, bạn phải thêm tham chiếu cho cả hai dự án.
Mike Perrenoud 23/07/13

12
@MichaelPerrenoud Tôi không nghĩ đó là sự thật. Nếu bạn nhìn vào một đầu ra MSBuild chi tiết, bạn sẽ thấy các lệnh gọi tới ResolveAss lanhReference trong đó nêu rõ "bao gồm các phụ thuộc thứ hai và thứ n". Điều này cũng đồng tình với những gì tôi thấy trong các thư mục bin của mình (phụ thuộc thứ n được sao chép). Vấn đề là có một số cảnh báo về những gì được sao chép, chủ yếu là xung quanh GAC và các tài liệu tham khảo gián tiếp (Thêm tham khảo đôi khi không đủ)
Jack Ukleja

2
Kinh nghiệm hiện tại của tôi là điều này sẽ hoạt động ngoại trừ các phụ thuộc 'sao chép': dự án A.net tham chiếu các dll C ++ bên ngoài dưới dạng các tệp 'luôn luôn sao chép'. Tài liệu tham khảo Project B.net Project A. Khi xây dựng, B / Debug bao gồm các dll C ++. Tuy nhiên, khi tôi xây dựng Ứng dụng X, tham chiếu Project B, các dll C ++ đôi khi bị sao chép (dường như chỉ khi tôi thực hiện Rebuild).
Stewol

33

Nó trông trơn tru khi bạn làm cho nó một thuộc tính lắp ráp

[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);
    }
}

Việc sử dụng sẽ là:

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

Cảm ơn bạn, nhưng đối với tôi điều này chỉ làm một cái gì đó khi tôi thêm thuộc tính lắp ráp vào phụ thuộc (Project X), đã tham chiếu AbcDll.AnyClass. Và sau đó, nó không làm nhiều hơn bình thường, nơi nó sao chép AbcDll vào thư mục đầu ra của phụ thuộc. Nó vẫn không sao chép nó vào đầu ra của dự án phụ thuộc chính. Và tôi không thể thêm thuộc tính vào hội đồng phụ thuộc trừ khi tôi cũng thêm một tham chiếu đến AbcDll. Khi tôi làm điều đó, AbcDll đã được sao chép mà không có thuộc tính.
JS

25

Ran vào vấn đề tương tự. Thông tin cơ bản: trước khi xây dựng, tôi đã thêm một Dự án X mới vào giải pháp. Dự án Y phụ thuộc vào Dự án X và Dự án A, B, C phụ thuộc vào Dự án Y.

Lỗi xây dựng là các dll Project A, B, C, Y và X không thể tìm thấy.

Nguyên nhân sâu xa là Project X mới được tạo nhắm mục tiêu .NET 4.5 trong khi phần còn lại của các dự án giải pháp nhắm vào .NET 4.5.1. Dự án X không được xây dựng khiến các dự án còn lại cũng không xây dựng.

Hãy chắc chắn rằng bất kỳ Dự án mới được thêm nào đều nhắm đến cùng một phiên bản .NET như phần còn lại của giải pháp.


1
Các dự án được tham chiếu có thể là một phiên bản cũ hơn của .NET. Tôi có thể tham khảo một dự án được xây dựng cho .NET 4 bởi một dự án được xây dựng cho .NET 4.5.
redcurry

18

Không chắc chắn nếu điều này có ích nhưng đối với tôi, nhiều lần tôi tham chiếu một DLL (tất nhiên sẽ tự động thêm nó vào thư mục bin). Tuy nhiên, DLL có thể cần thêm DLL (tùy thuộc vào chức năng tôi đang sử dụng). Tôi KHÔNG muốn tham chiếu những người trong Dự án của mình vì họ chỉ cần kết thúc trong cùng một thư mục với DLL mà tôi thực sự đang sử dụng.

Tôi thực hiện điều này trong Visual Studio bằng cách "Thêm một tệp hiện có". Bạn sẽ có thể thêm nó ở bất cứ đâu ngoại trừ thư mục Add_data. Cá nhân tôi chỉ cần thêm nó vào thư mục gốc.

Sau đó thay đổi thuộc tính của tệp đó thành ...

Build Action = Không (có cài đặt này thành một cái gì đó như Nội dung thực sự sao chép phiên bản "root" vào thư mục gốc, cộng với một bản sao trong Thùng).

Sao chép vào thư mục đầu ra = Sao chép nếu Mới hơn (Về cơ bản chỉ đặt nó vào thư mục BIN nếu bị thiếu, nhưng sau đó không thực hiện được)

Khi tôi xuất bản .. DLL của tôi chỉ tồn tại trong thư mục BIN và không ở đâu khác trong vị trí Xuất bản (đó là những gì tôi muốn).


10

Bạn cũng có thể kiểm tra để đảm bảo các DLL bạn đang tìm kiếm không được bao gồm trong GAC. Tôi tin rằng Visual Studio đang thông minh về việc không sao chép các tệp đó nếu nó đã tồn tại trong GAC trên máy dựng.

Gần đây tôi đã chạy trong tình huống này khi tôi đang thử nghiệm gói SSIS cần lắp ráp tồn tại trong GAC. Tôi đã quên điều đó và tự hỏi tại sao những DLL đó không xuất hiện trong quá trình xây dựng.

Để kiểm tra những gì trong GAC (từ Dấu nhắc lệnh của nhà phát triển Visual Studio):

gacutil -l

Hoặc xuất ra một tệp để dễ đọc hơn:

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

Để loại bỏ một hội đồng:

gacutil -u MyProjectAssemblyName

Tôi cũng cần lưu ý rằng, một khi tôi xóa các tệp khỏi GAC, chúng được xuất chính xác trong thư mục \ bin sau khi xây dựng (Ngay cả đối với các cụm không được tham chiếu trực tiếp trong dự án gốc). Đây là trên Visual Studio 2013 Update 5.


Cảm ơn, bạn đã đúng, MSBuild sẽ không sao chép dll vào thư mục đầu ra nếu nó tìm thấy chúng trong GAC.
John-Philip

3

Trong trường hợp của tôi, đó là điều ngu ngốc nhất, gây ra bởi một hành vi mặc định của TFS / VS mà tôi không đồng ý.

Vì việc thêm dll làm tham chiếu cho dự án chính không hoạt động, tôi quyết định thêm nó dưới dạng "Mục hiện có", với Sao chép cục bộ = Luôn luôn. Thậm chí sau đó tập tin không có ở đó.

Hóa ra, mặc dù tệp có mặt trên Giải pháp VS và mọi thứ được biên dịch cả cục bộ và trên máy chủ, VS / TFS không thêm thực sự thêm tệp vào kiểm soát nguồn. Nó hoàn toàn không được bao gồm trong "Thay đổi đang chờ xử lý". Tôi đã phải tự đi đến Source Control Explorer và nhấp vào biểu tượng "Thêm mục vào thư mục".

Ngốc vì tôi đã phát triển 15 năm ở VS. Tôi đã gặp phải điều này trước đây, tôi chỉ không nhớ và bằng cách nào đó tôi đã bỏ lỡ nó vì mọi thứ vẫn được biên dịch vì tệp là tài liệu tham khảo thông thường, nhưng tệp được thêm dưới dạng Mục hiện tại không được sao chép vì nó không tồn tại máy chủ điều khiển nguồn.

Tôi hy vọng điều này sẽ giúp ai đó tiết kiệm thời gian, vì tôi đã mất 2 ngày trong cuộc đời này.


1
Tôi không thể cảm ơn bạn đủ ... bạn đã tiết kiệm cho tôi rất nhiều thời gian. Đây là giải pháp cho tôi. Nó cũng phơi bày vấn đề gốc, DLL tôi đã thêm làm tham chiếu khớp với một gitignoremẫu, vì vậy khi thêm làm tham chiếu, nó không thêm vào dự án. Bạn PHẢI tự thêm tệp vào kiểm soát nguồn !!!
Mattkwish

2

Đây là một điều chỉnh nhỏ về ví dụ của nvirth

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

2

Tôi sẽ thêm nó vào các sự kiện Postbuild để sao chép các thư viện cần thiết vào các thư mục đầu ra. Một cái gì đó giống như thư mục thư mục XCopy

Bạn có thể tìm thấy chúng trên các thuộc tính dự án -> Xây dựng sự kiện.


Điều này làm việc cho tôi, và tôi nghĩ rằng đây là câu trả lời tốt hơn. Giải pháp tham chiếu giả hoạt động, nhưng đó là một hack, trong khi quy tắc hậu xây dựng là một cách rõ ràng để thực hiện cùng một kết quả.
Kevin Fichter

2

Vấn đề:

Gặp phải một vấn đề tương tự đối với gói NuGet DLL (Newtonsoft.json.dll) trong đó đầu ra bản dựng không bao gồm DLL được tham chiếu. Nhưng việc biên dịch đi qua tốt đẹp.

Sửa chữa:

Đi qua các dự án của bạn trong một trình soạn thảo văn bản và tìm kiếm các tài liệu tham khảo với các thẻ trong đó. Thích Đúng hay Sai. Tư nhân ăn ý là một từ đồng nghĩa với bản sao Sao chép. Ở đâu đó trong các hành động, MSBuild đang thực hiện để xác định vị trí phụ thuộc, nó tìm thấy sự phụ thuộc của bạn ở một nơi khác và quyết định không sao chép nó.

Vì vậy, hãy đi qua từng tệp .csproj / .vbproj và xóa các thẻ theo cách thủ công. Xây dựng lại và mọi thứ hoạt động trong cả Visual Studio và MSBuild. Khi bạn đã làm việc đó, bạn có thể quay lại và cập nhật địa điểm mà bạn nghĩ họ cần.

Tài liệu tham khảo:

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


1

KHÔNG CẦN DUMMY TRONG MÃ
Chỉ:

thêm một tài liệu tham khảo cho dự án thực thi

hoặc / và đảm bảo rằng tham chiếu trong dự án thực thi đã "Copy Local"được đặt thành TRUE(đó là " lỗi " của tôi ) có vẻ như "ghi đè" cài đặt này trong dự án thư viện tham chiếu cơ sở ...


1

Nếu bạn nhấp vào hội đồng được tham chiếu, bạn sẽ thấy một thuộc tính có tên là Copy Local . Nếu Copy Local được đặt thành true, thì lắp ráp sẽ được bao gồm trong thùng. Tuy nhiên , có một số vấn đề với Visual studio, đôi khi nó không bao gồm dll được tham chiếu trong thư mục bin ... đây là cách giải quyết phù hợp với tôi:

nhập mô tả hình ảnh ở đây


1
Sao chép Loal đã bị vô hiệu hóa, điều này đã giúp stackoverflow.com/questions/15526491/ cấp
codemirror

1

TLDR; Visual Studio 2019 có thể chỉ cần khởi động lại.

Tôi đã gặp tình huống này khi sử dụng các dự án dựa trên dự án Microsoft.NET.Sdk.

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

Đặc biệt:

  • Project1: mục tiêu .netstandard2.1
    • tài liệu tham khảo Microsoft.Extensions.Logging.Consolequa Nuget
  • Project2: mục tiêu .netstandard2.1
    • tài liệu tham khảo Project1thông qua tài liệu tham khảo Dự án
  • Project2Tests: mục tiêu .netcoreapp3.1
    • tài liệu tham khảo Project2thông qua tài liệu tham khảo Dự án

Khi thực hiện kiểm tra, tôi nhận được thông báo lỗi cho biết Microsoft.Extensions.Logging.Consolekhông thể tìm thấy và thực sự nó không có trong thư mục đầu ra.

Tôi đã quyết định giải quyết vấn đề bằng cách thêm Microsoft.Extensions.Logging.Consolevào Project2, chỉ để phát hiện ra rằng Trình quản lý Nuget của Visual Studio không liệt kê Microsoft.Extensions.Logging.Consolenhư đã cài đặt Project1, mặc dù có sự hiện diện trong Project1.csprojtệp.

Việc tắt và khởi động lại đơn giản của Visual Studio đã giải quyết vấn đề mà không cần thêm tài liệu tham khảo. Có lẽ điều này sẽ giúp ai đó tiết kiệm được 45 phút năng suất bị mất :-)


Trên thực tế, tôi đã khởi động lại toàn bộ PC trên đường thử nghiệm mọi thứ nhưng nó hoạt động với tôi
Noman_1

0

Bạn có thể đặt cả đường dẫn đầu ra xây dựng của dự án chính và ProjectX vào cùng một thư mục, sau đó bạn có thể nhận được tất cả các dll bạn cần trong thư mục đó.


0

Đảm bảo rằng dll phụ thuộc mà bạn sử dụng không có khung .net đích cao hơn khung .net đích của Ứng dụng dự án của bạn.

Bạn có thể kiểm tra điều này bằng cách chọn dự án của bạn, sau đó nhấn ALT + ENTER, sau đó chọn Ứng dụng từ bên trái và sau đó chọn Khung mục tiêu của dự án của bạn.

Giả sử, khung phụ thuộc dll Target = 4.0 và Application dll Target Framework = 3.5 sau đó thay đổi thành 4.0

Cảm ơn bạn!


0

Khác với những cái phổ biến ở trên, tôi đã có một giải pháp đa dự án để xuất bản. Rõ ràng một số tệp nhắm mục tiêu các khung khác nhau.

Vì vậy, giải pháp của tôi: Thuộc tính> Phiên bản cụ thể (Sai)


0

Thêm DLL như một mục hiện có vào một trong các dự án và nó sẽ được sắp xếp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.