[.NET, C#] Уменьшить размер консольного .NET 5.0 приложения
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Target Framework MonikerДавайте знакомиться. В .NET 5.0 для использования Windows Forms или WPF нам недостаточно просто указать net5.0:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
При попытке использования Windows Forms или WPF мы получаем ошибку
C:\Program Files\dotnet\sdk\5.0.201\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets(369,5): error NETSDK1136: The target platform must be set to Windows (usually by including '-windows' in the TargetFramework property) when using Windows Forms or WPF, or referencing projects or packages that do so.
Решение, как подсказывает ошибка состоит в указании Target Framework Moniker
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
Как это работаетПри сборки автоматически импортируются файлы из Microsoft.NET.Sdk\targets.
Далее в dotnet\sdk\5.0\Sdks\Microsoft.NET.Sdk.WindowsDesktop\targets\Microsoft.NET.Sdk.WindowsDesktop.props содержиться код:
<FrameworkReference Include="Microsoft.WindowsDesktop.App" IsImplicitlyDefined="true"
Condition="('$(UseWPF)' == 'true') And ('$(UseWindowsForms)' == 'true')"/>
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" IsImplicitlyDefined="true"
Condition="('$(UseWPF)' == 'true') And ('$(UseWindowsForms)' != 'true')"/>
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" IsImplicitlyDefined="true"
Condition="('$(UseWPF)' != 'true') And ('$(UseWindowsForms)' == 'true')"/>
Где проблемаДело в том, что FrameworkReference это транзитивная зависимость: Документ дизайна .NET , Документация NuGetЭто значит, что если у нас есть где-то сборка, которая использует тип из Windows Forms или из WPF мы должны будем все зависимые сборки перевести на 'net5.0-windows'.Это грозит нам тем, что мы добавляем в резузльтатирующий файл потенциально ненужный хлам.Если весь код использует Windows Forms или WPF проблемы нет, а если мы в итоге создаём консольное приложение то получаем дополнительные 60МБ при создании самодостаточного файла.ПримерБиблиотека
using System.Windows.Forms;
namespace Library
{
public class Demo
{
void ShowForm()
{
var f = new Form();
f.Show();
}
}
}
Консольное приложение
using System;
class Program
{
public static void Main()
{
Console.WriteLine("Hello World!");
}
}
Обратим внимание, что мы не используем класс Library.Demo.Соберём самодостаточное приложение с помощью dotnet publish:
dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
Результат 81,8МБ !Благодаря IncludeAllContentForSelfExtract при запуске приложение в %TEMP%\.net мы можем посмотреть из чего оно состоит.
Как же так ?
Мы не использовали Library.Demo, мы указали PublishTrimmed, а Windows Forms к нам пришёл.РешениеКак видим dotnet publish при обычных настройках не справился со своей работой, поэтому поможем ему !Шаг 1В библиотеке укажем вручную зависимость фреймворка и попросим не создавать транзитивную зависимость:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<!-- Укажем зависимости явно -->
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<!-- .NET Runtime -->
<!-- В данном случае неважно будет PrivateAssets="all" или нет, всегда добавляется при сборке -->
<FrameworkReference Include="Microsoft.NETCore.App" />
<!-- Windows Desktop -->
<!-- PrivateAssets="all" - зависимость не идёт дальше -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" PrivateAssets="all" />
<!-- Можно указать и более конкретно:
Microsoft.WindowsDesktop.App.WPF
Microsoft.WindowsDesktop.App.WindowsForms -->
</ItemGroup>
</Project>
Документация для DisableImplicitFrameworkReferenceКлючевая часть PrivateAssets="all". которая не даёт зависимости распространяться дальше.Шаг 2Меняем .net5.0-windows на .net5.0 в нашем консольном приложенииРезультатСобираем той же командой:
dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
Получаем файл размером всего 18.8МБ со следующим содержимым
ЗаключениеСтоит ли делать так в библиотеках ?
Однозначно да !
С одной стороны это позволяет использовать типы из Windows Forms или WPF, с другой стороны у сборщика получается выкинуть всё неиспользованное и выдать меньший размер файла.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, .NET, Компиляторы, C#, WebAssembly] Ahead-of-Time компиляция и Blazor
- [.NET, Машинное обучение] Посмотрим на девочек? Или ml.net в работе
- [.NET] Нюансы при работе с EF миграциями
- [Ненормальное программирование, Поисковые технологии, Python, Игры и игровые приставки] Однажды Microsoft забанила всю мою страну за читерство (перевод)
- Выпуск среды разработки PascalABC.NET 3.8
- [Разработка веб-сайтов, .NET, C#, Функциональное программирование] От внедрения зависимостей к отказу от зависимостей
- [C#, Serverless] Создание превью картинок в объектном хранилище с помощью Yandex Cloud Functions
- [.NET, C#] SmartTraits or lets add «multiple inheritance» to C#
- [.NET, C#, Профессиональная литература] Книга «Паттерны проектирования для C# и платформы .NET Core»
- [Программирование, .NET, Алгоритмы, C#, Математика] Compilation of math functions into Linq.Expression
Теги для поиска: #_.net, #_c#, #_.net_5, #_.net, #_csharp, #_.net, #_c#
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 07:23
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Target Framework MonikerДавайте знакомиться. В .NET 5.0 для использования Windows Forms или WPF нам недостаточно просто указать net5.0: <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <UseWindowsForms>true</UseWindowsForms> </PropertyGroup> C:\Program Files\dotnet\sdk\5.0.201\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets(369,5): error NETSDK1136: The target platform must be set to Windows (usually by including '-windows' in the TargetFramework property) when using Windows Forms or WPF, or referencing projects or packages that do so.
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework> <UseWindowsForms>true</UseWindowsForms> </PropertyGroup> Далее в dotnet\sdk\5.0\Sdks\Microsoft.NET.Sdk.WindowsDesktop\targets\Microsoft.NET.Sdk.WindowsDesktop.props содержиться код: <FrameworkReference Include="Microsoft.WindowsDesktop.App" IsImplicitlyDefined="true"
Condition="('$(UseWPF)' == 'true') And ('$(UseWindowsForms)' == 'true')"/> <FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" IsImplicitlyDefined="true" Condition="('$(UseWPF)' == 'true') And ('$(UseWindowsForms)' != 'true')"/> <FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" IsImplicitlyDefined="true" Condition="('$(UseWPF)' != 'true') And ('$(UseWindowsForms)' == 'true')"/> using System.Windows.Forms;
namespace Library { public class Demo { void ShowForm() { var f = new Form(); f.Show(); } } } using System;
class Program { public static void Main() { Console.WriteLine("Hello World!"); } } dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
Как же так ? Мы не использовали Library.Demo, мы указали PublishTrimmed, а Windows Forms к нам пришёл.РешениеКак видим dotnet publish при обычных настройках не справился со своей работой, поэтому поможем ему !Шаг 1В библиотеке укажем вручную зависимость фреймворка и попросим не создавать транзитивную зависимость: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <TargetFramework>net5.0</TargetFramework> <!-- Укажем зависимости явно --> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> </PropertyGroup> <ItemGroup> <!-- .NET Runtime --> <!-- В данном случае неважно будет PrivateAssets="all" или нет, всегда добавляется при сборке --> <FrameworkReference Include="Microsoft.NETCore.App" /> <!-- Windows Desktop --> <!-- PrivateAssets="all" - зависимость не идёт дальше --> <FrameworkReference Include="Microsoft.WindowsDesktop.App" PrivateAssets="all" /> <!-- Можно указать и более конкретно: Microsoft.WindowsDesktop.App.WPF Microsoft.WindowsDesktop.App.WindowsForms --> </ItemGroup> </Project> dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
ЗаключениеСтоит ли делать так в библиотеках ? Однозначно да ! С одной стороны это позволяет использовать типы из Windows Forms или WPF, с другой стороны у сборщика получается выкинуть всё неиспользованное и выдать меньший размер файла. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 07:23
Часовой пояс: UTC + 5