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

Posted

技术标签:

【中文标题】使用 WMI COM 对象监视远程服务【英文标题】:Monitor Remote Service using WMI COM objects 【发布时间】:2014-12-24 12:08:20 【问题描述】:

我正在尝试使用 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 但没有帮助我。请告诉我我缺少的东西。

【问题讨论】:

【参考方案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+)。

【讨论】:

尝试了所有 ImpersonationLevel 选项并尝试以管理员权限运行 VS,仍然收到相同的访问被拒绝消息。【参考方案2】:

另一种方法(根据您的要求)是使用 PowerShell 远程处理。与 WMI 远程处理相比,Powershell 远程处理的工作方式完全不同。

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

【讨论】:

这里我遇到了类 WSManConnectionInfo 的问题,即使在从 powershell v1 添加了所需 dll 的引用之后也是如此。 有什么问题?随意问另一个问题。 :)(或者如果它很小/相关,请发表评论) ***.com/questions/27798696/…【参考方案3】:

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

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

netsh 防火墙设置服务 RemoteAdmin 启用

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

【讨论】:

以上是关于使用 WMI COM 对象监视远程服务的主要内容,如果未能解决你的问题,请参考以下文章

SCOM 监视器的 WMI 访问被拒绝错误

Powershell - 调用远程 WMI 对象 - RPC 错误 HRESULT:0x800706BA(RPC 服务器不可用)

什么是WMI 有什么用?

C# - Windows 服务 - 远程 WMI 查询抛出错误:找不到 RPC

作为 Windows 服务托管时,远程 WMI 不起作用

远程 WMI 查询慢