使用WMI COM对象监视远程服务

时间:2014-12-24 12:08:20

标签: c# service wmi

我正在尝试使用WMI组件访问远程计算机的服务状态(如果有任何其他方式建议)。

以下是我的代码:

public void MonitorService()
{
                ConnectionOptions con = new ConnectionOptions();
                con.Username = "username";
                con.Password = "password";
                con.Authority = "ntlmdomain:somedomain";
                con.Authentication = AuthenticationLevel.Connect;
                con.EnablePrivileges = true;
                con.Impersonation = ImpersonationLevel.Identify;
                ManagementScope scope = new ManagementScope(@"\\machinename\root\cimv2", con);
                scope.Connect();
                ManagementPath path = new ManagementPath("Win32_Service");
                ManagementClass services;
                services = new ManagementClass(scope, path, null);

                foreach (ManagementObject service in services.GetInstances())
                {

                    // some manipulations

                }
}


scope.Connect(),我从HRESULT获得错误"异常:0x80070005(E_ACCESSDENIED)"

我在ConnectionOption中使用的用户在远程系统上拥有管理员权限。 我允许用户访问远程计算机中的WMI COM对象。我已经通过link但没有帮助我。请告诉我我缺少的东西。

3 个答案:

答案 0 :(得分:1)

首先,尝试以管理员身份运行visual studio,或以管理员身份运行输出exe。

此外,您需要使用Impersonation = ImpersonationLevel.Impersonate而不是Identity,因此请尝试以下代码:

VB.NET:

Dim opt As ObjectGetOptions
 opt = New ObjectGetOptions(Nothing, TimeSpan.MaxValue, True)
 Using manClass As New ManagementClass("\\YOUR_MACHINE\root\cimv2", "Win32_Service", opt)
    manClass.Scope.Options.EnablePrivileges = True
    manClass.Scope.Options.Impersonation = ImpersonationLevel.Impersonate
    manClass.Scope.Options.Username = "username"
    manClass.Scope.Options.Password = "pass"
    manClass.Scope.Options.Authority = "ntlmdomain:Domain"
 End Using  

C#:(在线转换)

ObjectGetOptions opt = default(ObjectGetOptions);
opt = new ObjectGetOptions(null, TimeSpan.MaxValue, true);
using (ManagementClass manClass = new ManagementClass("\\\\YOUR_MACHINE\\root\\cimv2", "Win32_Service", opt)) {
    manClass.Scope.Options.EnablePrivileges = true;
    manClass.Scope.Options.Impersonation = ImpersonationLevel.Impersonate;
    manClass.Scope.Options.Username = "username";
    manClass.Scope.Options.Password = "pass";
    manClass.Scope.Options.Authority = "ntlmdomain:Domain";
}

有关详细信息,请参阅codeplex上的开源Windows Services Manager (Services+)

答案 1 :(得分:0)

另一种选择(根据您的要求)将使用PowerShell远程处理。与WMI远程处理相比,Powershell远程处理以一种根本不同的方式工作。

Here是一个示例,偶然使用来自C#的Get-Service cmdlet从远程计算机获取服务信息(默认为localhost

答案 2 :(得分:0)

首先,我建议不要将Authentication属性更改为默认值,除非您完全确定需要这样做。 Documentation for this property表示数据包级别身份验证用于Windows XP及更高版本,而连接级别身份验证用于Windows 2000及更低版本。默认设置将使用服务器指定的任何身份验证,这比指示服务器可能不接受的特定身份验证级别更有可能。你需要设置Authority属性也是不寻常的,因为默认情况下它将对当前用户的域使用NTLM身份验证,但这样做可能不会伤害任何东西。对于Impersonation属性,我同意Sameh应该使用ImpersonationLevel.Impersonate的值(也是默认值)。通常,您不必更改任何ConnectionOptions属性值,除非您需要连接除运行该程序的用户帐户以外的用户帐户,然后您只需要更改用户名和密码。

其次,我不太确定“允许管理员访问远程计算机上的WMI COM”的含义。根据我的经验,当远程WMI无法连接时,通常是因为Windows防火墙阻碍了它。如果您还没有,我还建议您在尝试连接的计算机上运行以下命令(请参阅您最初Connecting Through Windows Firewall所在页面中的链接linked)。

netsh防火墙设置服务RemoteAdmin启用

关于服务的API,.NET框架包括System.ServiceProcess.ServiceController类,它提供有关本地或远程计算机上的命名服务的信息并对其进行控制。但是,看起来这个API不允许在连接时指定用户名和密码,因此如果您没有以连接用户身份运行程序,这可能不是一个可行的解决方案。如果您将程序作为需要用于远程连接的帐户运行并想要尝试此类,请注意您必须添加对System.ServiceProcess的引用,因为它未包含在默认框架中大多数新VS项目的参考资料。