【发布时间】: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