【问题标题】:Delphi: intercept SWbemServices.ExecQuery errorDelphi:拦截 SWbemServices.ExecQuery 错误
【发布时间】:2017-01-01 00:40:59
【问题描述】:

我在 Delphi VCL 中实现了一个 WMI 接口,我设法让它工作,但我现在正试图让它更健壮一些。

我正在处理的代码部分是这样的:

var
    FWbemServices: ISWbemServices;
    WMIObject: ISWbemObjectSet;
    WMISQLQuery: String;
    FCount: Integer;
...
    FWbemServices := FWbemLocator.ConnectServer('', 'root\CIMV2', '', '', '', '', 0, nil);
    WMIObject := FWbemServices.ExecQuery(WMISQLQuery, 'WQL', wbemFlagReturnImmediately, nil);
...
    FCount := WMIObject.Count;
...

当 WMISQLQuery 包含有效的 WMI 查询时,它完全有效,例如:

SELECT * FROM Win32_BaseBoard

但如果查询错误,例如拼错类名,当尝试访问 WMIObject.Count 时,它会突然给我一个 EOleException“无效查询”,我无法通过用 try .. except 块来处理它.

我查看了this MSDN page,其中明确指出:

ExecQuery方法完成后,Err对象可以 包含以下列表中的错误代码之一。

wbemErrAccessDenied - 2147749891 (0x80041003)

当前用户没有查看结果集的权限。

wbemErrFailed - 2147749889 (0x80041001)

未指定的错误。

wbemErrInvalidParameter - 2147749896 (0x80041008)

指定的参数无效。

wbemErrInvalidQuery - 2147749911 (0x80041017)

查询语法无效。

wbemErrInvalidQueryType - 2147749912 (0x80041018)

不支持请求的查询语言。

wbemErrOutOfMemory - 2147749894 (0x80041006)

内存不足,无法完成操作。

事实上,我无法以任何方式访问 Err 对象。

当我在 VB 中使用 Err 对象时,我仍然记得它:

On Error Resume Next
...
DoSomething
If Err.Number <> 0 Then
...

我只是希望能够在 Delphi 中使用它。

有趣的事实是,在导入的 WMI TLB 中,我确实有这些常量可供使用。

更新,部分解决

也许我只是太累了(当时是 1 月 1 日凌晨 3 点 25 分),需要休息一下,看看整件事情的表现如何。我并不是说我解决了它,因为 我没有找到从 Delphi 访问 Err 对象的方法,但在这种特殊情况下,我能够处理异常。不幸的是,我无法辨别它们,因为该类始终是 EOleException 并且 Exception.Message 被翻译为系统语言,但至少我没有未处理的异常。

我在Dropbox上分享了一个小项目,它不包含二进制文件,只是需要编译的最少Delphi文件,你也可以在VirusTotal上查看。

此示例将测试一个好的和一个坏的 WMI 查询。

如果有人找到从 Err 对象获取信息的方法,我仍然会很感激。

【问题讨论】:

  • 您能否提供完整的源代码来重现该问题。对我来说,它在 ExecQuery 方法上失败并出现“无效类”异常
  • 如果没有 wbemFlagReturnImmediately 标志,它会在 ExecQuery 上引发异常,你需要它吗?
  • 响应 EugeneK 的两个 cmets:wbemFlagReturnImmediately 不会改变函数在我的情况下的行为方式,因为 它总是返回一个有效的指针。我提供了一个指向源的链接您可以测试代码,但正如我的更新中所述,这只会处理异常,而不是给我任何方法来找出导致它的错误。我仍然需要访问 Err 对象来确定发生了什么样的错误。

标签: vb.net delphi error-handling wmi msdn


【解决方案1】:

EOLEException 有 ErrorCode 属性,所以你可以使用这样的东西

except
  on E: EOLEException do
  begin
    if E.ErrorCode = HRESULT(wbemErrInvalidQuery) then
    begin
      // do something
    end;
  end;
end;

【讨论】:

  • 谢谢,这是正确的解决方案!没有检查 EOleException 的成员,通常 E.Message 和 E.ClassName 对我来说已经足够了,这确实限制了我的视野。再次感谢你,你让我开心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
相关资源
最近更新 更多