我正在尝试使用以下代码(写得不好,但它只是一个概念证明)来编辑域上计算机的注册表。我有一个域帐户,我已经验证域管理员组在我试图影响的计算机上的本地管理员组中。我已连接到这些其他计算机以执行其他管理类型的任务,因此我确信我对这些主机具有管理权限。
所有StdRegProv的“get”方法都可以正常工作(http://msdn.microsoft.com/en-us/library/aa393664%28VS.85%29.aspx)但是“set”或“create”方法以及check all都返回“5”,根据winerror.h,它是“Error_Access_Denied”。所以有问题:为什么我在尝试修改注册表时会被拒绝访问?如果有人能帮我解决这个问题,那么你将非常感谢!
我差点忘了,当我在本地计算机上以管理模式启动Visual Studio并对本地计算机运行代码时,它可以正常运行。如果我没有在本地计算机上以管理模式启动,代码会失败,所以我怀疑可能存在UAC问题?
更新:使用regedit并连接到远程计算机,我可以更改注册表项,这使我相信这不是UAC问题,但它在运行时使用本地WMI连接执行在我自己的机器上提升模式,所以也许它是UAC。此外,winXP机器返回相同的错误代码(5,ERROR_ACCESS_DENIED),这让我相信它不是UAC ......这很糟糕。
已解决:ManagementClass对象使用了错误的覆盖;它必须使用ManagementScope进行参数化,否则,您只需在本地执行函数。
ManagementClass mc = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
是的,我是一个史诗般的失败:/ 9K行代码,这条线让我把它们放得最长。
using System;
using System.Management;
public class EditRemoteRegistry
{
public static void Main(string[] args)
{
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
options.Impersonation = ImpersonationLevel.Impersonate;
options.Password = "password goes here";
//options.Authority = "my company's domain";
//options.Username = "Admin username";
ManagementScope scope = new ManagementScope("\\\\arbitraryhost\\root\\default", options);
scope.Connect();
ManagementClass mc = new ManagementClass("StdRegProv");
ManagementBaseObject inParams = mc.GetMethodParameters("CreateKey");
inParams["hDefKey"] = (UInt32)2147483650;
inParams["sSubKeyName"] = "Software\\Test";
ManagementBaseObject outParams = mc.InvokeMethod("CreateKey", inParams, null);
//Should return a 0, but returns a 5, "Error_Access_Denied"
Console.WriteLine("CreateKey Method returned " + outParams["returnValue"]);
//This chunk works fine
ManagementBaseObject inParams5 = mc.GetMethodParameters("GetDWORDValue");
inParams5["hDefKey"] = 2147483650;
inParams5["sSubKeyName"] = "Software\\Test";
inParams5["sValueName"] = "testDWORDvalue";
ManagementBaseObject outParams5 = mc.InvokeMethod("GetDWORDValue", inParams5, null);
Console.WriteLine("GetDWORDValue returned " + (UInt32)outParams5["returnValue"] + " ");
Console.WriteLine((UInt32)outParams5["uValue"]);
ManagementBaseObject inParams6 = mc.GetMethodParameters("SetStringValue");
inParams6["hDefKey"] = 2147483650;
inParams6["sSubKeyName"] = "Software\\Test";
inParams6["sValueName"] = "TestStringValue";
inParams6["sValue"] = "Hello World!";
ManagementBaseObject outParams6 = mc.InvokeMethod("SetStringValue", inParams6, null);
//Should return a 0, but returns a 5, "Error_Access_Denied"
Console.WriteLine("SetStringValue returned " + outParams6["returnValue"]);
Console.ReadKey();
}
}
答案 0 :(得分:2)
您也可以关闭远程UAC过滤。
不建议通过更改控制远程UAC的注册表项来禁用远程UAC,但在工作组中可能是必需的。注册表项是HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Policies \ system \ LocalAccountTokenFilterPolicy。当此条目的值为零(0)时,将启用远程UAC访问令牌过滤。值为1时,禁用远程UAC。
http://msdn.microsoft.com/en-us/library/aa826699(VS.85).aspx
答案 1 :(得分:0)
对于启用了UAC的计算机,似乎存在运行WMI setter的问题。
引用
根据我们从现场收到的报告,似乎需要禁用UAC才能使远程WMI查询正常工作。在UAC运行时,管理员帐户实际上有两个安全令牌,一个普通用户令牌和一个管理员令牌(只有在您通过UAC提示时才会激活)。不幸的是,通过网络进入的远程请求获得管理员的正常用户令牌,并且由于无法远程处理UAC提示,因此无法将令牌提升为真正的管理员安全令牌。
源: http://www.poweradmin.com/help/enableWMI.aspx
尝试编辑远程计算机的注册表项:
HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \政策\ SYSTEM \ LocalAccountTokenFilterPolicy。
0 - 构建过滤令牌(启用远程UAC) 1 - 构建提升令牌(禁用远程UAC)