3

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

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

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

那么...我如何确定用户是否可以执行 runas=admin?我们在 .net 3.5 上。

谢谢 - 戴夫

4

1 回答 1

2

我一般在我们写的一些客户端软件中使用的流程是这样的:

  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
于 2012-04-25T22:09:26.913 回答