Delphi:拦截SWbemServices.ExecQuery错误

Delphi: intercept SWbemServices.ExecQuery error

我在 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

但如果查询错误,例如拼错 class 名称,当尝试访问 WMIObject.Count 时,它突然给我一个 EOleException "Invalid query",我无法处理用 try 包围它 .. 除了块。

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

After the completion of the ExecQuery method, the Err object can contain one of the error codes in the following list.

wbemErrAccessDenied - 2147749891 (0x80041003)

Current user does not have the permission to view the result set.

wbemErrFailed - 2147749889 (0x80041001)

Unspecified error.

wbemErrInvalidParameter - 2147749896 (0x80041008)

Invalid parameter was specified.

wbemErrInvalidQuery - 2147749911 (0x80041017)

Query syntax is not valid.

wbemErrInvalidQueryType - 2147749912 (0x80041018)

Requested query language is not supported.

wbemErrOutOfMemory - 2147749894 (0x80041006)

Not enough memory to complete the operation.

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

我还记得我在 VB 中使用它时的 Err 对象,例如:

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

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

有趣的是,在导入的 WMI TLB 中,我确实准备好了这些常量。

更新,部分解决

也许我只是太累了(那是 3:25AM 1 月 1 日),需要休息一下,看看整个过程如何。我并不是说我解决了它,因为 我没有找到从 Delphi 访问 Err 对象的方法,但在这种特殊情况下我能够处理异常.不幸的是我无法辨别它们,因为 class 总是 EOleException 并且 Exception.Message 被翻译成系统语言,但至少我没有未处理的异常。

我在 Dropbox, it does not contain binaries, just the minimum required Delphi files to be compiled, you can also check it on VirusTotal 上分享了一个小项目。

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

如果有人能找到从 Err 对象获取信息的方法,我将不胜感激。

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

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