Файл manifest что это
Зачем Win32-приложению манифест?
Недавно на руборде в разделе Программирование был задан вопрос: «Зачем Win32-приложению манифест? На что он влияет?». Первое, что сразу приходит в голову большинству программистов — это темы оформления. Но на самом деле в современных виндах манифест нужен не только для этого. Я подумал и написал пять ключевых аспектов, на которые влияет манифест или его отсутствие. После этого сразу несколько человек попросили оформить этот пост в виде более развернутой статьи.
Для начала предлагаю вспомнить, как вообще в Windows появились манифесты, и как они развивались.
История манифеста
В древние времена в мире Win95/98 царил ад, точнее DLL hell. Возник он из-за того, что Windows задумывалась как идеальная система. Все приложения в ней всегда должны были писаться с использованием самых свежих версий системных библиотек. А различные версии самих библиотек должны были быть взаимозаменяемыми. Реальность быстро доказала всем, что для популярной операционки это несбыточная мечта, так и возник ад. Каждое второе приложение во время инсталляции перезаписывало системные библиотеки нужными ему версиями. В результате после установки приложения X установленное ранее приложение Y начинало глючить. А после переустановки приложения Y глючить начинало приложение X. В общем юзерам жилось весело.
Всем был хорош SxS кроме одного — он был ужасно неудобен для программиста. В 99% случаев манифест применялся только для включения тех самых тем оформления, и ни для чего больше. Разработчикам винды стало ясно, что нужен новый, более простой в использовании способ указать поддерживаемые версии системных библиотек. Тогда они придумали простое правило: в пределах одной версии системы интерфейс и поведение этих библиотек не изменяется. Нужно было только каким то образом научится определять какая их версия требуется конкретному приложению. Так в Windows 7 в манифесте появилась секция Compatibility, где можно указать с какими версиями ОС тестировалось приложение.
Также в манифесте начиная с Windows Vista появилось еще несколько секций, обо всех о них ниже.
Функции манифеста
Справа тоже самое приложение без манифеста:
Запрос разрешения пользователя:
Виртуализация файловой системы в деле:
Разработчики Висты не стерпели подобного безобразия, и заложили в DWM возможность производить масштабирование самостоятельно, а приложениям врать, что DPI по прежнему равен 96. Причем зависящие от него системные настройки, разрешение монитора и даже положение мыши, также пересчитываются. К сожалению разработчики Висты небыли волшебниками, поэтому масштабирование DWM производит с помощью простых алгоритмов растягивания изображений. И если интерфейс приложения нужно увеличить, то происходит замыливание картинки. Представьте что было бы, если бы разработчики Фотошопа не могли это отключить. Таких бунтов на корабле никто не хотел, поэтому появилась возможность указать в манифесте, что ваше приложение таки умеет нормально масштабировать свой интерфейс, и помощь DWM ему не нужна. За это отвечает параметр dpiAware. Тут правда следует отметить, что по умолчанию масштабирование силами DWM включается при увеличении 150% и выше. Видимо в Microsoft посчитали, что при масштабировании 125% артефакты как на скриншоте выше вполне терпимы.
Слева масштабирование силами DWM, а справа — самого приложения:
В Windows 8.1 появилась возможность указывать разный масштаб разным мониторам, если подключено сразу несколько. Соответственно у ключа dpiAware появилось новое значение «True/PM». Оно означает, что приложение умеет динамически изменять масштаб своего интерфейса при переносе окон с одного монитора на другой.
Наиболее интересен вопрос: «На что влияют эти GUID-ы?» Пока что список различий в поведении системных библиотек невелик. Наиболее интересно упоминание об оптимизации RPC. Получается что приложения, задекларировавшие совместимость с семеркой, будут работать быстрее.
В будущем этот раздел манифеста наверняка будет играть большую роль чем сейчас. Ведь в винде полно разных хаков призванных обеспечивать совместимость. И теперь есть возможность оградить от них нормальные приложения.
Если GUID-ы полностью отсутствуют в манифесте, то к приложению применяются правила как к совместимому с Вистой:
Манифесты приложений
Манифест приложения — это файл XML, который описывает и определяет общие и закрытые сборки одновременного выполнения, которые приложению следует подключить во время выполнения. Это должны быть те же версии сборок, что и использованные для проверки приложения. Манифесты приложения также могут описывать метаданные закрытых для приложения файлов.
Полный список схем XML см. в разделе Схема файла манифеста.
Манифесты приложений имеют следующие элементы и атрибуты.
Элемент | Атрибуты | Обязательно |
---|---|---|
сборок | Да | |
манифестверсион | Да | |
не наследовать | Нет | |
Неправильн | Да | |
type | Да | |
name | Да | |
язык | Нет | |
processorArchitecture | Нет | |
version | Да | |
publicKeyToken | Нет | |
см | Нет | |
приклад | Нет | |
суппортедос | Id | Нет |
maxversiontested укажите установленную | Id | Нет |
зависимостей | Нет | |
dependentAssembly | Нет | |
File | Нет | |
name | Нет | |
hashAlg | Нет | |
hash | Нет | |
активекодепаже | Нет | |
автоповышение | Нет | |
дисаблесеминг | Нет | |
дисаблевиндовфилтеринг | Нет | |
дпиаваре | Нет | |
дпиаваренесс | Нет | |
гдискалинг | Нет | |
хигхресолутионскроллингаваре | Нет | |
лонгпасаваре | Нет | |
принтердриверисолатион | Нет | |
ултрахигхресолутионскроллингаваре | Нет | |
msix | Нет | |
хеаптипе | Нет |
Расположение файла
Манифесты приложений должны быть добавлены в качестве ресурсов в EXE-файл или библиотеку DLL приложения.
Дополнительные сведения см. в разделе Установка параллельных сборок.
Синтаксис имени файла
Имя файла манифеста приложения — это имя исполняемого объекта приложения, за которым следует manifest.
Элементы
В именах элементов и атрибутов учитывается регистр. Значения элементов и атрибутов не учитывают регистр, за исключением значения атрибута Type.
сборка
Элемент Assembly должен находиться в пространстве имен urn: schemas-microsoft-com: ASM. v1. Дочерние элементы сборки также должны находиться в этом пространстве имен путем наследования или добавления тегов.
Элемент Assembly имеет следующие атрибуты.
attribute | Описание |
---|---|
манифестверсион | Атрибут манифестверсион должен иметь значение 1,0. |
не наследовать
Элемент NoInherit является необязательным и обычно опускается. Большинство сборок работает неправильно с помощью контекста активации без наследования, так как сборка должна быть специально разработана для управления распространением собственного контекста активации. Использование элемента NoInherit требует, чтобы все зависимые сборки, на которые ссылается манифест приложения, имели элемент NoInherit в манифесте сборки.
assemblyIdentity
Элемент assemblyIdentity имеет следующие атрибуты. У него нет вложенных элементов.
совместимость
Содержит по крайней мере одно приложение. У него нет атрибутов. Необязательный элемент. манифесты приложений без элемента compatibility по умолчанию Windows совместимость с Vista на Windows 7.
application
суппортедос
Элемент суппортедос имеет следующий атрибут. У него нет вложенных элементов.
attribute | Описание |
---|---|
Id | Задайте для атрибута ID значение , чтобы запустить приложение с помощью функции Vista. это может позволить приложению, предназначенному для Windows Vista, работать в более поздней версии операционной системы. задайте для атрибута Id значение , чтобы запустить приложение с помощью функции Windows 7. приложения, поддерживающие Windows Vista, Windows 7 и функции Windows 8, не нуждаются в отдельных манифестах. в этом случае добавьте идентификаторы guid для всех операционных систем Windows. сведения о поведении атрибута Id в Windows см. в разделе Windows 8 и Windows Server 2012 Compatibility Cookbook. Следующие идентификаторы GUID соответствуют указанным операционным системам: — > Windows 10, Windows 11, Windows Server 2016, Windows server 2019 и Windows server 2022 — > Windows 8.1 и Windows Server 2012 R2 — > Windows 8 и Windows Server 2012 — > Windows 7 и Windows Server 2008 R2 — > Windows Vista и Windows Server 2008 вы можете протестировать это на Windows 7 или Windows 8. x, запустив монитор ресурсов (ресмон), перейдя на вкладку цп, щелкнув правой кнопкой мыши метки столбцов, «выбрать столбец. » и установив флажок «контекст операционной системы». на Windows 8. x можно также найти этот столбец, доступный в диспетчере задач (панели диспетчер задач). содержимое столбца показывает наибольшее найденное значение или «Windows Vista» в качестве значения по умолчанию. |
maxversiontested укажите установленную
элемент maxversiontested укажите установленную указывает версии Windows, на которые проверялось приложение, начиная с минимальной версии ос, поддерживаемой приложением до максимальной версии. Полный набор версий можно найти здесь. Он предназначен для использования в приложениях для настольных систем, использующих острова XAML и не развернутых в пакете MSIX. этот элемент поддерживается в Windows 10, версии 1903 и более поздних версиях.
Элемент maxversiontested укажите установленную имеет следующий атрибут. У него нет вложенных элементов.
attribute | Описание |
---|---|
Id | задайте для атрибута Id строку версии из 4 частей, которая указывает максимальную версию Windows, с которой было протестировано приложение. Например, «10.0.18226.0». |
dependency
Содержит по меньшей мере один dependentAssembly. У него нет атрибутов. Необязательный элемент.
dependentAssembly
Указывает файлы, являющиеся частными для приложения. Необязательный элемент.
Элемент File содержит атрибуты, приведенные в следующей таблице.
attribute | Описание |
---|---|
name | Имя файла. Например, Comctl32.dll. |
hashAlg | Алгоритм, используемый для создания хэша файла. Это значение должно быть SHA1. |
hash | Хэш файла, на который ссылается имя. Шестнадцатеричная строка длины в зависимости от хэш-алгоритма. |
активекодепаже
в Windows 10 этот элемент заставляет процесс использовать UTF-8 в качестве кодовой страницы процесса. Дополнительные сведения см. в разделе Использование кодовой страницы UTF-8. в Windows 10 единственным допустимым значением для активекодепаже является UTF-8.
начиная с Windows 11, этот элемент также позволяет выбрать устаревшую кодовую страницу не в кодировке UTF-8 или кодовые страницы для определенного языкового стандарта для совместимости с устаревшими приложениями. Современные приложения настоятельно рекомендуется использовать Юникод. в Windows 11 для активекодепаже также может быть задано значение Legacy или имя локали, например en-US или ja-JP.
этот элемент впервые был добавлен в Windows 10 версии 1903 (обновление 2019 мая). вы можете объявить это свойство и целевой объект или выполнить его в более ранних Windows сборках, но необходимо как обычно выполнять обнаружение и преобразование кодовых страниц прежних версий. Этот элемент не содержит атрибуты.
В следующем примере показано, как использовать этот элемент, чтобы заставить текущий процесс использовать UTF-8 в качестве кодовой страницы процесса.
автоповышение
Указывает, включен ли автоматический повышенный уровень прав. Значение true указывает, что он включен. У него нет атрибутов.
дисаблесеминг
Указывает, отключено ли предоставление элементов пользовательского интерфейса для темы. Значение true указывает, что отключено. У него нет атрибутов.
дисаблевиндовфилтеринг
Указывает, следует ли отключить фильтрацию окон. True — отключить фильтрацию окон, чтобы можно было перечислить иммерсивное окно с рабочего стола. дисаблевиндовфилтеринг был добавлен в Windows 8 и не имеет атрибутов.
дпиаваре
Указывает, учитывается ли текущий процесс в точках на дюйм (DPI).
В следующей таблице описывается поведение, получаемое в зависимости от наличия элемента дпиаваре и содержащегося в нем текста. В тексте элемента не учитывается регистр.
Дополнительные сведения о параметрах осведомленности о dpi см. в разделе Сравнение уровней осведомленности о dpi.
дпиаваре не имеет атрибутов.
дпиаваренесс
Указывает, учитывается ли текущий процесс в точках на дюйм (DPI).
Элемент дпиаваренесс может содержать один элемент или список элементов с разделителями-запятыми. В последнем случае используется первый (крайний левый) элемент в списке, распознанном операционной системой. таким образом можно указать различные варианты поведения, поддерживаемые в будущих Windows версиях операционных систем.
В следующей таблице описывается поведение, получаемое в зависимости от наличия элемента дпиаваренесс и содержащегося в нем текста в его левом распознанном элементе. В тексте элемента не учитывается регистр.
Дополнительные сведения о параметрах осведомленности о разрешении, поддерживаемых этим элементом, см. в разделе _ Поддержка dpi и _ _ контекст осведомленностио dpi.
дпиаваренесс не имеет атрибутов.
гдискалинг
Платформа GDI (интерфейс графических устройств) может применять масштабирование DPI к примитивам и тексту на уровне отдельных мониторов без обновления самого приложения. Это может быть полезно для приложений GDI, которые больше не обновляются.
Невекторная графика (например, точечные рисунки, значки или панели инструментов) не может масштабироваться этим элементом. Кроме того, графика и текст, отображаемые в растровых изображениях, динамически создаваемые приложениями, также не могут масштабироваться этим элементом.
Значение true указывает, что этот элемент включен. У него нет атрибутов.
хигхресолутионскроллингаваре
Указывает, включено ли разрешение на прокрутку с высоким разрешением. Значение true указывает, что он включен. У него нет атрибутов.
лонгпасаваре
принтердриверисолатион
Указывает, включена ли изоляция драйвера принтера. Значение true указывает, что он включен. У него нет атрибутов. изоляция драйвера принтера повышает надежность службы Windows печати, позволяя драйверам принтера выполняться в процессах, отделяющих от процесса, в котором работает диспетчер очереди печати. поддержка изоляции драйвера принтера запущена в Windows 7 и Windows Server 2008 R2. Приложение может объявить изоляцию драйвера принтера в своем манифесте приложения, чтобы изолировать себя от драйвера принтера и повысить его надежность. Это значит, что приложение не будет завершаться сбоем, если в драйвере принтера произошла ошибка.
ултрахигхресолутионскроллингаваре
Указывает, включено ли разрешение на прокрутку Ultra-High-resolution. Значение true указывает, что он включен. У него нет атрибутов.
Указывает сведения об удостоверении разреженного пакета MSIX для текущего приложения. этот элемент поддерживается в Windows 10, версии 2004 и более поздних версиях.
attribute | Описание |
---|---|
publisher | Описание сведений об издателе. это значение должно соответствовать атрибуту Publisher в элементе Identity манифеста разреженного пакета. |
PackageName | Описывает содержимое пакета. Это значение должно соответствовать атрибуту Name в элементе Identity манифеста разреженного пакета. |
applicationId | Уникальный идентификатор приложения. Это значение должно соответствовать атрибуту ID в элементе Application в манифесте разреженного пакета. |
хеаптипе
Файл манифеста
В предыдущей статье мы рассмотрели создание простого файла манифеста, давайте теперь рассмотрим как его использовать в автономных приложениях.
Использование манифеста
Самого факта создания манифеста недостаточно, чтобы браузер обращал на него внимание. Чтобы манифест имел какой-либо эффект, на него должны существовать ссылки в веб-страницах. Для этого нужно вставить в корневой элемент атрибут manifest и присвоить ему в качестве значения имя файла манифеста:
Это нужно проделать для каждой страницы, входящей в автономное приложение.
Веб-сайт может иметь неограниченное количество автономных приложений при условии, что каждое из них имеет собственный манифест. Автономные приложения также могут совместно использовать некоторые ресурсы (например, таблицы стилей), но каждое приложение должно иметь свой отдельный набор веб-страниц.
Помещение манифеста на веб-сервер
Тестирование файла манифеста может оказаться сложным процессом. Небольшие ошибки могут вызывать скрытые сбои и нарушать весь процесс кэширования. Но, тем не менее, на определенном этапе файл манифеста нужно протестировать, чтобы удостовериться в том, что разработанное автономное приложение работает так, как вы ожидаете.
Не должно быть неожиданностью то обстоятельство, что автономное приложение нельзя тестировать, запуская файлы на исполнение с локального жесткого диска. Вместо этого автономное приложение нужно разместить на веб-сервере, будь то веб-сервер поставщика услуг интернета или тестовый веб-сервер разработчика, например веб-сервер IIS, встроенный в Windows.
Тестирование автономного приложения выполняется в такой последовательности:
Первым делом необходимо удостовериться в том, что для предоставления файлов манифеста в настройках веб-сервера указан MIME-тип text/cache-manifest. Если веб-сервер будет указывать какой-либо другой тип файла, включая простой текстовый файл, браузер будет полностью игнорировать манифест.
Рассмотрите отключение обычного кэширования для файлов манифеста. Это может быть необходимым по той причине, что веб-сервер может давать указание браузерам кэшировать файлы манифеста в течение определенного времени, точно так же, как и другие типы файлов. Такое поведение логично, но оно может вызвать большие проблемы.
Проблема состоит в том, что некоторые браузеры могут игнорировать обновленные файлы манифеста на веб-сервере и продолжать использовать старые, кэшированные файлы манифеста, вследствие чего они также будут продолжать использовать старые, кэшированные файлы веб-страниц. (Особенно грешит неохотой расставаться со старыми файлами манифеста браузер Firefox.) Во избежание этой проблемы веб-сервер необходимо настроить так, чтобы тот не указывал браузерам кэшировать файлы манифеста.
Откройте страницу в браузере, поддерживающем автономные приложения, иными словами, практически в любом браузере, за исключением Internet Explorer. Когда браузер обнаружит, что веб-страница использует манифест, он может запросить разрешение на загрузку файлов. Вероятнее всего, что такое разрешение будут требовать браузеры мобильных устройств по причине ограниченных возможностей хранения. Браузеры настольных компьютеров могут либо выдавать такой запрос, либо нет. Например, Firefox запрашивает разрешение на кэширование, a Chrome и Safari — нет:
Получив разрешение, браузер начинает кэширование файлов. Сначала загружается манифест, а потом все перечисленные в нем файлы. Процесс загрузки осуществляется в фоновом режиме, позволяя, таким образом, продолжать просмотр страницы. Этот процесс подобен тому, когда браузер загружает изображение или видео большого объема и при этом отображает остальную страницу.
Отключитесь от интернета. Если ваше приложение размещено на удаленном сервере, просто разорвите подключение. Если же приложение размещено на локальном сервере (т.е. на том же компьютере, что и браузер), остановите веб-сервер.
Перейдите на одну из страниц автономного приложения и обновите ее. Даже если дать указание браузеру не кэшировать страницу, иногда он все равно сохранит ее, чтобы можно было возвращаться на ранее просмотренные страницы, нажимая кнопку Назад. Но если обновить страницу, браузер всегда будет пытаться подключиться к веб-серверу.
При запросе обыкновенной страницы и при отсутствии подключения к интернету этот запрос не выполнится. Но при обновлении страницы автономного приложения браузер незаметно предоставляет копию страницы из кэша, даже не информируя пользователя об этом. Можно переходить с одной страницы автономного приложения на другую, но если перейти по ссылке на страницу, не являющуюся частью автономного приложения, браузер выдаст знакомое сообщение о невозможности подключиться к удаленному серверу.
Чтобы продемонстрировать использование автономных приложений загрузите страницу canvas_labirint.html, на которой реализована игра, которую мы создавали ранее. В данной странице реализовано автономное управление, т.е. если вы отключитесь от интернета и обновите эту страницу, она все равно будет работать. Файл манифеста для этой страницы довольно простой, нам нужно кэшировать таблицу стилей, файл JavaScript и несколько изображений:
Обновление файла манифеста
Заставить автономное приложение работать — это только первая часть задачи. Вторая часть — обновление его содержимого.
Рассмотрим пример с лабиринтом. Если обновить файл canvas_labirint.html и перезагрузить страницу, браузер все равно будет выводить старую, кэшированную версию страницы, даже если компьютер подключен к интернету. Проблема состоит в том, что после сохранения автономного приложения в кэше браузер использует только эту кэшированную копию, игнорируя онлайновые версии соответствующих вебстраниц и не проверяя, были ли какие-либо изменения. А так как срок хранения автономного приложения в кэше никогда не истекает, браузер будет упрямо игнорировать измененные страницы на веб-сервере.
Но при этом браузер регулярно проверяет присутствие нового файла манифеста. Таким образом, можно подумать, что все, что нужно сделать для решения этой проблемы — это сохранить новый файл манифеста на веб-сервере.
Не обязательно. Чтобы инициировать обновление кэшированного автономного приложения, необходимо выполнение следующих требований:
Отсутствие кэширования файла манифеста
Если у браузера есть локальная кэшированная копия файла манифеста, он никогда не будет проверять наличие этого файла на веб-сервере. Разные браузеры подходят по-разному к вопросу кэширования файлов манифеста. Некоторые браузеры (например Chrome) всегда проверяют наличие нового файла манифеста на веб-сервере. Но Firefox следует традиционным правилам кэширования и хранит локальную копию файла манифеста в течение некоторого времени. Поэтому, чтобы избежать проблем в этой области, удостоверьтесь в том, что ваш веб-сервер явно указывает своим клиентам не кэшировать файлы манифеста.
У манифеста должна быть проставлена новая дата
Когда браузер проверяет наличие нового файла манифеста на сервере, первым делом он смотрит, изменилась ли метка времени последнего изменения. Если нет, браузер не будет загружать файл манифеста.
Содержимое файла манифеста должно быть новым
Если браузер обнаружит что содержимое нового файла манифеста не изменилось, он прекращает процесс обновления и продолжает использовать ранее кэшированную копию. Эта потенциально препятствующая плану обновления практика имеет практическую цель. Повторная загрузка кэшированного приложения занимает время и расходует пропускную способность сети, поэтому браузеры выполняют ее только в тех случаях, когда это абсолютно необходимо.
Если вы внимательно читали этот материал, то должны были заметить здесь потенциальную проблему. Что если менять содержимое файла манифеста нет надобности, т.к. не были добавлены или удалены никакие файлы, но браузер все равно нужно заставить обновить кэш автономного приложения, поскольку содержимое некоторых файлов было изменено? В таких случаях следует незначительно изменить файл манифеста, чтобы он казался новым, хотя, по сути, не является таковым. Эту задачу лучше всего реализовать, вставив в файл манифеста комментарий:
В следующий раз, когда нужно обновить кэш, просто измените номер версии, в этом примере на 1.00.002, и т.д. Таким образом мы можем заставить браузер обновить кэш и получаем способ отслеживать количество обновлений.
Новое содержимое не отображается в окне браузера сразу же после загрузки. Когда браузер обнаруживает новый файл манифеста, он загружает новые файлы в фоновом режиме и заменяет ими старые кэшированные файлы. Новое содержимое отображается, когда посетитель открывает или обновляет страницу.
Очистка кэша браузера
В процессе тестирования автономного приложения часто бывает полезным вручную очистить кэш браузера. Таким образом можно тестировать свежие обновления без необходимости изменять файл манифеста.
Для просмотра кэшированных приложений в браузере Chrome введите chrome://appcache-internals в строку адреса:
Все браузеры разрешают очистку кэша, но каждый из них подходит к решению этой задачи по-своему. Наиболее полезные в этом отношении браузеры отслеживают объем хранилища, занимаемого каждым автономным приложением. Это позволяет определить, когда кэширование было неудачным, например, веб-сайт приложения не указывается в списке или же объем кэшированных файлов меньше, чем должен быть. Это также позволяет удалять кэшированные файлы для отдельных сайтов, не затрагивая другие.