Комментарии 26
-p:PublishSingleFile=true
, дописывать в конце --self-contained true
не имеет смысла, первый параметр это и так подразумевает, в чем можно можно убедиться, запустив публикацию сборки.-p:PublishSingleFile=true — включает компиляцию всех зависимостей в один общий .exe файл. То есть этот файл может, как быть зависимым от среды, так и независимым.
Источник: docs.microsoft.com/ru-ru/dotnet/core/deploying/single-file#publish-a-single-file-app---cli
Вы совершенно напрасно минуснули мой комментарий ) Как и заметил комментатор ниже, в официальных примерах указывается что при указании параметра -p:PublishSingleFile=true,
параметр --self-contained true
используется по умолчанию. И его наоборот приходится отключать явно указывая false:
https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md
-p:EnableCompressionInSingleFile=true
включает zlib сжатие сборок в single file, опция доступна только при использовании .NET 6 SDK Preview 4 и выше. Размер файла уменьшится дополнительно еще примерно в 2 раза.--self-contained true
при публикации с -p:PublishSingleFile=true
используется по умолчанию.-p:IncludeNativeLibrariesForSelfExtract=true
позволяет включить в единый файл нативные зависимости, чтобы они после публикации не лежали рядом с исполняемым файлом. Опция точно доступна в .NET 5.0 SDK, а может и более ранних.Например тут https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file или тут https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md.
Про сжатие вряд ли где-то написано, т.к. эта фича появилась недавно https://github.com/dotnet/runtime/pull/50817
https://github.com/dotnet/sdk/pull/16838
Вот тут про сжатие упоминается https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/
Странно. У меня на .NET 6 SDK Preview 4 получаются такие результаты с пустым WinForms проектом:
SingleFile+Trim+Link=87.9MB
SingleFile+Trim+Copy=87.9MB
SingleFile+Trim+Link+Compress=41.1MB
SingleFile+Trim+Copy+Compress=41.1MB
SingleFile=134MB
SingleFile+Compress=61MB
(размеры указаны без учета нативных библиотек, лежащих рядом с исполняемым файлом)
Похоже что опция Link не работает, т.к. на размер она никак не влияет...
Оказывается TrimMode=Link на .NET 6 используется по умолчанию, и при попытке поменять его на CopyUsed никакой разницы не наблюдается.
clrjit.dll
coreclr.dll
D3DCompiler_47_cor3.dll
mscordaccore.dll
PenImc_cor3.dll
PresentationNative_cor3.dll
vcruntime140_cor3.dll
wpfgfx_cor3.dll
По сравнению с обычной публикацией, когда на выходе целая куча файлов, наличие 10 вместо одного не напрягает. Но всё-же, single file app должен быть single file app.
По существу вопроса, в том же самом проекте, при включении опции обрезки на уровне неиспользуемых сборок, происходит забавная штука: асинхронные команды WPF стартуют, то есть вызов из интерфейса проходит, но до пользовательского кода управление не доходит. В итоге кнопки нажимаются, но ничего не происходит. Отключение обрезки решает проблему — всё работает как должно. Публикую приложение не из командной строки, а из-под Visual Studio 16.8.? (сейчас 16.9.5, но последняя публикация проводилась ещё в 16.8).
Приложение используется для внутренних нужд, поэтому ошибка была не критичной и пересборка без обрезки вполне устраивает.
PS: Долго ждал .NET 5, но оказалось, что и он не решает проблем с доставкой до клиента. По-прежнему, чтобы доставить клиенту что-то небольшое по размеру, приходится использовать .NET Framework 4.5, так как он скорее всего уже есть у клиента. Надеяться на то, что у клиента установлен .NET 5 пока нельзя, а заставлять скачивать 100 МБ для чего-то маленького (условно, калькулятор) — кажется расточительно.
Одно хорошо, что результат относительно неплохо сжимается (в моём случае ~50%).
С опцией PublishSingleFile, помимо непосредственно .exe файла размером 135 МБ, я получаю ещё дополнительный набор файлов.
Так используйте опцию
-p:IncludeNativeLibrariesForSelfExtract=true
и нативные зависимости тоже упакуются в единый файл. По умолчанию они располагаются рядом с исполняемым файлом.Я бы отнёс это к категории вредных советов.
Да, использование опции IncludeNativeLibrariesForSelfExtract
приведёт к тому, что файл станет один, зато приложение сначала будет распаковываться во временную директорию со всеми потрохами, а уже оттуда запускаться.
То есть вся польза от упаковки в один файл сходит на нет. С гораздо большим успехом можно просто заархивировать дистрибутив программы.
Распаковываться будут только нативные зависимости, коих обычно не больше 10, а не все потроха, причем только при первом запуске. При последующих запусках будут использоваться распакованные библиотеки. Не вижу в этом проблемы.
Нет. Вот здесь:
https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file#other-considerations
вполне конкретно написано:
Specifying IncludeAllContentForSelfExtract
will extract all files before running the executable. This preserves the original .NET Core single-file deployment behavior.
Original behavior — это поведение .NET Core 3.1, когда приложение распаковывалось целиком на диск, а не в память.
При последующих запусках будут использоваться распакованные библиотеки.
Которые занимают место на диске, помимо собственно упакованного файла. Это и есть проблема.
Вообще-то IncludeAllContentForSelfExtract
и IncludeNativeLibrariesForSelfExtract
не одно и тоже… Совершенно разные опции…
Ну и во многих случаях важнее иметь единый файл, чем потерять 10 МБ места на диске из-за распакованных файлов. Например у консольных приложений вообще нет никаких нативных зависимостей (если их самому не добавить), они из коробки имеются только у WinForms и WPF.
Кстати, а что за проблемы с отладкой были при использовании PublishTrimmed и TrimMode=Link?
Я имел в виду что если запустить его под отладчиком, то по идее должно показать где проблема. Так же обычно в этих случаях создается запись в событиях винды (Event Viewer) с текстом исключения. В большинстве случаев проблема вызвана удалением какого-то нужного типа и решается добавлением специальных тегов в файл проекта.
Особенно эта проблема становится заметной при тестировании ежедневных (или ежечасных) сборок — размер директории .net во временном хранилище ОС начинает занимать десятки гигабайт через некоторое время.
Дополнительно ко всему начинают появляться странные глюки приложения (падения на ровном месте в непредсказуемых местах), которые исчезают, если НЕ использовать монолитные сборки.
Чтобы не видеть россыпь библиотек, необходимых для запуска приложения — можно использовать net core beauty — github.com/nulastudio/NetCoreBeauty — работает под Win/Lin/Mac.
Да, так было в .NET Core 3.1, но в .NET 5.0 подобная распаковка уже не делается.
А куда же оно распаковывает все библиотеки? В оперативку? чудес ведь не бывает и где-то оно лежит во время выполнения.
.NET 5.0 это не просто переименованный 3.1, там огромное количество изменений...
А библиотеки оно никуда не распаковывает. Сборки грузятся напрямую из памяти используя CreateFileMapping/MapViewOfFile peimagelayout.cpp.
А куда же оно распаковывает все библиотеки? В оперативку? чудес ведь не бывает и где-то оно лежит во время выполнения.
https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md#peimage-loader
IL assemblies are loaded directly from the bundle.
The portion of the single-file bundle containing the required assembly is memory mapped, and the contents are appropriately interpreted by the runtime.
Как уменьшить размер приложения на C#, которое независимо от среды?