Регистрация типа файла

75

Допустим нужно зарегистрировать в Windows расширение файла (например .testDoc) и ассоциировать его с приложением. После этого щелчок на файле *.testDoc должен приводить к немедленному запуску приложения.

Один из способов зарегистрировать этот тип файла вручную предусматривает использование проводника Windows:

Другой способ регистрации типа файла состоит в выполнении кода, который редактирует системный реестр:

string extension = ".testDoc";
string title = "SingleInstanceApplication";
string extensionDescription = "A Test Document";
FileRegistrationHelper.SetFileAssociation(
   extension, title + "." + extensionDescription);

Класс FileRegistrationHelper регистрирует расширение файла .testDoc, используя классы из пространства имен Microsoft.Win32.

Процесс регистрации должен выполняться только однажды. После того, как регистрация завершена, любой двойной щелчок на файле с расширением .testDoc приводит к запуску SingleInstanceApplication, и этот файл передается в виде аргумента командной строки. Если SingleInstanceApplication уже запущен, то вызывается метод SingleInstanceApplicationWrapper.OnStartupNextInstance() и существующее приложение загружает новый документ.

Контроль учетных записей пользователей

Регистрация файла — это задача, которая обычно выполняется программой установки. Проблема с включением ее в код приложения состоит в том, что она требует повышенных привилегий, которых может не иметь пользователь, запустивший приложение. В частности, здесь вступает в действие средство контроля учетных записей пользователей (User Account Control — UAC) в Windows Vista и Windows 7. Фактически по умолчанию этот код завершится сбоем с генерацией исключения, связанного с безопасностью.

С точки зрения UAC все приложения имеют один из трех уровней выполнения:

asInvoker

Приложение наследует маркер процесса от родительского процесса (процесса, запустившего его). Приложение не получит административных привилегий, если только пользователь специально не запросит их — даже если пользователь зарегистрирован как администратор. Этот уровень принимается по умолчанию.

requireAdministrator

Если текущий пользователь является членом группы Administrators (Администраторы), появится диалоговое окно подтверждения UAC. Как только пользователь подтвердит, приложение получит административные привилегии. Если же пользователь не является членом группы Administrators, появится диалоговое окно, где пользователь сможет ввести имя и пароль учетной записи, обладающей административными привилегиями.

highestAvailable

Приложение получает максимальные привилегии согласно членству в группах. Например, если текущий пользователь — член группы Administrators, то приложение получает административные привилегии (как только примет подтверждение UAC). Преимущество этого уровня выполнения в том, что приложение продолжит выполнение, если административные привилегии недоступны, в отличие от requireAdministrator.

Обычно приложение выполняется с уровнем aslnvoker. Чтобы запросить административные привилегии, при запуске необходимо щелкнуть правой кнопкой мыши на ЕХЕ-файле и выбрать в контекстном меню пункт Run As Administrator (Запуск от имени администратора). Чтобы получить административные привилегии при тестировании приложения в среде Visual Studio, потребуется щелкнуть правой кнопкой мыши на ярлыке Visual Studio и выбрать в контекстном меню пункт Run As Administrator.

Если приложению требуются административные привилегии, их можно запросить с помощью уровня выполнения requireAdministrator или highestAvailable. В любом случае понадобится создать манифест — файл с блоком XML-разметки, который будет встроен в скомпилированную сборку. Чтобы добавить манифест, щелкните правой кнопкой мыши на проекте в Solution.Explorer и выберите в контекстном меню пункт Add --> New Item (Добавить) --> Новый элемент). Укажите шаблон Application Manifest File (Файл манифеста приложения) и щелкните на кнопке Add (Добавить).

Для изменения уровня выполнения просто модифицируйте атрибут уровня элемента <requestedExecutionLevel>. Допустимыми значениями являются aslnvoker, requireAdministrator и highestAvailable:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel  level="highestAvailable" />
        <!-- Параметры манифеста UAC
          При необходимости изменить уровень управления учетными записями Windows замените 
          узел requestedExecutionLevel одним из следующих значений.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            Задание узла requestedExecutionLevel отключит виртуализацию файла и реестра.
            Если виртуализацию файла и реестра нужно использовать для обратной 
            совместимости, удалите узел requestedExecutionLevel.
        -->
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
  
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Список всех версий Windows, с которыми это приложение предназначено работать. Windows автоматически выберет наиболее совместимую среду.-->

      <!-- Если приложение предназначено для работы с Windows 7, раскомментируйте следующий узел supportedOS-->
      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
      
    </application>
  </compatibility>
  
  <!-- Включите темы для общих элементов управления и диалоговых окон Windows (Windows XP и более поздние версии) -->
  <!-- <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>-->

</asmv1:assembly>

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

Пройди тесты
Лучший чат для C# программистов