模拟在.NET在Windows 7(请求的注册表访问是不允许的) [英] Impersonation in .NET in Windows 7 (Requested registry access is not allowed)
问题描述
所以,我使用的是用户运行以下code即用户组的Windows 7中,64位机上的成员。我想使用模拟(通过登录的用户是管理员组的一部分),允许当前用户从注册表中读取。出于某种原因,用户登录成功后会发生,但即使WindowsIdentity.GetCurrent()的返回是管理员组我仍然得到请求的注册表访问不允许一个错误信息说的部分用户。我究竟做错了什么?
这是主要的code:
昏暗RA由于运行方式=无
如果UserDomain.Length> 0 AndAlso UserName.Length> 0 AndAlso UserPassword.Length> 0然后
RA =新的运行方式
ra.ImpersonateStart(USERDOMAIN,用户名的userPassword)
结束如果
如果不My.Computer.Registry.GetValue(HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ Windows错误报告,DontShowUI,0)是没有AndAlso _
My.Computer.Registry.GetValue(HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ Windows错误报告,DontShowUI,0)= 0,那么
My.Computer.Registry.SetValue(HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ Windows错误报告,DontShowUI,1)
结束如果
再假设我的RunAs类如下:
公共类的RunAs
公开声明自动功能CloseHandle的库KERNEL32.DLL(BYVAL句柄作为IntPtr的)作为布尔
公开声明自动功能DuplicateToken库ADVAPI32.DLL(BYVAL ExistingTokenHandle作为IntPtr的,_
BYVAL SECURITY_IMPERSONATION_LEVEL作为整数,_
为ByRef DuplicateTokenHandle作为IntPtr的)作为布尔
测试工具。
如果你把这种code到DLL时,一定要要求FullTrust的。
< PermissionSetAttribute(SecurityAction.Demand,名称:=FullTrust的)> _
公用Sub ImpersonateStart(BYVAL域作为字符串,BYVAL用户名作为字符串,BYVAL密码作为字符串)
tokenHandle = IntPtr.Zero
调用LogonUser来获取句柄到一个访问令牌。
昏暗的returnValue作为布尔= LogonUser的(用户名,域,密码,2,0,tokenHandle)
检查是否登录成功
如果的returnValue = false,那么
昏暗RET作为整数= Marshal.GetLastWin32Error()
Console.WriteLine(LogonUser的失败,错误code:{0},RET)
抛出新System.ComponentModel.Win32Exception(RET)
退出小组
结束如果
登录成功
'使用的LogonUser返回的令牌句柄。
昏暗NEWID作为新的WindowsIdentity(tokenHandle)
impersonatedUser = newId.Impersonate()
结束小组
末级
我同意@Hans。通过UAC,您需要重新启动了UAC权限的应用程序,这将导致UAC提示显示。实现此目的的一个简单方法如下:
- 在该应用程序的正常路径,当需要管理员权限,重新启动与UAC要求和命令行标志,就像
/管理员
应用程序。 - 在应用程序的第二次运行,检测标记
/管理员
,并执行应用程序的管理部分。 - 当第二次运行结束(#2),如果它是成功的,然后继续应用程序逻辑从第一关。如果不成功,显示错误/执行适当的异常处理逻辑。
在我们的应用程序,我有一个名为helper方法 RunElevated
,试图重新启动应用程序与要求管理员权限,这将导致UAC提示显示(我也有包括我IsAdmin()辅助功能):
专用功能RunElevated(命令行作为字符串,可选BYVAL超时为整数= 0)作为布尔
昏暗的StartInfo作为新的ProcessStartInfo
startInfo.UseShellExecute = TRUE
startInfo.WorkingDirectory = Environment.CurrentDirectory
昏暗URI作为新的URI(Assembly.GetEntryAssembly.GetName。codeBase类)
startInfo.FileName = uri.LocalPath
startInfo.Verb =运行方式
startInfo.Arguments =命令行
昏暗的成功作为布尔
尝试
昏暗的数p作为流程=的Process.Start(StartInfo的)
等待30秒完成
如果超时> 0然后
如果不p.WaitForExit(30000)则
没有完成在三秒,杀
p.Kill()
成功=假
其他
成功= TRUE
结束如果
其他
p.WaitForExit()
成功= TRUE
结束如果
抓住EX作为Win32Exception
成功=假
抓住EX为例外
MSGBOX(试图启动应用程序以管理员身份发生了错误:&放大器; ex.Message)
成功=假
结束尝试
返回成功
端功能
公共功能IsAdmin()作为布尔
昏暗的ID作为的WindowsIdentity = WindowsIdentity.GetCurrent
昏暗的数p作为新的WindowsPrincipal(ID)
返回p.IsInRole(WindowsBuiltInRole.Administrator)
端功能
要使用,我通过一个标志和运行升高。就我而言,我有一个功能,设置注册表项,并使用标志 / setregistry
来表示该实例启动了UAC的目的只是设置的注册表项。这code看起来是这样的:
昏暗的成功作为布尔
如果不IsAdmin(),然后
尝试创建注册表项以管理员身份
成功= RunElevated(/ setregistry,30000)
成功=成功而ValidateKeysSet()检查,如果它是成功的
返回成功
结束如果
如果我们的管理员(不是IsAdmin()= FALSE),然后继续前进,在这里设置的键
然后,在启动逻辑(的Form_Load,因为这是一个形式应用),我检查是否该标志是present:
如果Command.ToLower.Contains(/ setregistry),然后
如果应用程序实例是设置注册表项,管理的唯一目的
如果IsAdmin(),然后
SetRegistryKeys()'设置键,因为我们都是admin
其他
MSGBOX(错误:应用程序必须以管理员身份运行设置注册表项。)
结束如果
其他
执行正常启动过程
结束如果
So I am using a user to run the following code that is a member of the "User" group on a Windows 7, x64 machine. I am trying to use impersonation (by logging in as a user that is part of the Administrator group) to allow the current user to read from the registry. For some reason the login happens successfully but even though WindowsIdentity.GetCurrent() is returning the user that is part of the Administrator group I am still getting an error message saying "Requested registry access is not allowed". What am I doing wrong?
This is the main code:
Dim ra As RunAs = Nothing
If UserDomain.Length > 0 AndAlso UserName.Length > 0 AndAlso UserPassword.Length > 0 Then
ra = New RunAs
ra.ImpersonateStart(UserDomain, UserName, UserPassword)
End If
If Not My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting", "DontShowUI", 0) Is Nothing AndAlso _
My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting", "DontShowUI", 0) = 0 Then
My.Computer.Registry.SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting", "DontShowUI", 1)
End If
And suppose my RunAs class is the following:
Public Class RunAs
Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Boolean
' Test harness.
' If you incorporate this code into a DLL, be sure to demand FullTrust.
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Sub ImpersonateStart(ByVal Domain As String, ByVal userName As String, ByVal Password As String)
tokenHandle = IntPtr.Zero
' Call LogonUser to obtain a handle to an access token.
Dim returnValue As Boolean = LogonUser(userName, Domain, Password, 2, 0, tokenHandle)
'check if logon successful
If returnValue = False Then
Dim ret As Integer = Marshal.GetLastWin32Error()
Console.WriteLine("LogonUser failed with error code : {0}", ret)
Throw New System.ComponentModel.Win32Exception(ret)
Exit Sub
End If
'Logon succeeded
' Use the token handle returned by LogonUser.
Dim newId As New WindowsIdentity(tokenHandle)
impersonatedUser = newId.Impersonate()
End Sub
End Class
I agree with @Hans. With UAC, you need to restart the application with UAC privileges, which will cause the UAC prompt to display. A simple way to accomplish this is as follows:
- In normal path of the application, when admin privileges are needed, restart the application with UAC request and a command-line flag, like
/admin
. - On second run of the application, detect the flag
/admin
, and do the administrative part of the application. - When the second run finishes (#2), if it was successful, then continue application logic from the first pass. If not successful, display error/perform appropriate exception handling logic.
In our application, I have a helper method called RunElevated
that attempts to restart the application with requested administrator privileges, which will cause the UAC prompt to display (I have also included my IsAdmin() helper function):
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
Public Function IsAdmin() As Boolean
Dim id As WindowsIdentity = WindowsIdentity.GetCurrent
Dim p As New WindowsPrincipal(id)
Return p.IsInRole(WindowsBuiltInRole.Administrator)
End Function
To use, I pass a flag and run elevated. In my case, I have a function that sets registry keys, and uses the flag /setregistry
to indicate that the instance is started for UAC purposes to just set the registry keys. That code looks something like this:
Dim success As Boolean
If Not IsAdmin() Then
' try to create the registry keys as administrator
success = RunElevated("/setregistry", 30000)
success = success And ValidateKeysSet() ' check if it was successful
Return success
End If
' If we are Admin (Not IsAdmin() = False), then go ahead and set the keys here
Then in the startup logic (Form_Load, since this is a forms application), I check if that flag is present:
If Command.ToLower.Contains("/setregistry") Then
' if application instance is for sole purpose of setting registry keys as admin
If IsAdmin() Then
SetRegistryKeys() ' set the keys, since we are admin
Else
MsgBox("ERROR: Application must be run as administrator to set registry keys.")
End If
Else
' Perform normal startup process
End If
这篇关于模拟在.NET在Windows 7(请求的注册表访问是不允许的)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!