Пакетная сборка visual studio что это

Обновлено: 05.07.2024

packages.config и PackageReference

Прежде чем перейти к рассмотрению каждого инструмента для управления пакетами, сделаем небольшое отступление. Видимо так исторически сложилось, что существует два формата хранения информации об установленных пакетах.

Package Manager UI и Package Manager Console

nuget.exe

Установка пакетов для заданного проекта
1. В папке проекта (где лежит файл *.csproj) создайте файл packages.config и добавьте в него информацию о необходимых пакетах. Вот пример такого файла:

<?xml version = "1.0" encoding = "utf-8" ?>
<packages >
<package id = "AForge" version = "2.2.5" targetFramework = "net46" />
<package id = "AForge.Imaging" version = "2.2.5" targetFramework = "net46" />
<package id = "AForge.Math" version = "2.2.5" targetFramework = "net46" />
</packages >

2. Далее в командной строке (обычной cmd.exe) запускаем nuget. При этом в аргументах командной строки обязательно надо указать путь к файлу packages.config и путь к папке, в которую будут установлены пакеты (обычно это папка packages, которая лежит в папке решения):

SolutionDir\ProjectDir> nuget install packages.config -OutputDirectory SolutionDir\packages

Восстановление пакетов для всего решения
Переходим в корневую папку решения и вызываем:

Когда нужно восстановить пакеты, nuget.exe ищет в папках проектов файлы packages.config и считывает из них информацию о том, какие именно пакеты надо установить.

dotnet.exe

Установка пакетов для заданного проекта

SolutionDir\ProjectDir> dotnet add package <PACKAGE_NAME> --package-directory <PACKAGE_DIRECTORY>

Восстановление пакетов для всего решения

SolutionDir> dotnet restore --packages <PACKAGES_DIRECTORY>

PowerShell PackageManagement

The commands listed here are specific to the Package Manager Console in Visual Studio, and differ from the Package Management module commands that are available in a general PowerShell environment.

И не видим ничего. А делать надо так:

Ага, есть такой пакет, называется Extended.Wpf.Toolkit. Теперь я его устанавливаю:

Естественно, никакие ссылки в проект не добавляются (т. е. в этом смысле PowerShell PackageManagement работает аналогично nuget.exe).
А теперь я хочу посмотреть список установленных пакетов:

Get - Package -Destination SolutionDir\packages
Name Version Source ProviderName
---- ------- ------ ------------
Extended.Wpf.Toolkit 3.5.0 SolutionDir\Extended.Wpf.Toolkit. NuGet

Переход с Nuget на Paket

При безусловных преимуществах, которые дает использование Nuget, есть и некоторые мелкие неудобства. Нас с коллегами например напрягало, что при установке (или восстановлении) пакета средствами Visual Studio в проект всегда добавляются ссылки на сборки пакета с установленным свойством Copy Local = True, т. е. они будут копироваться в выходную папку проекта, а нас такое поведение не устраивало по некоторым причинам.

1. Вам придется создать в корне вашего решения папку .paket, а поскольку имя папки начинается с точки, вы сможете сделать это только из командной строки:

2. Есть еще одна инструкция по установке, которая говорит: скачав файл paket.bootstrapper.exe в папку .paket, переименуйте его в paket.exe и закоммитьте (игнорировать его при помощи файла .gitignore, не надо). Зачем все это надо, написано в описании файла paket.bootstrapper.exe.

3. Для удобства пользования утилитой packet.exe существует расширение для Visual Studio под названием Paket for Visual Studio, которое обеспечивает некие плюшки, в частности подсветку синтаксиса и InteliSense для файлов paket.dependencies и paket.references. Но это расширение не устанавливается для Visual Studio 2019.

Установив paket.exe, подготавливаем наше решение (имеется в виду Visual Studio solution). Создаем в папке решения файл paket.dependencies. В нем перечисляются все пакеты для всех проектов решения, обычно, с указанием версий. Для одного из моих решений файл выглядит так:

// paket.dependencies file for paket package manager utility

// restrict target framework
framework: >= net46

// don't copy referenced assemblies to project's output directory
copy_local: false

// NuGet packages
nuget Accord 3.8.0
nuget Accord.Imaging 3.8.0
nuget Accord.MachineLearning 3.8.0
nuget Accord.Math 3.8.0
nuget Accord.Statistics 3.8.0
nuget Accord.Video 3.8.0
nuget Accord.Vision 3.8.0
nuget AForge 2.2.5
nuget AForge.Imaging 2.2.5
nuget AForge.Math 2.2.5
nuget AForge.Video 2.2.5
nuget AForge.Video.DirectShow 2.2.5
nuget AvalonEdit 5.0.4
nuget Extended.Wpf.Toolkit 2.5
nuget Mantin.Controls.Wpf.Notification 3.2.0.0
nuget MessagingToolkit.QRCode 1.3.0
nuget Microsoft.CodeDom.Providers.DotNetCompilerPlatform 2.0.1
nuget Ookii.Dialogs.Wpf 1.0.0
nuget System.ValueTuple 4.5.0
nuget System.Windows.Interactivity.WPF 2.0.20525

После того как файл paket.dependencies создан, можно попросить paket закачать пакеты:

Команда paket.exe install генерирует в папке решения файл paket.lock, который описывает какой пакет от какого пакета зависит. У меня он выглядит так:

Microsoft.CodeDom.Providers.DotNetCompilerPlatform
System.ValueTuple

Если теперь запустить paket.exe install, то нужные пакеты не только загрузятся в папку packages (если они уже не загружены), но и в файл проекта (.csproj) добавятся ссылки на сборки из этих пакетов. Я уже писал выше, что для меня было важно в ссылках на сборки контролировать параметр Copy Local и делать его равным False. В paket это достигается строчкой copy_local: false в файле paket.dependencies.

Вот собственно и весь процесс использования paket. Последнее, что нужно сказать: если вы в своем решении уже пользовались NuGet, и переходите на paket, то утилита paket может выполнить этот переход полностью автоматически (т. е. вам не придется делать все, что было описано выше, нужно будет только скачать paket.exe):

Создание проектов и решений без Visual Studio

Создание файлов проектов и решений вручную

<ItemGroup >
<!-- Input to the tasks (see below) -->
<OutputFiles Include = "$(OutputPath)*.dll" />
</ItemGroup >

<!-- Target -->
<Target Name = "PostBuild" AfterTargets = "Build" >
<!-- Task -->
<Exec Command = "echo POSTBUILD COPYING OUTPUT FILES" />

<!-- Task -->
<Copy SourceFiles = "@(OutputFiles)"
DestinationFolder = "$(DistributionFolder)" />
</Target >
</Project >

Во фрагменте файла проекта (.csproj) даны комментарии по терминологии (в MSBuild ключевую роль играют понятия: Target, Task, Property и Item). По принципам своей работы MSBuild очень похожа на утилиту make.

Небольшое отступление. Если речь не идет о создании нового файла проекта (.csproj), а лишь об изменении имеющегося, то даже необязательно редактировать файл проекта. Те изменения, которые вы планируете внести в файл проекта можно вынести в отдельные два файла Directory.Build.props и Directory.Build.targets, которые утилита MSBuild сама ищет в папке проекта и выше нее и импортирует в проект. Подробнее об этом читайте в статье Customize your build.

Утилита dotnet.exe

dotnet new sln -n MySolution
dotnet new classlib -n MyProject
dotnet sln MySolution.sln add MyProject/MyProject.csproj
dotnet build

Утилита CMake

Программная генерация файлов проектов и решений

Резюме

Сборка решения

MSBuild

SolutionDir> MSBuild.exe -property:Configuration=Release

Чтобы программа MSBuild успешно запустилась из командной строки, вам нужно либо добавить путь к папке, где лежит msbuild.exe в переменную окружения PATH (у меня это C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin ), либо запускать командную строку Visual Studio Command Prompt либо указывать полный путь к файлу MSBuild.exe.

Build Systems (автоматизация сборки решения)

  1. Очистка решения и ⁄ или дистрибутива
  2. Установка ⁄ восстановление ⁄ обновление пакетов
  3. Построение проектов
  4. Формирование дистрибутива (копирование всяких файлов в папку дистрибутива)

В итоге остановились на системе Nuke.

Установка Nuke на компьютер:

Установка Nuke в решение Visual Studio:

Далее у меня состоялся с утилитой следующий диалог:

How should the build project be named?
┐ nuke_build_project
Where should the build project be located?
┐ nuke_build_project
Which NUKE version should be used?
┐ 0.20.1 (latest release)
Which solution should be the default?
┐ MySuperBigSolution.sln
Do you need help getting started with a basic build?
┐ Yes, get me started!
Restore, compile, pack using .
┐ Neither
Source files are located in .
┐ ./src
Move packages to .
┐ Neither
Where do test projects go?
┐ ./tests
Do you use GitVersion?
┐ Yes, just not setup yet
Creating directory 'SolutionDir\nuke_build_project'.
Creating directory 'SolutionDir\tests'.

Пример очень простого кода Build.cs:

AbsolutePath SourceDirectory => RootDirectory / "src" ;

Итак, у нас есть проект программы, которая выполняет сборку решения. Теперь чтобы запустить процесс сборки решения, надо выполнить в командной строке powershell скрипт build.ps1:

SolutionDir> .\build.ps1 -target compile -configuration release

Расширения для Visual Studio

Command Task Runner

Вот пример файла commands.json с двумя задачами (BuildRelease и Clean), которые выполняются путем запуска скрипта build.ps1 (скрипт PowerShell, который появился при установке Nuke):

NUKE Support

Как пользоваться VS Code

Command Palette

Отладка в VS Code

В VS Code почему-то можно отлаживать только 64-разрядные программы, поэтому вам придется специально построить 64-разрядную версию своей программы. Для этого при компиляции вы должны передать утилите MSBuild параметр командной строки /p:Prefer32Bit=False . Если мы запускаем MSBuild из проекта nuke, то можно добавить такую tagret в исходный код проекта nuke:

Благодарности

Сборки имеют следующие составляющие:

Манифест, который содержит метаданные сборки

Метаданные типов. Используя эти метаданные, сборка определяет местоположение типов в файле приложения, а также места размещения их в памяти

Все эти компоненты могут находиться в одном файле, и тогда сборка представляет один единственный файл в формате exe или dll.

Компоненты сборки в .NET

Но также может быть, что эти компоненты хранятся в отдельных файлах. Например, есть основной файл exe, который имеет метаданные сборки и типов и который использует дополнительные файлы ресурсов - различные изображения, звуковые файлы, вспомогательные модули, элементы интерфейса, локализованные для различных культур.


Манифест сборки

Ключевым компонентом сборки является ее манифест . Если у сборки отсутствует манифест, то заключенный в ней код MSIL выполняться не будет. Манифест может находиться в одном файле с исполняемым кодом сборки, а может размещаться и в отдельном файле.

Манифест хранит следующие данные:

Номер версии : основной и дополнительный номера. Используется для управления версиями

Язык и региональные параметры : информация о языке и региональных параметрах, которые поддерживает сборка

Информация о строгом имени : открытый ключ издателя

Список всех файлов сборки : хэш и имя каждого из входящих в сборку файлов

Список ссылок на другие сборки , которые использует текущая сборка

Список ссылок на типы , используемые сборкой

Таким образом, манифест позволяет системе определить все файлы, входящие в сборку, сопоставить ссылки на типы, ресурсы, сборки с их файлами, управлять контролем версий.

Атрибуты сборки

По умолчанию Visual Studio при создании проекта добавляет файл AssemblyInfo.cs, который можно найти в узле Properties:

Смысл этого файла состоит в том, что он задает настройки манифесту сборки. Через атрибуты типа [assembly: AssemblyVersion("1.0.0.0")] можно установить значения в манифесте. Префикс assembly: перед атрибутом указывает на то, что это атрибут уровня сборки, в данном случае атрибут номера версии сборки.

В принципе, исходя из названия, я думаю, предназначение многих атрибутов итак понятно:

AssemblyCompany : название компании

AssemblyConfiguration : конфигурация сборки (Retail или Debug)

AssemblyCopyright : авторское право на программу

AssemblyDefaultAlias : псевдоним по умолчанию, используемый при ссылке на данную сборку из других сборок

AssemblyDescription : краткое описание сборки

AssemblyProduct : информация о продукте

AssemblyTitle : название сборки как информационного продукта

AssemblyTrademark : сведения о торговой марке

AssemblyCulture : задает язык и региональные параметры, поддерживаемые сборкой (например, установка русской культуры: [assembly:AssemblyCultureAttribute("ru")] )

AssemblyInformationalVersion : полная версия сборки

AssemblyVersion : версия сборки

AssemblyFileVersion : номер версии файла Win32. По умолчанию совпадает с версией сборки.

Также есть графический способ определения информации о сборке. Для этого нажмем в окне Solution Explorer (Обозреватель решений) на название проекта правой кнопкой мыши и выберем в появившемся меню пункт Properties (Свойства). В открывшемся окне нажмем на кнопку Assembly Information. , и нам предстанет окно изменения атрибутов:

В наше время open source проекты все популярнее. На площадках открытых проектов, например, на github можно найти множество полезных программ, но они не всегда имеют исполняемые файлы ("exe"), поэтому я постараюсь рассказать о том, как можно собрать самостоятельно C/C++ программу, из исходников, написанную на Microsoft Visual Studio.

Первым делом нам необходимо загрузить онлайн установщик Microsoft Visual Studio, с официального сайта. Для компиляции С/С++ проектов нет необходимости во всех пакетах и можно выбрать только те, которые нам необходимы.

Установщик загрузит необходимые пакеты из интернета и установит их.

После установки Visual Studio можно убедиться, что всё работает создав тестовый проект и скомпилировав его. Для этого нажмите в меню "Файл" → "Создать" → "Проект. "

После чего появится диалог выбора типа проекта, где можно выбрать:

  • Консольное приложение;
  • Классическое приложение;
  • Библиотеку динамической компоновки (dll);
  • Статическую библиотеку;

В нашем случае для быстрой проверки подойдет консольное приложение, выбираем название и папку проекта , после чего жмём кнопку "ОК" и создается наша программа.

После этого остается остается лишь скомпилировать её, для этого нужно выбрать в меню "Сборка" и нажать на пункт "Собрать решение".

Далее наш проект скомпилируется и в папке проекта появится наш тестовый исполняемый файл ("exe").

Если всё работает как надо, то можно приступать к сборке какого-нибудь другого открытого проекта с github или другого хостинга проектов.

Первым делом нам нужно загрузить исходники проекта. На площадке github это делается довольно просто, жмем на кнопку "Code" и "Download ZIP". После чего нужно распаковать его и можно приступать к сборке.

Ищем файл с расширением "<название_проекта>.vcxproj" и запускаем его. Перед нами появится диалог в котором нам предложат обновить SDK проекта (набор библиотек для разработки, которые Microsoft периодически обновляет) и набор инструментов, жмём обновить.

Теперь наш проект можно собрать, но до сборки необходимо выбрать разрядность проекта (например, для 32 битной системы или 64 битной), а также тип сборки (отладочный режим - debug или release).

Выбираем 64 битную систему и тип сборки релиз, после чего компилируем проект. Как и ранее нужно выбрать в меню "Сборка" и нажать на пункт "Собрать решение".

Некоторые проектам требуется вручную изменить SDK и набор инструментов, на установленный у вас, для этого идём в свойства проекта, выбираем сверху типа сборки и разрядность системы и уже там изменяем SDK и набор инструментов. В выпадающем меню появляются установленные у нас версии, выбираем их и нажимаем "ОК". После чего наш проект скомпилируется.

Бывает, что проект использует сторонние библиотеки, для этого их нужно загрузить отдельно и положить в папку. Узнать путь или изменить его можно в свойстве проекта, в разделе "С/C++" → "Общие" → "Дополнительные каталоги включаемых файлов".

Бывает, что SDK или набор инструментов, в свойстве проекта не изменяется в диалоге, чтобы изменить их нужно записать номер SDK, закрыть Visual Studio и вручную, блокнотом изменить этот номер в файле проекта "<название_проекта>.vcxproj".

При возникновении других проблем можно попробовать их загуглить, возможно, что кто-то уже сталкивался с ними и решил их.

Немного теории

Замечу, что речь идет именно о страницах ASPX и серверных скриптах внутри этих страниц, а не о т.н. code behind файлах, которые должны быть заранее скомпилированы и размещены в папке BIN или глобальном кеше сборок (GAC - Global Assembly Cache). Использование code behind файлов является предпочтительным способом, так как позволяет добиться разделения кода и представления. К сожалению это не исключает компиляции ASPX страниц.

После JIT-компиляции исполняемый код метода кешируется и последующие обращения к этому методу происходят напрямую.

Последнюю мы рассматривать не будем, а вот в процесс компиляции "на-лету" можно вмешаться.

Первый запрос страницы

  • разбор (parsing) страницы и генерация исходного кода. Данный код можно увидеть при включенной отладке (см. ниже "Как устроена страница").
  • компилиция кода страницы и сохранение полученной сборки

Если страница уже была ранее скомпилирована, т.е. для нее есть соответствующая сборка, то данная сборка используется в качестве обработчика запрошенной страницы.

Давайте представим себе реальную ситуацию, когда Веб-сайт содержит несколько сотен или тысяч страниц. Что происходит, когда пользователь запрашивает страницу с сервера? Правильно - компиляция этой страницы. Теперь представьте, что сайт нагружен. Очевидно, что в этом случае время отклика сервера возрастает, а это не есть хорошо. Кстати - это касается и Веб-сервисов, но это немного другая история, так как здесь вмешиваются механизмы Reflection и сериализации.

Что же можно сделать, чтобы оптимизировать процесс динамической компиляции?

ASP.NET предлагает средство, называемое "пакетная компиляция" (batch compilation).

Пакетная компиляция

За процесс компиляции отвечает элемент конфигурации <compilation> файла web.config:

Чтобы включить эту опцию, надо установить атрибут batch равным true, а debug равным false.

Здесь надо заметить, что пакетная компиляция производится на основе каталога, а не для всего Веб-приложения.

Очевидно преимущество такого подхода - не надо компилировать и разбирать страницу за страницей при первом к ним обращении. Но как говорится, бесплатный сыр бывает только в мышеловках. И данный подход - не исключение. Отрицательная сторона заключается в том, что такая компиляция занимает больше ресурсов сервера и может увеличить время отклика страниц, участвующих в такой компиляции. Но на это есть свое противоядие - "пред-пакетная" компиляция (pre-batch compilation). Т.е. перед тем, как кто-либо запросит любую страницу с сервера, Вы сами обращаетесь к любой странице, тем самым инициируя процесс пакетной компиляции и заставляя ASP.NET создать и закешировать все страницы сайта. Отсюда мораль - всегда перед передачей Веб-приложения в "производство" запрашивайте страницы из всех виртуальных каталогов.

Технические детали

Теперь немного о технических деталях. Любая страница ASPX при обращении к ней автоматически компилируется и попадает в:

(nnnnn и mmmm - случайные последовательности).

Часть пути "%systemroot%/Microsoft.NET/Framework/<версия>/Temporary ASP.NET Files" может быть изменена с помощью атрибута tempDirectory

На моем компьютере - это:

В зависимости от значения атрибута batch , там будет находиться один или более файлов вида aabbcc.dll, а так же настройки для связывания (Test.aspx.mmmmm.xml).

Хитрость заключается в том, что в случае с batch=true , там будет всего одна dll, но в настройках связывания (напоминаю - это файлы вида Test.aspx.mmmmm.xml) будет указана одна и та же dll для всех страниц. Название dll выбирается случайным образом, аналогично выбору имени временного файла.

Что происходит, если меняется одна страница

ASP.NET компилирует ее и создает отдельную сборку со случайным именем, например xxyyzz.dll. Потом меняется настройка связывания, так что теперь ASP.NET знает: "код выполнения страницы Test.aspx находится не в aabbcc.dll, а в xxyyzz.dll". При этом в старой сборке остается код для страницы Test.aspx, но он не используется.

Как устроена страница или магия в действии

Для лучшего понимания процесса надо установить debug=true .

Читайте также: