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