Подтвердить что ты не робот

Необходимость UAC для консольного приложения

У меня есть консольное приложение, для которого требуется использовать код, требующий уровня администратора. Я прочитал, что мне нужно добавить файл манифеста myprogram.exe.manifest, который выглядит так:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator">
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Но он по-прежнему не повышает UAC (в консоли или при отладке в VS). Как я могу решить эту проблему?

Update

Я могу заставить его работать, если я запустил решение в Administrator или когда я запустил /bin/ *.exe в Administrator. Я все еще задаюсь вопросом, возможно ли иметь что-то, что будет появляться, когда приложение запускается, а не прямое нажатие правой кнопки мыши > Запуск от имени администратора?

4b9b3361

Ответ 1

Вам нужно встроить манифест UAC в качестве встроенного ресурса Win32. См. Добавление манифеста UAC в управляемый код.

Короче говоря, вы используете инструмент командной строки Windows SDK для вставки его в свой исполняемый файл.

Вы можете автоматизировать это как шаг после сборки, поставив следующую строку в качестве задачи пост-сборки в свойствах проекта VS:

mt.exe -manifest "$(ProjectDir)$(TargetName).exe.manifest" -updateresource:"$(TargetDir)$(TargetName).exe;#1"

Ответ 2

Для всех, кто использует Visual Studio, это очень просто. Я собирался настроить SDK для Windows и выполнить шаги post-build mt.exe и все это, прежде чем реализовать его в VS. Я решил, что записал его для потомков.

  • Проект | Добавить новый элемент → Элементы Visual С# → Файл манифеста приложений
  • Откройте app.manifest, измените requestExecutionLevel. @level на "requireAdministrator"
  • Построить

Та-да

Ответ 3

Ответ Скотта будет делать то, что вы просили, но Microsoft рекомендует, чтобы консольные приложения отображали сообщение "отказ в доступе", а не запрос на повышение.

Из http://msdn.microsoft.com/en-us/library/bb756922.aspx:

Консольное приложение представляет свой вывод в окне консоли, а не с отдельным пользовательским интерфейсом. Если для приложения требуется полный администратор токен доступа для запуска, то это приложение необходимо запустить из приподнятое консольное окно.

Для консольных приложений вы должны сделать следующее:

  • Отметьте, что ваше приложение "asInvoker": вы можете сделать это, создав манифест вашего приложения, в котором вы установите RequestedExecutionLevel == asInvoker. Эта настройка позволяет вызывающим абонентам из невыполненных контекстов создавать ваш процесс, что позволяет им перейти к шагу 2.

  • Предоставьте сообщение об ошибке, если приложение запущено без токена доступа для полного доступа администратора. Если приложение запущено на не-поднятой консоли, ваше приложение должно предоставить краткое сообщение и выйти. Рекомендуемое сообщение: "Доступ запрещен. Для использования выбранных параметров необходимы разрешения администратора. Для выполнения этих задач используйте командную строку администратора."

Приложение также должно вернуть код ошибки ERROR_ELEVATION_REQUIRED при неудаче запуска для облегчения написания сценариев.

Мой код С# для этого ниже. Он протестирован в Windows XP (администратор → ok, стандартный пользователь → запрещен) и Windows Server 2008 (повышенный администратор → ok, неа повышенный администратор → отклонен, стандартный пользователь → отклонен).

static int Main(string[] args)
{
    if (!HasAdministratorPrivileges())
    {
        Console.Error.WriteLine("Access Denied. Administrator permissions are " +
            "needed to use the selected options. Use an administrator command " +
            "prompt to complete these tasks.");
        return 740; // ERROR_ELEVATION_REQUIRED
    }

    ...
    return 0;
}

private static bool HasAdministratorPrivileges()
{
    WindowsIdentity id = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(id);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}