WMI:远程编辑注册表

问题描述:

我试图使用下面的代码(写得不好,但它只是一个概念证明)来编辑域上的计算机注册表。我有一个域帐户,并且我已验证域管理员组存在于我试图影响的计算机上的本地管理员组中。我连接到这些其他机器来执行其他管理类型任务,所以我确信我拥有这些主机的管理权限。WMI:远程编辑注册表

根据winerror.h,StdRegProv的所有“get”方法都正常工作(http://msdn.microsoft.com/en-us/library/aa393664%28VS.85%29.aspx),但“set”或“create”方法以及检查访问都返回“Error_Access_Denied”的“5”。所以有这样的问题:当我试图修改注册表时,为什么我的访问被拒绝?如果有人能帮我弄清楚这一点,我会非常感谢!

我差点忘了,当我在本地机器上以管理员模式启动Visual Studio并在本地机器上运行代码时,它完美地工作。如果我没有在本地机器上以管理员模式启动,则代码失败,因此我怀疑可能存在UAC问题?

UPDATE:使用注册表编辑器并连接到远程计算机,我可以改变这使我相信这不是一个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(); 
    } 
} 

也可以关闭远程UAC过滤。

不建议通过更改控制远程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

+0

好的提示,但不幸的是,UAC需要通过策略在整个域中启用。另外,注册表值更改后,计算机是否需要重新启动? – Quanta 2010-04-02 20:20:43

+0

是的,它需要重新启动。似乎应该有办法解决这个问题... – 2010-04-02 20:52:12

+0

您是否尝试将您的用户添加到本地管理员组?根据我发布的链接:'如果您的计算机是域的一部分,请使用远程计算机的本地管理员组中的域帐户连接到目标计算机。然后,UAC访问令牌筛选将不会影响本地管理员组中的域帐户。我不知道在你的情况下这是否可能。 – 2010-04-02 20:54:30

看起来有问题运行WMI setter对UAC上的机器。

报价

从我们从现场收到报告,它出现UAC需要远程WMI查询工作被禁用。在UAC运行时,管理员帐户实际上具有两个安全令牌,一个普通用户令牌和一个管理员令牌(仅在您通过UAC提示时激活)。不幸的是,通过网络进入的远程请求会为管理员获取正常的用户令牌,并且由于无法远程处理UAC提示,所以令牌不能提升为真实管理员安全令牌。

来源: http://www.poweradmin.com/help/enableWMI.aspx

尝试编辑远程计算机的注册表项:

HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \政策\系统\ LocalAccountTokenFilterPolicy。

0 - 建立筛选的令牌(启用远程UAC) 1 - 构建提升的令牌(远程UAC禁用)

+0

这就是问题所在,我不能远程因为UAC是对编辑的关键。我将在数千台机器上运行此代码,并且他们都需要运行UAC,不幸的是:/ – Quanta 2010-04-02 20:21:33