Як змусити .NET Core проекти копіювати посилання NuGet на вихід збірки?


109

Я намагаюся написати систему плагінів за допомогою .NET Core, і одна з моїх вимог полягає в тому, щоб мати можливість поширювати DLL плагіна разом з його залежностями користувачеві для встановлення.

Однак я не можу зрозуміти, як включити мої залежності NuGet як артефакт збірки і вивести їх у папку збірки, не використовуючи dotnet publishяк хак. Чи я можу вказати це у файлі .csproj (файл проекту)?


2
Навіщо використовувати dotnet publishhack? Включіть команду у свій файл csproj як сценарій створення збірки.
Остін Дренскі

3
dotnet publishвикидає весь фреймворк у папку публікації, оскільки я пишу плагін, більшість файлів не потрібні, оскільки рамка вже буде завантажена програмою завантажувача. Я шукаю щось подібне до того, як будують роботу на .NET Framework.
chyyran

І в тому числі, якщо <CopyToOutputDirectory>Always</CopyToOutputDirectory>у вашому csproj на кожній з дільниць, які ви хочете перенести, це не виходить? Можливо, поєднується з <link>вузлом?
Остін Дренскі

7
<PackageReference/>не підтримує <CopyToOutputDirectory>.
чийран

1
«Цілий фреймворк» походить від NuGet, хоча .. і якщо ви вирішите скопіювати всі збори NuGet на вихідний збір, ви отримаєте всі вони ..
Мартін Улріх

Відповіді:


178

Ви можете додати це <PropertyGroup>всередину свого файлу csproj для примусового копіювання збірок NuGet до виводу збірки:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

Однак зауважте, що висновок збірки ( bin/Release/netcoreapp*/*) не повинен бути портативним та розповсюджуваним, вихід dotnet publishє. Але у вашому випадку копіювання складання на вихідний збірник, ймовірно, дуже корисне для тестування. Але зауважте, що ви також можете використовувати DependencyContextapi для вирішення DLL та їх розташування, які є частиною графіка залежності програми, а не для перерахування локального каталогу.


7
Це спричиняє копіювати всі dll, а не лише Nuget
Mohammad Dayyan

2
Core 2 Я отримую і всі DLL Microsoft. Не впевнений, чому, але до того, як я отримував лише NuGet, але потім він перестав це робити? дратує
Петро Кула

4
@MartinUllrich Чи можете ви детальніше розглянути питання про те DependencyContext? Як я можу використовувати його для пошуку DLL, який відсутній у каталозі програм? Де це все-таки?
ygoe

2
не працює для мене ядро ​​asp.net не копіює System.ValueTuple.dll
Алі Юсефі

1
@AliYousefie system.valuietuple для .net-рамкових проектів більше не повинен надходити з NuGet на останніх версіях .net-фреймворку та розробляти інструменти
Martin Ullrich

10

Ви можете використовувати PostBuildEvent для автоматизації розгортання модулів під час збирання.

Щоб отримати збірки NuGet у папці збірки, додайте csproj свого модуля

<PropertyGroup>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>

Визначте, які файли модулів ви хочете, коли використовуєте Включити / Виключити (змінити шлях за необхідності)

<ItemGroup>
    <ModuleFiles
      Include="$(TargetDir)*.dll"
      Exclude="$(TargetDir)System*.dll;$(TargetDir)Microsoft*.dll"
      DestinationPath="$(SolutionDir)src\MyProject\Modules\MyModule\%(Filename)%(Extension)">
    </ModuleFiles>
</ItemGroup>

Скиньте папку збирання за замовчуванням та додайте PostbuildEvent

<Target Name="PublishModule" AfterTargets="PostBuildEvent" Inputs="@(ModuleFiles)" Outputs="@(ModuleFiles->'%(DestinationPath)')">
    <WriteLinesToFile File="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
    <Copy SourceFiles="@(ModuleFiles)" DestinationFiles="@(ModuleFiles->'%(DestinationPath)')" />
    <Delete Files="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
</Target>

Я включаю app_offline для переробки програми, якщо вона вже запущена, щоб уникнути помилок у використанні файлів.


У своєму проекті я маю залежність від бібліотеки Nuget "Microsoft.Extensions.Logging.Log4Net.AspNetCore", і це не частина NetCore, тому такий підхід не буде працювати
sad_robot

4

Додавання

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

не працювало, але додавши це до файлу Framework .csproj:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

зробив.


Це добре працювало для мене, коли я посилався на .net Standard 2.0 бібліотеки з проекту .Net Framework 4.7.2. Ніщо інше це не виправило.
Грунгондола

3

Я "вирішив" (створив обхід) цим простішим способом.

На посаді

dotnet publish "$(ProjectFileName)" --no-build -o pub
xcopy "$(ProjectDir)pub\3rdPartyProvider.*.dll" "$(OutDir)"

pub - це папка, в яку ви хочете, щоб ваші опубліковані матеріали йшли для постановки

ПРИМІТКА. Залежно від версії, dotnet.exeяку ви використовуєте, команда --no-buildможе бути недоступною.

Наприклад, недоступний у v2.0.3; і доступний у версії 2.12.42. Я знаю, що VS2017 Update4 мав v2.0.3. І Update8 має 2.1.x

Оновлення:

Налаштування, описане вище, буде працювати в базовій середовищі налагодження, але для його введення в середовище побудови сервера / виробництва потрібно більше. У цьому конкретному прикладі, який мені довелося вирішити, ми будуємо Release|x64і Release|x86окремо. Тож я склав обоє. Але щоб підтримати команду post build dotnet publish, я спершу додав RuntimeIdentifierдо файлу проекту.

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
  <OutputPath>..\..\lib\</OutputPath>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
  <OutputPath>..\..\lib\</OutputPath>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>

Навіщо мені це було потрібно і чому ви можете піти без нього? Мені це було потрібно, тому що моя програма збірки налаштована на перехоплення попередження MSB3270 , і не вийде збірка, якщо вона з'явиться. Це попередження говорить: "Ей, деякі файли у ваших залежностях мають неправильний формат". Але ви пам’ятаєте мету цієї вправи? Нам потрібно витягнути DLL-файли залежності від пакета. І в багатьох випадках не має значення, чи існує таке попередження, оскільки наступне створення повідомлення не має значення. Знову ж таки, це моя програма побудови. Отже, я додав лише RuntimeIdentifier2 конфігурації, які використовую під час створення збірки.

Повна збірка повідомлення

if not exist "$(ProjectDir)obj\$(ConfigurationName)" mkdir "$(ProjectDir)obj\$(ConfigurationName)"
xcopy  "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)" "$(ProjectDir)obj\$(ConfigurationName)" /E /R /Y

if $(ConfigurationName) == Release (
    dotnet publish "$(ProjectFileName)" --runtime win-$(PlatformName) --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
) else (
    dotnet publish "$(ProjectFileName)" --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
)

xcopy "$(ProjectDir)pub\my3rdPartyCompany.*.dll" "$(OutDir)" /Y /R

Пояснення: дотнет публікація шукає obj\Debugабо obj\Release. У нас його немає під час збирання, оскільки build створює obj\x64\Releaseабо obj\x86\Release. Рядок 1 і 2 пом'якшують це питання. У рядку 3 я кажу dotnet.exeпро використання конкретної конфігурації та цільового часу виконання. В іншому випадку, коли це режим налагодження, я не переймаюся елементами виконання та попередженнями. І в останньому рядку я просто беру свої копи і копіюю потім у вихідну папку. Робота виконана.


Параметр "-c Release" необхідний для команди "дотнет опублікувати", якщо проект не має конфігурації налагодження (як у моєму випадку). Тому я використав цю партію як події після збирання: dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
Xtro

0

У поєднанні з вищенаведеною відповіддю: у мене це чудово працює в командному рядку подій після складання: у Visual Studio. Він перебирає вибір на dlls (System * .dll та Microsoft .dll) *, а потім пропускає видалення конкретних dlls. System.Data.SqlClient.dll і System.Runtime.Loader.dll

for %%f in ($(OutDir)System*.dll $(OutDir)Microsoft*.dll) do if not %%f == $(OutDir)System.Data.SqlClient.dll if not %%f == $(OutDir)System.Runtime.Loader.dll del %%f
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.