WMI:远程编辑注册表

时间:2010-04-02 18:32:20

标签: c# permissions registry wmi uac

我正在尝试使用以下代码(写得不好,但它只是一个概念证明)来编辑域上计算机的注册表。我有一个域帐户,我已经验证域管理员组在我试图影响的计算机上的本地管理员组中。我已连接到这些其他计算机以执行其他管理类型的任务,因此我确信我对这些主机具有管理权限。

所有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();
    }
}

2 个答案:

答案 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)