Как получить проекты .NET Core для копирования ссылок NuGet для сборки вывода?

Я пытаюсь написать плагиновую систему с .NET Core, и одним из моих требований является возможность распространения DLL плагина вместе с его зависимостями с пользователем для установки. Тем не менее, я не могу понять, как включить мои зависимости NuGet в качестве артефакта сборки и вывести их в папку сборки, не используя dotnet publish как взломать. Есть ли способ указать это в csproj?

Ответ 1

Вы можете добавить это к <PropertyGroup> внутри вашего файла csproj, чтобы принудительно скопировать сборки NuGet на встроенный вывод:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

Однако обратите внимание, что вывод сборки (bin/Release/netcoreapp*/*) не должен быть переносимым и распространяемым, выход dotnet publish есть. Но в вашем случае копирование сборок на вывод сборки, вероятно, очень полезно для целей тестирования. Но обратите внимание, что вы также можете использовать DependencyContext api для разрешения DLL и их местоположений, которые являются частью графика зависимостей приложения, вместо перечисления локального каталога.

Ответ 2

Вы можете использовать PostBuildEvent для автоматизации развертывания модулей при сборке.

Чтобы получить сборки NuGet в папке сборки, добавьте csproj вашего модуля

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

Определите, какие файлы модулей вы хотите использовать с помощью Include/Exclude (при необходимости измените путь)

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

Reset ваша сборка по умолчанию и добавьте 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 для утилизации приложения, если он уже работает, чтобы избежать ошибок использования файла.

Ответ 3

Я "решил" (создал обходной путь) это проще.

В пост сборки

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

pub - это папка, в которую вы хотите, чтобы ваши опубликованные материалы были отправлены

ПРИМЕЧАНИЕ: в зависимости от того, какую версию dotnet.exe вы используете, команда --no-build может быть недоступна.

Например, недоступно в версии 2.0.3; и доступно в v2.1.402. Я знаю, что VS2017 Update4 был v2.0.3. И у Update8 есть 2.1.x

Обновить:

Вышеуказанная настройка будет работать в базовой среде отладки, но для ее установки в среду сборки/производственную среду требуется больше. В этом конкретном примере, который мне пришлось решить, мы строим Release|x64 и Release|x86 отдельно. Так что я учел оба. Но для поддержки dotnet publish после сборки 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 и сбой сборки, если она появляется. Это предупреждение говорит: "Эй, некоторые файлы в ваших зависимостях имеют неправильный формат". Но помните ли вы цель этого упражнения? Нам нужно извлечь библиотеки зависимостей пакетов. И во многих случаях не имеет значения, присутствует ли это предупреждение, потому что после пост-сборки все равно. Опять же, это моя программа сборки, которая заботится. Итак, я только добавил RuntimeIdentifier к 2 конфигурациям, которые я использую во время производственной сборки.

Полный пост сборки

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

Объяснение: dotnet publish ищет obj\Debug или obj\Release. У нас его нет во время сборки, потому что сборка создает obj\x64\Release или obj\x86\Release. Строки 1 и 2 смягчают эту проблему. В строке 3 я dotnet.exe использовать конкретную конфигурацию и целевую среду выполнения. В противном случае, когда это режим отладки, мне наплевать на время выполнения и предупреждения. И в последней строке я просто беру мои библиотеки и затем копирую их в выходную папку. Работа выполнена.

Ответ 4

Добавление

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

не работает, но добавив это в файл Framework.csproj:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

сделал.

Ответ 5

В сочетании с ответом, приведенным выше: у меня это прекрасно работает в командной строке события после сборки: в Visual Studio. Он перебирает выбранные библиотеки DLL (System *.dll и Microsoft.dll) *, а затем пропускает удаление определенных библиотек DLL. 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