суббота, 31 января 2009 г.

UAC для разработчика

UAC (User account control) впервые появился в Windows Vista, и сразу же, не заслуженно, получил отрицательную репутацию, а в Интернете появилось полным полно статей как его отключить. Доходит даже до откровенного маразма, что эту функцию ставят как основной недостаток этой операционной системы. Не буду здесь подробно на нем останавливаться, скажу лишь, что у меня он включен по умолчанию, и я нахожу его очень даже полезным для себя, тем более что в Windows 7 он был значительно переработан, хотя на вкус и цвет – все фломастеры разные.

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

Несмотря на то, что UAC обладает некоторой "интеллектуальностью" и при запуске может определить нужно ли приложению увеличение привилегий или нет – возможности его ограничены, и он не всегда корректно работает, что приводит к тихому (или не всегда к тихому) «помиранию» запущенной программы, которой необходимы права администратора, но которые ей никто не дал. Поэтому перед разработчиком стоит задача явно указать необходимый уровень привилегий для своего приложения. Делается это через все тот же файл-манифест приложения, который появился в Windows XP и который используется для отрисовки интерфейса "в стиле XP".

Для явного указания необходимого уровня привилегий используется раздел Security:

<security>
<requestedprivileges>
<requestedexecutionlevel level="requireAdministrator">
</requestedprivileges>
</security>

Полностью файл-манифест приложения может выглядеть, например следующим образом:

<?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="UAC_Elevation_Prompt" type="win32" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32"
name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*" />
</dependentAssembly>
</dependency>
</assembly>

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

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

Но не все так просто в Delphi 2009. По каким-то своим, никому не известным причинам, разработчики решили добавлять манифест во все проекты по умолчанию. С одной стороны – довольно удобно, но с другой получается наоборот больше работы. Вот, например, так же по умолчанию в ресурсы добавляется иконка приложения и информация о версии. Это не плохо – потому, что существуют инструменты для их быстрого и безболезненного изменения. А манифест – не очень хорошо, мягко говоря, потому как он жестко задан в файле WindowsXP.res в наиболее общей форме и не учитывает специфики конкретного приложения, и нет инструментов для его изменения.

Так вот, при попытке добавления описанного выше манифеста в проект Delphi 2009 получаем предупреждение компилятора о дублировании ресурсов и наш манифест не включается в приложение. Можно перейти в исходный код проекта и убрать директиву компилятора {$R *.res}, но в этом случае мы лишимся иконки приложения и информации о версии. Можно убрать файл WindowsXP.res куда подальше, чтобы Delphi его не нашла – но это тоже неудачный способ выхода из положения – поскольку нарушается работа VCL.

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

Оригинальный способ для решения проблем использован в файловом менеджере Total Commander – для выполнения операций требующих повышения привилегий используется отдельное приложение TCADMIN.EXE, которому передается команда в случае невозможности выполнения операции с правами текущего пользователя.

Интересно, а как еще можно организовать повышение привилегий в Runtime и решить проблемы с манифестом в Delphi 2009?

8 комментариев:

  1. >>>Интересно, а как еще можно организовать повышение привилегий в Runtime и решить проблемы с манифестом в Delphi 2009?

    А если отключить галочку "Enable runtime themes" в опциях проекта? :)

    ОтветитьУдалить
  2. 2Andrew Tishkin
    В 99% случаев просто не нужно лезть в защищенные области и программа будет работать без прав администратора, поэтому способ, описанный автором вполне действенный. Есть еще вариант с виртуализацией, но он не дает реальных прав администратора:
    http://www.flenov.info/blog.php?catid=240

    ОтветитьУдалить
  3. 2 Andrew Tishkin:
    Спасибо за подсказку, работает :) Просто уж очень нелогично данная опция расположена

    ОтветитьУдалить
  4. Способ, использованный автором TC - рекомендованный Microsoft способ для организации работы с UAC. Так что не вижу в нем ничего особенного. Если приложение не является административным целиком, то есть смысл разбить его на два, одно из которых будет содержать функции, требующие полных административных прав, а второй только те возможности, с которыми может работать обычный пользователь.

    ОтветитьУдалить
  5. Спасибо) способ однозначно проче, чем способ с COM-объектом

    ОтветитьУдалить
  6. 2 C# программист
    Бе сомнения всё так, хранить натсройки надо давно не в програмфайлс, а в специальных папках системы и т.д. и т.п. Пример приложения, которое не нуждается в UAC - Google Chrome

    А вот ссылки на Флёнова давать... Наслыхан я уже об этом товарище. Уж поверьте, читать про UAC лучше на MSDN (читал статьи Руссиновича, и вам советую), а не в блоге дяди Ф ;-)

    ОтветитьУдалить
  7. "А манифест – не очень хорошо, мягко говоря, потому как он жестко задан в файле WindowsXP.res в наиболее общей форме и не учитывает специфики конкретного приложения, и нет инструментов для его изменения." - не совсем так, если изменить манифест в WindowsXP.res на выше описаный, то в исполняемом файле будет уже два манифеста, но приложение права админа получает.

    ОтветитьУдалить
  8. Мда, не работает эта схема повышения при запуске приложения со съёмного носителя (флэшки или CD). С харда всё повышается нормально.

    ОтветитьУдалить