[.NET, C#] Shrinking .NET Console Application (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Target Framework MonikerLet's start. .NET 5.0 doesn't allow using Windows Forms or WPF by specifying net5.0:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
We get the following error:
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 suggests the correct solution by specifying net5.0-windows:
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
How does it work ?During the build, the build files from Microsoft.NET.Sdk\targets are implicitly imported.
Inside dotnet\sdk\5.0\Sdks\Microsoft.NET.Sdk.WindowsDesktop\targets\Microsoft.NET.Sdk.WindowsDesktop.props there are following lines:
<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')"/>
What is the problem ?The thing is that FrameworkReference is a transitive dependency: .NET Targeting, Runtime and AppHost Packs, FrameworkReference in NuGet.This means that when there is an assembly using any type from Windows Forms or from WPF, we must specify 'net5.0-windows' in all dependent projects.As a result we potentially add unwanted bloat to the output file.It is not a problem when your program is Windows Forms or WPF, however it is a problem when you want a console application and you end up with additional 60MB.Our use-caseClass Library project:
using System.Windows.Forms;
namespace Library
{
public class Demo
{
void ShowForm()
{
var f = new Form();
f.Show();
}
}
}
Console application with reference to Class Library.
using System;
class Program
{
public static void Main()
{
Console.WriteLine("Hello World!");
}
}
We only reference the Class Library project, yet we do not use Library.Demo class.Let's build using dotnet publish:
dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
Output size: 81,8MB!Thanks to IncludeAllContentForSelfExtract when the application is executed we can see the internal content inside %TEMP%\net:
But, why ?
We did not use Library.Demo, we do use PublishTrimmed, and yet we have Windows Forms dlls.SolutionAs we see dotnet publish is not being able to do its job and remove unused dependencies. Let's help !Step 1Inside Class Library, we specify framework references explicitly and make it non-transitive.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<!-- Use explicit -->
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<!-- .NET Runtime -->
<!-- PrivateAssets="all" here doesn't do anything, this reference is always added -->
<FrameworkReference Include="Microsoft.NETCore.App" />
<!-- Windows Desktop -->
<!-- PrivateAssets="all" - non-transitive dependency -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" PrivateAssets="all" />
<!-- We can be more specific
Microsoft.WindowsDesktop.App.WPF
Microsoft.WindowsDesktop.App.WindowsForms -->
</ItemGroup>
</Project>
Documentation of DisableImplicitFrameworkReferenceThe key point here is PrivateAssets="all" which stops transitive dependency.Step 2Replace .net5.0-windows with .net5.0 inside our console application.The resultUsing the same build command as before:
dotnet publish ConsoleApp.csproj --self-contained -c Release -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeAllContentForSelfExtract=true
The output file is just 18.8MB size with the following content:
ConclusionShall I use this in my library ?Definitely yes !On the one hand this makes it possible to create a library which uses types from Windows Forms or WPF, on the other hand the dotnet publishing is able to throw away unused framework references and produce a much smaller file.
===========
Источник:
habr.com
===========
===========
Автор оригинала: NN
===========Похожие новости:
- [Open source, .NET, C#] Избавляемся от постоянного написания конструкторов для инжекта зависимостей с помощью C# Source Generators
- [.NET, C#, Программирование микроконтроллеров, Интернет вещей, DIY или Сделай сам] .NET nanoFramework — платформа для разработки приложений на C# для микроконтроллеров
- [C#, Unity] Основы Unity + Mirror
- [.NET, C#] Уменьшить размер консольного .NET 5.0 приложения
- [Разработка веб-сайтов, .NET, Компиляторы, C#, WebAssembly] Ahead-of-Time компиляция и Blazor
- [.NET, Машинное обучение] Посмотрим на девочек? Или ml.net в работе
- [.NET] Нюансы при работе с EF миграциями
- [Ненормальное программирование, Поисковые технологии, Python, Игры и игровые приставки] Однажды Microsoft забанила всю мою страну за читерство (перевод)
- Выпуск среды разработки PascalABC.NET 3.8
- [Разработка веб-сайтов, .NET, C#, Функциональное программирование] От внедрения зависимостей к отказу от зависимостей
Теги для поиска: #_.net, #_c#, #_.net, #_.net_5, #_csharp, #_.net, #_c#
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:19
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Target Framework MonikerLet's start. .NET 5.0 doesn't allow using Windows Forms or WPF by specifying 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> Inside dotnet\sdk\5.0\Sdks\Microsoft.NET.Sdk.WindowsDesktop\targets\Microsoft.NET.Sdk.WindowsDesktop.props there are following lines: <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
But, why ? We did not use Library.Demo, we do use PublishTrimmed, and yet we have Windows Forms dlls.SolutionAs we see dotnet publish is not being able to do its job and remove unused dependencies. Let's help !Step 1Inside Class Library, we specify framework references explicitly and make it non-transitive. <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <TargetFramework>net5.0</TargetFramework> <!-- Use explicit --> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> </PropertyGroup> <ItemGroup> <!-- .NET Runtime --> <!-- PrivateAssets="all" here doesn't do anything, this reference is always added --> <FrameworkReference Include="Microsoft.NETCore.App" /> <!-- Windows Desktop --> <!-- PrivateAssets="all" - non-transitive dependency --> <FrameworkReference Include="Microsoft.WindowsDesktop.App" PrivateAssets="all" /> <!-- We can be more specific 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
ConclusionShall I use this in my library ?Definitely yes !On the one hand this makes it possible to create a library which uses types from Windows Forms or WPF, on the other hand the dotnet publishing is able to throw away unused framework references and produce a much smaller file. =========== Источник: habr.com =========== =========== Автор оригинала: NN ===========Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:19
Часовой пояс: UTC + 5