Навіщо Win32-додатком маніфест?

Нещодавно на руборде в розділі Програмування було поставлено питання: «Навіщо Win32-додатком маніфест? На що він впливає? ». Перше, що відразу спадає на думку більшості програмістів — це теми оформлення. Але насправді в сучасних винда маніфест потрібен не тільки для цього. Я подумав і написав п'ять ключових аспектів, на які впливає маніфест або його відсутність. Після цього відразу кілька людей попросили оформити цей пост у вигляді більш розгорнутої статті.
 
Для початку пропоную згадати, як взагалі в Windows з'явилися маніфести, і як вони розвивалися.
 
 
Історія маніфесту
У стародавні часи в світі Win95/98 панував пекло, точніше DLL hell . Виник він через те, що Windows замислювалася як ідеальна система. Всі додатки в ній завжди мали писатися з використанням найсвіжіших версій системних бібліотек. А різні версії самих бібліотек мали бути взаємозамінними. Реальність швидко довела всім, що для популярної операційки це нездійсненна мрія, так і виник пекло. Кожне друге додаток під час інсталяції Перезаписувати системні бібліотеки потрібними йому версіями. У результаті після установки програми X встановлене раніше додаток Y починало глючити. А після переустановлення додатки Y глючити починало додаток X. Загалом юзерам жилося весело.
 
Для вирішення цієї проблеми в Windows XP з'явилася технологія Side-by-side Assembly (SxS) . Суть її полягала в тому, що додаток могло явно вказати, з якою версією бібліотеки воно бажає працювати. Ця інформація могла вказуватися або в спеціальному файлі. Manifest, або в ресурсах додатка в розділі Manifest. У самій ХР на основі нової технології реалізували одну з найпомітніших нових фішок системи — теми оформлення.
 
Типовий маніфест:
 
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="*"
    name="CompanyName.ProductName.YourApplication"
    type="win32"
/>
<description>Your application description here.</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>

 
Всім був хороший SxS крім одного — він був страшенно незручний для програміста. У 99% випадків маніфест застосовувався тільки для включення тих самих тем оформлення, і ні для чого більше. Розробникам вінди стало ясно, що потрібен новий, більш простий у використанні спосіб вказати підтримувані версії системних бібліотек. Тоді вони придумали просте правило: в межах однієї версії системи інтерфейс і поведінку цих бібліотек не змінюється. Потрібно було тільки якимось чином навчиться визначати яка їх версія вимагається певної програми. Так в Windows 7 в маніфесті з'явилася секція Compatibility, де можна вказати з якими версіями ОС тестувалося додаток.
Також в маніфесті починаючи з Windows Vista з'явилося ще кілька секцій, про всі про них нижче.
 
 
Функції маніфесту
 
     
  1. Активація тем оформлення (Visual Styles )
    Ця технологія з'явилася в ХР і повністю заснована на SxS. Працює просто: ви запитуєте у системи ComCtl32.dll шостої версії, і — вуаля — всі стандартні контроли малюються згідно з активованою в системі темою. Якщо ж ви не згадаєте в маніфесті ComCtl32.dll, або маніфест взагалі буде відсутня у додатку, то система за замовчуванням завантажить ComCtl32.dll п'ятої версії, яка отрісовиваєт контроли в стилі Win95. Крім підтримки тем оформлення, шоста версія ComCtl32.dll містить сякий функціонал, якого нету в п'ятій версії. Тому якщо відключити теми оформлення, деякі програми будуть працювати і виглядати не так, як задумували їхні автори.
     
    Праворуч теж саме додаток без маніфесту:
     
     
     
     
  2.  
  3. Взаємодія з UAC має кілька аспектів :
     
       
    • Ключ requestedExecutionLevel.level дозволяє вказати необхідний додатком рівень прав користувача. Приміром якщо вказати requireAdministrator, то додатком будуть надані права адміністратора (якщо користувач дозволить).
       
      Запит дозволу користувача:
       
       
       
       
    •  
    • Якщо вся секція по взаємодії з UAC відсутня в маніфесті, до додатка буде застосована віртуалізація файлової системи і реєстру . Якщо такий додаток спробує записати що то в захищені папки типу «Program files», воно буде перенаправлено в папку "% userprofile% \ AppData \ Local \ VirtualStore \ Program files". Аналогічно, спроби запису в розділ реєстру HKEY_LOCAL_MACHINE будуть перенаправлені в «HKEY_CURRENT_USER \ Software \ Classes \ VirtualStore \ MACHINE». Природно, зроблені таким чином зміни будуть видні тільки додаткам, запущеним в режимі віртуалізації.
       
      Віртуалізація файлової системи у справі:
       
       
       
       
    •  
    • Ключ requestedExecutionLevel.uiAccess дозволяє додаткам, запущеним без прав адміністратора, взаємодіяти з вікнами додатків, запущених з правами адміністратора. Це може знадобитися екранним клавіатурам, додаткам типу AutoIt, екранним читалкам, тестовим і налагоджувальний ТУЛЗ. Щоб цей ключ спрацював, програма має бути підписано сертифікатом Microsoft Authenticode .
    •  
     
  4.  
  5. Управління DPI-масштабуванням
    З найдавніших часів вінда має механізм масштабування інтерфейсу залежно від DPI монітора (тут говориться, що все почалося в XP, але мені здається, що раніше ). У ті часи ця настройка виставлялася тільки вручну, напевно через відсутність EDID . Популярністю вона не користувалася, можливо тому, що захована була далеко, а можливо тому, що моніторів з великою роздільною здатністю було дуже-дуже мало. Крім того, велика частина роботи, необхідної для підтримки масштабування, була віддана на відкуп самим додаткам і їх авторам. А програмісти, як відомо, люди вельми ледачі, тому купа софта для вінди писалася в припущенні, що DPI завжди дорівнює стандартному значенню 96. Дуже часто зустрічалася ситуація, коли в додатку використовувалися бібліотеки підтримують нестандартний DPI, в той час як код самого додатка його НЕ підтримував. Це призводило до появи жахливих артефактів в інтерфейсі програми, варто було користувачеві виставити DPI, наприклад, в значення 120 (масштабування 125%):
     
     
     
    Розробники Вісти не стерпів подібного неподобства, і заклали в DWM можливість виробляти масштабування самостійно, а додаткам брехати, що DPI по раніше дорівнює 96. Причому залежні від нього системні налаштування, дозвіл монітора і навіть положення миші, також перераховуються. На жаль розробники Вісти небилиці чарівниками, тому масштабування DWM виробляє за допомогою простих алгоритмів розтягування зображень. І якщо інтерфейс програми потрібно збільшити, то відбувається замилювання картинки. Уявіть що було б, якби розробники Фотошопа не могли це відключити. Таких бунтів на кораблі ніхто не хотів, тому з'явилася можливість вказати в маніфесті, що ваш додаток таки вміє нормально масштабувати свій інтерфейс, і допомога DWM йому не потрібна. За це відповідає параметр dpiAware . Тут правда слід зазначити, що за замовчуванням масштабування силами DWM включається при збільшенні 150% і вище. Мабуть в Microsoft порахували, що при масштабування 125% артефакти як на скріншоті вище цілком терпимі.
     
    Зліва масштабування силами DWM, а праворуч — самого програми:
     
     
     
    У Windows 8.1 з'явилася можливість вказувати різний масштаб різним моніторам, якщо підключено відразу декілька. Відповідно у ключа dpiAware з'явилося нове значення «True / PM». Воно означає, що додаток вміє динамічно змінювати масштаб свого інтерфейсу при перенесенні вікон з одного монітора на інший.
     
     
  6.  
  7. Декларування сумісності
    Працює дуже просто: програміст тестує свій додаток в певної версії вінди, і якщо все працює як треба, додає GUID цієї версії в маніфест.
     
    Приклад:
     
     
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
          <application> 
            <!--This Id value indicates the application supports Windows Vista functionality -->
              <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
            <!--This Id value indicates the application supports Windows 7 functionality-->
              <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!--This Id value indicates the application supports Windows 8 functionality-->
              <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
            <!--This Id value indicates the application supports Windows 8.1 functionality-->
              <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
          </application> 
      </compatibility>
    

     
    Найбільш цікавим є питання: «На що впливають ці GUID-и?» Поки що список відмінностей в поведінці системних бібліотек невеликий. Найцікавіше згадка про оптимізацію RPC . Виходить що додатки, які задекларували сумісність з сімкою, будуть працювати швидше.
    У майбутньому цей розділ маніфесту напевно буде відігравати велику роль ніж зараз. Адже в винде повно різних хаков покликаних забезпечувати сумісність. І тепер є можливість захистити від них нормальні додатки.
     
    Якщо GUID-и повністю відсутні в маніфесті, то до додатка застосовуються правила як до сумісного з Віста:
     
     
     
     
  8.  
  9. Управління іншими функціями
    Вище я описав тільки ті функції, з якими доводилося мати справу особисто. Але це далеко не все, чим можна управляти з маніфесту: msdn.microsoft.com/en-us/library/aa374191.aspx На жаль, документація здебільшого інших функцій недоступна. Можливо її опублікують пізніше, як свого часу сталося з Magnification API .
  10.  
 
 
Епілог
На цьому я, мабуть, завершу розгляд можливостей маніфестів Win32-додатків. Якщо у вас є які-небудь виправлення або доповнення, будь ласка, викладіть їх у коментарях.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.