如何确定用户是否可以运行admin?

时间:2012-04-25 21:13:35

标签: .net windows-identity windows-principal

当用户需要输入他们的许可证密钥时,如果可以,我们希望将其放入HKLM,如果我们不能,则在HKCU中。如果它在HKLM中,则计算机上的所有用户都拥有许可证,而不必每次都输入它。

我们是Office的AddOn,因此我们使用Office权限运行。通常这不是管理员权限(除非他们关闭了UAC)。因此,无论用户做什么,WindowsPrincipal.IsInRole(管理员)都将返回false。

如果用户具有本地管理员权限,我们想要启动一个具有runas = admin的applet,然后他们可以在HKLM中设置它。但是,如果他们没有本地管理员权限,那么我们将其放入HKCU。

那么......我怎样才能确定用户是否可以执行runas = admin?我们在.net 3.5。

谢谢 - 戴夫

1 个答案:

答案 0 :(得分:2)

我通常在我们编写的某些客户端软件中使用的过程如下所示:

  1. 尝试启动提升的进程以设置注册表项。
  2. 等待该过程完成或抛出异常。
  3. 通过尝试读取预期的密钥来设置验证注册表项(非管理员可以执行此操作)
  4. 如果未设置密钥,请运行后备方法(例如,写入HKCU)
  5. 我有一个帮助函数来运行看起来像这样的提升代码(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