ManagementEventWatcher(WMI) 通知来自远程计算机的事件时出现异常

Posted

技术标签:

【中文标题】ManagementEventWatcher(WMI) 通知来自远程计算机的事件时出现异常【英文标题】:Exception while ManagementEventWatcher(WMI) to notify events from remote machine 【发布时间】:2010-05-06 15:31:47 【问题描述】:

我正在尝试使用 WMI 和 C# 从远程机器的事件查看器中获取通知。我可以使用ManagementObjectSearcher 连接系统并获取事件日志。但是当我尝试使用ManagementEventWatcher.Start 方法时,我遇到了一个异常:

访问被拒绝。 (来自 HRESULT 的异常:0x80070005 (E_ACCESSDENIED))

我已将 WMI 控制中的权限授予root\cimv2,并在 DCOM Config 中授予用户帐户的管理员权限。

我有正常的 Windows 应用程序,因此我没有使用 ASP.net(ASPNET 用户)。

我的代码是:

ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Username = @"Domain\UName";//txtUserName.Text;
connectionOptions.Password = "pass";//txtPassword.Text;
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope managementScope = new ManagementScope(@"\\server\root\cimv2",connectionOptions);
managementScope.Options.EnablePrivileges = true;
managementScope.Connect(); // this line is executing fine.
eventWatcher = new ManagementEventWatcher(managementScope, new EventQuery("Select * From __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'  and TargetInstance.LogFile = 'Application'"));
eventWatcher.EventArrived += new EventArrivedEventHandler(Arrived);
eventWatcher.Scope.Options.EnablePrivileges = true;
eventWatcher.Start(); // Error occurs here

【问题讨论】:

【参考方案1】:

首先,请记住 Microsoft recommends the use of semi-synchronous operations(正如 Brian 建议的那样):

如果可以,我们建议您使用半同步操作 反而。性能影响小,半同步 操作允许相同的功能,但不需要反向 连接。

另见Setting Security on an Asynchronous Call in VBScript。

如果你还想使用 Async 操作,请参考以下文章:

How to troubleshoot WMI-related issues in Windows XP SP2 Connecting to WMI Remotely Starting with Windows Vista Securing a Remote WMI Connection Connecting Between Different Operating Systems

YMMV,但对我来说(客户端:Win7 x64 SP1 服务器:Windows Server 2008 Enterprise SP2 w/o 防火墙)E_ACCESSDENIED 异常的解决方案在第三篇文章中找到:

    点击开始,点击运行,输入DCOMCNFG,然后点击确定。 在组件服务对话框中,展开组件服务,展开计算机,然后右键单击我的电脑 strong>,然后点击属性。 在我的电脑属性对话框中,点击COM安全标签。 在访问权限下,点击编辑限制。 在访问权限对话框的组或用户名框中选择匿名登录名称。在用户权限下的允许列中,选择远程访问,然后点击确定

请注意,我在 客户端 中执行了上述操作。虽然这为我解决了 DCOM 权限问题,但随后我遇到了 WMI 访问被拒绝错误 (0x80041003)。原来这是由于第二篇文章中提到的注册表项:

如果远程连接不可用,则需要更新 CIMOM 设置 没有信任关系的计算机之间;否则,一个 异步连接将失败。不应修改此设置 适用于同一域或受信任域中的计算机。

需要修改以下注册表项以允许匿名 回调:HKLM\SOFTWARE\Microsoft\WBEM\CIMOM\AllowAnonymousCallback

如果 AllowAnonymousCallback 键设置为 0,则 WMI 服务 防止对客户端的匿名回调。如果该值设置为 1, WMI 服务允许对客户端进行匿名回调。

请注意,您需要在服务器中设置以上内容。一旦我这样做了,异步回调就起作用了。您可以尝试的其他事情是以管理员身份运行您的客户端并将ConnectionOptions.EnablePrivileges 设置为true。

有关疑难解答,请参阅:

WMI Troubleshooting Logging WMI Activity (Pre vista) Tracing WMI Activity (Starting with Vista)

最后,我建议你利用微软的 WMI 测试器 (%windir%\system32\wbem\wbemtest.exe)

【讨论】:

【参考方案2】:

尝试使用 WaitForNextEvent() 进行半同步监听:

    var managementScope = new ManagementScope(@"\\mysever\root\onguard"); 
    managementScope.Connect(); 

    var query = new EventQuery("select * from lnl_AccessEvent");
    var eventWatcher = new ManagementEventWatcher(managementScope, query);
    var wmiEvent = eventWatcher.WaitForNextEvent();
    Console.Out.WriteLine(wmiEvent.GetPropertyValue("Description"));

我们还发现 wbemtest.exe 很有用。单击 Notification Query... 按钮以侦听事件。您可以尝试各种连接方法(同步、异步或半同步)。连接到本地计算机时,所有连接方法都有效,但我们只能半同步远程工作。异步(您正在使用)更复杂(且安全性较低),因为服务器必须与客户端建立连接。

这里有一些关于安全和配置设置的有用信息: http://www.packettrap.com/network/Knowledge-Base/PacketTrap-MSP/WMI-Troubleshooting.aspx#_Toc239699682

【讨论】:

这显然应该是公认的答案。我花了很多时间试图修复这个错误,异步版本根本不适用于身份验证。谢谢你的回答。 @Pieter - 有可能,请参阅我的回答。不过,微软仍然推荐使用半同步方法。【参考方案3】:

我花了好几个小时才弄清楚这一点。以上都不适合我。

分析我的 IIS 服务器上的事件日志后,我发现每次调用 ManagementEventWatcher 对象的 Start 方法时,我都会在系统日志中收到以下错误事件:

机器默认权限设置不授予本地激活 具有 CLSID 的 COM 服务器应用程序的权限 49BD2028-1523-11D1-AD79-00C04FD8FDFF 和 APPID 49BD2028-1523-11D1-AD79-00C04FD8FDFF 给用户 IIS APPPOOL\DefaultAppPool SID (S-1-5-82-3006700770-424185619-1745488364-794895919-4004696415) 从 地址 LocalHost(使用 LRPC)。此安全权限可以是 使用组件服务管理工具进行修改。

注册表搜索显示错误中指定 APPID 的应用程序是

Microsoft WBEM 无担保公寓

要使异步回调起作用,您需要将此 COM 对象的本地激活权限授予 IIS APPPOOL\DefaultAppPool 用户,这听起来很容易,除了用户在安全性中没有显示为有效帐户这一事实数据库。这是因为它是在创建 IIS 应用程序池时自动构建的系统生成的用户帐户。

完成这项工作的过程如下:

    运行 mmc,添加组件服务管理单元 打开电脑->我的电脑->DCOM配置 向下滚动到“Microsoft WBEM Unsecured Apartment Object” 右键单击并选择属性 单击“安全”选项卡,然后在“启动和激活权限”部分下选择“自定义”选项并点击“编辑” 如果您的 IIS 服务器是域的一部分,请确保您在位置字段中指定了本地计算机,而不是域。 点击添加按钮并在用户框中输入“IIS APPPool\DefaultAppPool”并点击检查名称按钮。如果您不使用 DefaultAppPool,请替换您正在使用的应用程序池的名称。 您将看到一个有效的用户出现在框中,点击确定。 在列表中选择用户并选中本地启动和本地激活的允许框。 享受这样一个事实,即您将不再在 WMI 事件侦听器的异步回调中看到 E_ACCESSDENIED。

【讨论】:

以上是关于ManagementEventWatcher(WMI) 通知来自远程计算机的事件时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

using 子句调用 Dispose 失败?

从登录和注销中获取通知

C# 错误 1053 服务没有及时响应启动或控制请求

WM消息大全

WM消息大全

WM_PAINT与WM_ERASEBKGND