Delphi: intercept SWbemServices.ExecQuery error

422 views Asked by At

I'm implementing a WMI interface in Delphi VCL, I managed to have it working, but I'm now trying to make it a little more robust.

The portion of code I'm working on is this:

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;
...

It completely works when WMISQLQuery contains a valid WMI query like:

SELECT * FROM Win32_BaseBoard

But if the query is wrong, for example misspelling the class name, when trying to access WMIObject.Count it suddently gives me an EOleException "Invalid query" which I can't handle by surrounding it with a try .. except block.

I checked this MSDN page which clearly states:

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.

The fact is, I'm not able to access the Err object in any way.

I still remember the Err object when I was using it in VB like:

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

I just would like to be able to use it in Delphi.

The fun fact is that in the imported WMI TLB I do have those constants ready for use.

UPDATE, partially solved

Maybe I was just to tired (it was 3:25AM January, 1st) and needed some rest to see how the whole thing acted. I'm not saying I solved it, since I did not find the way to access the Err object from Delphi, but in this partitular case I was able to handle the exception. Unfortunately I cannot discern them since the class is always EOleException and the Exception.Message is translated to system language, but at least I don't have an unhandled exception.

I've shared a small project on Dropbox, it does not contain binaries, just the minimum required Delphi files to be compiled, you can also check it on VirusTotal.

This example will test a good and a bad WMI query.

I still would appreciate if someone finds a way to get information from the Err object.

1

There are 1 answers

1
EugeneK On BEST ANSWER

EOLEException has ErrorCode property, so you can use something like this

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