Как я могу определить, может ли пользователь работать с правами администратора?
Когда пользователю нужно ввести свой лицензионный ключ, мы хотим поместить его в HKLM, если можем, и в HKCU, если не можем. Если он находится в HKLM, то все пользователи на компьютере имеют лицензию без необходимости ее ввода.
Мы являемся надстройкой к Office, поэтому работаем с правами Office. Обычно это не права администратора (если у них не отключено UAC). Поэтому WindowsPrincipal.IsInRole(Administrator) вернет false независимо от того, что пользователь может сделать.
Если у пользователя есть права локального администратора, мы хотим запустить апплет, который имеет runas=admin, и они могут установить его в HKLM. Однако, если они не имеют прав локального администратора, то мы помещаем это в HKCU.
Итак... Как я могу определить, может ли пользователь выполнить runas=admin? Мы на.net 3.5.
спасибо - Дэйв
1 ответ
Процесс, который я обычно использую в некотором клиентском программном обеспечении, который мы написали, выглядит следующим образом:
- Попытайтесь запустить процесс с повышенными правами, чтобы установить ключи реестра.
- Подождите, пока процесс не завершится или не сгенерирует исключение.
- Проверка ключей реестра была установлена при попытке прочитать ожидаемые ключи (не администратор может сделать это)
- Если ключи не были установлены, запустите резервный метод (например, запись в 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