Как стать автором
Обновить

Комментарии 26

Плюс в карму, добавлю только что в случае использования параметра -p:PublishSingleFile=true, дописывать в конце --self-contained 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

После перехода на .NET 6 SDK старые режимы сжатия стали работать хуже. Размер программы после сжатия увеличился примерно на 30 МБ при тех же настройках… Думаю, пока что стоит дождаться официального релиза, когда все баги будут исправлены.

Странно. У меня на .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 никакой разницы не наблюдается.

У меня есть .NET 5 WPF приложение, независимое от среды. С опцией PublishSingleFile, помимо непосредственно .exe файла размером 135 МБ, я получаю ещё дополнительный набор файлов.
Список доп. файлов
clrcompression.dll
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.

Да, действительно IncludeNativeLibrariesForSelfExtract и IncludeAllContentForSelfExtract — разные опции. Что-то не обратил на это внимание.

Прочитайте комментарий TOM_RUS выше. Попробуйте использовать превью версию и указанные настройки. Отпишите, что в итоге получилось, будет очень интересно узнать :)

Кстати, а что за проблемы с отладкой были при использовании PublishTrimmed и TrimMode=Link?

В этом режиме приложение сжимается без ошибок, но отказывается запускаться почему-то. Пока не нашел проблему с чем это связно: с

Я имел в виду что если запустить его под отладчиком, то по идее должно показать где проблема. Так же обычно в этих случаях создается запись в событиях винды (Event Viewer) с текстом исключения. В большинстве случаев проблема вызвана удалением какого-то нужного типа и решается добавлением специальных тегов в файл проекта.

почему по умолчанию не включено «удаляет только неиспользуемые сборки»?
При использовании Self-Contained архивов приложений есть одна маленькая большая бяка. Дело в том, что OS распаковывает эти файлы во временную директорию. И (сюрприз) не занимается их очисткой, даже если файлы потом долгое время не используются.

Особенно эта проблема становится заметной при тестировании ежедневных (или ежечасных) сборок — размер директории .net во временном хранилище ОС начинает занимать десятки гигабайт через некоторое время.

Дополнительно ко всему начинают появляться странные глюки приложения (падения на ровном месте в непредсказуемых местах), которые исчезают, если НЕ использовать монолитные сборки.

Чтобы не видеть россыпь библиотек, необходимых для запуска приложения — можно использовать net core beauty — github.com/nulastudio/NetCoreBeauty — работает под Win/Lin/Mac.

Да, так было в .NET Core 3.1, но в .NET 5.0 подобная распаковка уже не делается.

Хмм, где-то видел утверждение, что 5.0 — это просто переименованный 3.1 и отличий там минимум. Надо будет исследовать этот момент детальнее.

А куда же оно распаковывает все библиотеки? В оперативку? чудес ведь не бывает и где-то оно лежит во время выполнения.

.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.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории