Как я могу определить, может ли пользователь работать с правами администратора?

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

Мы являемся надстройкой к Office, поэтому работаем с правами Office. Обычно это не права администратора (если у них не отключено UAC). Поэтому WindowsPrincipal.IsInRole(Administrator) вернет false независимо от того, что пользователь может сделать.

Если у пользователя есть права локального администратора, мы хотим запустить апплет, который имеет runas=admin, и они могут установить его в HKLM. Однако, если они не имеют прав локального администратора, то мы помещаем это в HKCU.

Итак... Как я могу определить, может ли пользователь выполнить runas=admin? Мы на.net 3.5.

спасибо - Дэйв

1 ответ

Решение

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

  1. Попытайтесь запустить процесс с повышенными правами, чтобы установить ключи реестра.
  2. Подождите, пока процесс не завершится или не сгенерирует исключение.
  3. Проверка ключей реестра была установлена ​​при попытке прочитать ожидаемые ключи (не администратор может сделать это)
  4. Если ключи не были установлены, запустите резервный метод (например, запись в HKCU)

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

Private Function RunElevated(commandLine As String, Optional ByVal timeout As Integer = 0) As Boolean
    Dim startInfo As New ProcessStartInfo
    startInfo.UseShellExecute = True
    startInfo.WorkingDirectory = Environment.CurrentDirectory
    Dim uri As New Uri(Assembly.GetEntryAssembly.GetName.CodeBase)
    startInfo.FileName = uri.LocalPath
    startInfo.Verb = "runas"
    startInfo.Arguments = commandLine

    Dim success As Boolean
    Try
        Dim p As Process = Process.Start(startInfo)
        ' wait thirty seconds for completion
        If timeout > 0 Then
            If Not p.WaitForExit(30000) Then
                ' did not complete in thirty seconds, so kill
                p.Kill()
                success = False
            Else
                success = True
            End If
        Else
            p.WaitForExit()
            success = True
        End If
    Catch ex As Win32Exception
        success = False
    Catch ex As Exception
        MsgBox("Error occurred while trying to start application as administrator: " & ex.Message)
        success = False
    End Try
    Return success
End Function

В приведенном выше коде я обрабатываю исключения как код ошибки, а также ограничиваю выполнение 30 секундами для нашей среды. Вы можете не хотеть ограничивать время в вашем случае, поэтому вы можете просто удалить эту часть кода.

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

Public Function IsAdmin() As Boolean
    Dim id As WindowsIdentity = WindowsIdentity.GetCurrent
    Dim p As New WindowsPrincipal(id)
    Return p.IsInRole(WindowsBuiltInRole.Administrator)
End Function

Как только я узнаю, что я администратор, я продолжаю устанавливать ключи реестра и возвращаюсь. Затем программа вызывающего абонента проверяет, были ли успешно установлены ключи, чтобы определить, нужно ли запускать процедуру восстановления. Это когда RunElevated возвращается к вызывающей стороне, потому что в то время подпроцесс завершился и был либо успешным, либо не смог установить ключи. Этот код выглядит примерно так:

Public Function UpdateSettings(...) As Boolean
    Dim success As Boolean
    Try
        If Not IsAdmin() Then
            ' try to create the registry keys as administrator
            success = RunElevated(Command() & " /admin", 30000)
        Else
            ' if we're already admin, then just update directly
            success = UpdateSettingsAdmin(...)
        End If
        success = success And ValidateUpdateSettings(...)
    Catch ex As Exception
        success = False
    End Try
    Return success
End Function
Другие вопросы по тегам