Как Windows решает, отображать ли приглашение UAC?

В моем приложении VB6 я открываю другие EXE файлы. Мое приложение запускается без приглашения UAC, но у меня есть EXE, который проверяет наличие обновлений программного обеспечения. Это вызывает приглашение UAC. Итак, как Windows решает, показывать ли приглашение UAC? Я видел ссылку . Так зависит ли он от кода, который я написал в своем приложении? Интересно, что мое приложение (то есть основной файл EXE) не запрашивает UAC, тогда как небольшой EXE, который проверяет и загружает обновления, запрашивает UAC. У меня есть все файлы EXE с цифровой подписью. Я уже взглянул на следующие ссылки:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx

http://technet.microsoft.com/en-us/library/cc505883.aspx и некоторые другие.

Но я все еще не понимаю.

Ответы

Ответ 1

Вы почти наверняка используете эвристику совместимости с Windows Installer Detection Technology. Windows попытается определить, когда приложение является установщиком, и, вероятно, необходимо повысить его.

Обнаружение установщика применяется только к:

  • 32-разрядные исполняемые файлы
  • Приложения без requestedExecutionLevel
  • Интерактивные процессы, выполняемые в качестве стандартного пользователя с включенным LUA

Перед созданием 32-битного процесса проверяются следующие атрибуты, чтобы определить, является ли он установщиком:

  • Имя файла включает такие ключевые слова, как "установка", "настройка", "обновление" и т.д.
  • Ключевые слова в следующих полях Ресурсы для Версии: поставщик, название компании, название продукта, описание файла, исходное имя файла, внутреннее имя и имя экспорта.
  • Ключевые слова в бок о бок манифест, встроенный в исполняемый файл.
  • Ключевые слова в определенных строковых записях, связанных в исполняемом файле.
  • Ключевые атрибуты в данных RC, связанных с исполняемым файлом.
  • Целевые последовательности байтов в исполняемом файле.

Итак, как вы сказали:

но у меня есть exe, который проверяет наличие обновлений для программного обеспечения

Я предполагаю, что этот CheckForUpdates.exe запускает эвристику совместимости.

правильная вещь - это манифест сборки для вашего "проверяющего" исполняемого файла, информирующий Windows о том, что он должен не поднять утилиту. Это делается с помощью requestedExecutionLevel asInvoker в манифесте:

AssemblyManifest.xml:

<?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="X86"
      name="client"
      type="win32"
   /> 

   <description>Update checker</description> 

   <!-- Run as standard user. Disable file and registry virtualization -->
   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
      <security>
         <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
         </requestedPrivileges>
      </security>
   </trustInfo>
</assembly>

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

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

Пример кода

//Check if there are updates available
if (!CheckForUpdatesAvailable())
   return; //no updates. We're done

//If the user is an administrator, then get the update
if (IsUserAnAdmin())
{
    //Maybe throw in a "Hey, user, wanna get the update now?" dialog
    DownloadAndApplyUpdates();
    return;
}

//The user is not an admin. 
//Relaunch ourselves as administrator so we can download the update
//Maybe throw in a "Hey, user, wanna get the update now?" dialog. A button with a UAC shield on it
ExecuteAsAdmin(Application.ExecutablePath, "/downloadUpdate");

со вспомогательными функциями:

private Boolean IsUserAnAdmin()
{
    //A user can be a member of the Administrator group, but not an administrator.
    //Conversely, the user can be an administrator and not a member of the administrators group.
    var identity = WindowsIdentity.GetCurrent();
    return (null != identity && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator));
}

private void ExecuteAsAdmin(string Filename, string Arguments)
{
    ProcessStartInfo startInfo = new ProcessStartInfo(Filename, Arguments);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
}

Тогда вам просто нужно искать параметр командной строки /downloadUpdate при запуске, чтобы знать, что вы работаете, чтобы на самом деле работать:

public Form1()
{
    InitializeComponent();

    //Ideally this would be in program.cs, before the call to Application.Run()
    //But that would require me to refactor code out of the Form file, which is overkill for a demo
    if (FindCmdLineSwitch("downloadUpdate", true))
    {
        DownloadAndApplyUpdates();
        Environment.Exit(0);
    }
}

Примечание. Любой код выпущен в общедоступном домене. Не требуется атрибуция.

Ответ 2

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

Как запросить привилегии администратора

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

Ответ 3

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

Эти эвристики включают поиск ключевых слов в имени файла EXE и нескольких расширенных свойствах EXE и могут даже искать известные двоичные подписи (например, байтовые строки) внутри файла.

Кстати, ваше шифрование не входит в это вообще. И это не помогает, если он не был выпущен доверенным ЦС.

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

Ответ 4

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

Теперь, в зависимости от точной версии Windows и обновлений безопасности, эта привилегия остается доступной некоторое время даже для других (дочерних) процессов. Это может предотвратить дублирование запросов UAC.