WMI in Delphi: How to enumerate serial ports and everything in Windows

Yesterday I was experimenting with WMI (Windows Management Instrumentation) using Delphi 2009.  As you know, WMI maintaines a huge repository containing … well, containing almost any piece of information available in Windows. At first glance it seems impossible to find what you need in such a repository, but actually the WMI structure is very simple and logical. Usually all you have to do is:

  1. Connect to the WMI service
  2. Obtain a collection of WMI objects by name
  3. Enumerate the collection.

The simplest tool to explore WMI is VBScript. You must have Windows Scripting Host installed, but nowadays it seems to be installed on every Windows system. A VBScript can be executed by doubleclicking on a *.vbs file or from the command-line:

  • cscript myscript.vbs

Let us start with serial port enumeration using VBScript:

strComputer = "."

Set objWMIService = GetObject( _
  "winmgmts:\\" & strComputer & "\root\cimv2")

Set colSerialPorts = _
  objWMIService.InstancesOf("Win32_SerialPort")

For Each SerPort In colSerialPorts
Wscript.Echo _
  "Name: " & SerPort.DeviceID & vbCrLf
Next

The first line of code defines local computer (“.”). I found that the empty string also works fine. Next you connect to WMI service, obtain the collection of serial ports (“Win32_SerialPort”) and enumerate the collection. That is all.

A little more work is required to do the same in Delphi. First of all you must import a type library. Click Component/Import Component from IDE main menu (I am using Delphi 2009). You will see the dialog with “Import Type Library radiobutton selected:

Import Component Dialog

Click “Next” and select “Microsoft WMI Scripting V1.2 Library” from the list of registered type libraries (library version may be different on your system):

Select WMI Library

Click “Next” and “Finish” to end the wizard.
A result of the process is the file “WbemScripting_TLB.pas” that must be added to a Delphi project. We also need ActiveX unit, so normally the “uses” clause of a unit that uses WMI looks like

    uses WbemScripting_TLB, ActiveX;

We can enumerate the available Windows resources using the following scheme:

  1. Connect to the WMI service
  2. Obtain a collection of WMI objects by name
  3. Enumerate the collection
  4. For each object in the collection obtain a collection of object’s properties
  5. Obtain a property by name.

The serial port enumeration example in Delphi:

uses WbemScripting_TLB, ActiveX;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  Locator:  ISWbemLocator;
  Services: ISWbemServices;
  ObjSet:   ISWbemObjectSet;
  SObject:  ISWbemObject;
  PropSet:  ISWbemPropertySet;
  SProp:    ISWbemProperty;
  sValue:   String;
  Enum:     IEnumVariant;
  Value:    Cardinal;
  TempObj:  OleVariant;

begin
  Memo1.Lines.Clear;
  Locator:= CoSWbemLocator.Create;
  Services:=  Locator.ConnectServer('.', 'root\cimv2', '', '', '','', 0, nil);
  ObjSet:= Services.InstancesOf('Win32_SerialPort', wbemFlagReturnWhenComplete, nil);
  Enum:= (ObjSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, tempObj, Value) = S_OK) do begin
    SObject:= IUnknown(tempObj) as SWBemObject;
    PropSet := SObject.Properties_;
    SProp:= PropSet.Item('DeviceID',0);
    sValue:= SProp.Get_Value;
    Memo1.Lines.Add(sValue);
  end;
end;

Now we can enumerate any Windows resource available in WMI repository by sligtly modifying the above code. The only question is where to find the names of WMI collections such as ‘Win32_SerialPort’ or property names like ‘DeviceID’? As usual everything about WMI can be found on MSDN. Delphi help also includes WMI SDK:

ms-help://embarcadero.rs2009/WMISDK/wmi/wmi_start_page.htm

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s