views:

480

answers:

4

I see that WMI is very powerful and seems to be able to return most properties of a PC hardware. I'd like to display the available parallel ports on any PC and find their I/O addresses - I know that normally this is done using a Kernel driver but this is a legacy need - dont ask! Presently we look in Device Manager and then have to type in the address displayed there. I'd like to use WMI to find out this information. There are an excellent set of WMI classes at 1 but I cannot see how to iterate.

Thanks.

+1  A: 

May be this will help you :

uses ComObj, ActiveX;

function TForm1.GetObject(const objectName: String): IDispatch;
var
  bindCtx: IBindCtx;
  moniker: IMoniker;
  chEaten: Integer;
begin
  OleCheck(CreateBindCtx(0, bindCtx));
  OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
  OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  objWMIService: OLEVariant;
  colItems, colItem: OLEVariant;
  oEnum : IEnumvariant;
  iValue, test : longword;
begin
  objWMIService := GetObject('winmgmts:\\YourPCname\root\CIMV2');
  colItems := objWMIService.ExecQuery('SELECT * FROM Win32_ParallelPort',,48);
  oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
  while oEnum.Next(1, colItem, iValue) = 0 do begin
     //You can get all the properties here 
     //for example colItem.Caption
     // properties of Win32_ParalelPort class : http://msdn.microsoft.com/en-us/library/aa394247%28VS.85%29.aspx
  end;
end;
SimaWB
+1  A: 

@Brian , you just use the Win32_parallelPort class to get the info .

check this code.

program GetWMI_ParallelPortInfo;

{$APPTYPE CONSOLE}

uses
  Windows,
  Classes,
  ActiveX,
  Variants,
  SysUtils,
  WbemScripting_TLB in '..\..\Documents\RAD Studio\5.0\Imports\WbemScripting_TLB.pas';

procedure  GetWMIParallelPortInfo;
var
  WMIServices  : ISWbemServices;
  WMILocator   : ISWbemLocator;
  Root         : ISWbemObjectSet;
  SWbemObject  : ISWbemObject;
  Item         : IEnumVariant;
  rgVar        : OleVariant;
  pCelFetched  : Cardinal;

begin
  WMILocator := CoSWbemLocator.Create();
  WMIServices := WMILocator.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);    //
  Root := WMIServices.ExecQuery('Select * From Win32_ParallelPort','WQL', 0, nil);
  Item :=  (Root._NewEnum) as IEnumVariant;
  while  (Item.Next(1, rgVar, pCelFetched) = S_OK) do
  begin
    SWbemObject := IUnknown(rgVar) as ISWBemObject;
    if (SWbemObject <> nil) then
    begin
      SWbemObject.Properties_;//Load the Properties to read 
      Writeln(SWbemObject.GetObjectText_(0));//The GetObjectText_ method of the SWbemObject  object returns a textual rendering of the object in MOF format
    end;
   end;
end;

begin
 try
    CoInitialize(nil);
    try
      GetWMIParallelPortInfo;
      Readln;
    finally
      CoUninitialize;
    end;
 except
    on E:Exception do
    Begin
        Writeln(E.Classname, ': ', E.Message);
        Readln;
    End;
  end;
end.

alt text

RRUZ
@RRUZ Thanks, the code gives me a start. How do I find the 'StartAddress' parameter please? Brian.
Brian Frost
@RRUZ: Thanks for the pointers - now solved.
Brian Frost
A: 

One must experiment to extract a complex information from WMI. I have tried to find the parallel port addresses on my PC and that is the report:

First of all I have quieried Win32_ParallelPort class to find all parallel ports. (using the same code as PRUZ in his post before): 'Select * From Win32_ParallelPort'. The result is (I have only one parallel port in my system):

instance of Win32_ParallelPort
{
    Availability = 3;
    Caption = "LPT1";
    ConfigManagerErrorCode = 0;
    ConfigManagerUserConfig = FALSE;
    CreationClassName = "Win32_ParallelPort";
    Description = "LPT1";
    DeviceID = "LPT1";
    Name = "LPT1";
    OSAutoDiscovered = TRUE;
    PNPDeviceID = "ACPI\\PNP0401\\4&25C6B52A&0";
    PowerManagementSupported = FALSE;
    ProtocolSupported = 17;
    SystemCreationClassName = "Win32_ComputerSystem";
    SystemName = "JUPITER";
};

Second, I have queried Win32_PNPAllocatedResource ('Select * From Win32_PnPAllocatedResource'). I have got a lot of information here, but I have selected only the 3 entries by PNPDeviceID = "ACPI\PNP0401\4&25C6B52A&0".

instance of Win32_PNPAllocatedResource
{
    Antecedent = "\\\\JUPITER\\root\\cimv2:Win32_PortResource.StartingAddress=\"888\"";
    Dependent = "\\\\JUPITER\\root\\cimv2:Win32_PnPEntity.DeviceID=\"ACPI\\\\PNP0401\\\\4&25C6B52A&0\"";
};


instance of Win32_PNPAllocatedResource
{
    Antecedent = "\\\\JUPITER\\root\\cimv2:Win32_PortResource.StartingAddress=\"1912\"";
    Dependent = "\\\\JUPITER\\root\\cimv2:Win32_PnPEntity.DeviceID=\"ACPI\\\\PNP0401\\\\4&25C6B52A&0\"";
};


instance of Win32_PNPAllocatedResource
{
    Antecedent = "\\\\JUPITER\\root\\cimv2:Win32_DMAChannel.DMAChannel=3";
    Dependent = "\\\\JUPITER\\root\\cimv2:Win32_PnPEntity.DeviceID=\"ACPI\\\\PNP0401\\\\4&25C6B52A&0\"";
};

The third entry is of no interest. The first two entries gives us two (decimal) starting addresses (888 and 1912)

Finally I have queiried Win32_PortResource ('Select * From Win32_PortResource') to find the ending addresses corresponding to the starting addresses 888 and 1912:

instance of Win32_PortResource
{
    Alias = FALSE;
    Caption = "0x00000378-0x0000037F";
    CreationClassName = "Win32_PortResource";
    CSCreationClassName = "Win32_ComputerSystem";
    CSName = "JUPITER";
    Description = "0x00000378-0x0000037F";
    EndingAddress = "895";
    Name = "0x00000378-0x0000037F";
    StartingAddress = "888";
    Status = "OK";
};


instance of Win32_PortResource
{
    Alias = FALSE;
    Caption = "0x00000778-0x0000077B";
    CreationClassName = "Win32_PortResource";
    CSCreationClassName = "Win32_ComputerSystem";
    CSName = "JUPITER";
    Description = "0x00000778-0x0000077B";
    EndingAddress = "1915";
    Name = "0x00000778-0x0000077B";
    StartingAddress = "1912";
    Status = "OK";
};

Updated I have used the same code as RRUZ, in GUI application (see below). The only thing you need to compile it is the WbemScripting_TLB.pas unit. The unit is generated by type library import wizard, you can read about the process in Delphi 2009 in my blog

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses WbemScripting_TLB, ActiveX;


{$R *.dfm}


procedure TForm1.Button4Click(Sender: TObject);
var
  WMIServices  : ISWbemServices;
  WMILocator   : ISWbemLocator;
  Root         : ISWbemObjectSet;
  SWbemObject  : ISWbemObject;
  Item         : IEnumVariant;
  rgVar        : OleVariant;
  pCelFetched  : Cardinal;

begin
  Memo1.Lines.Clear;
  WMILocator := CoSWbemLocator.Create();
  WMIServices := WMILocator.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);    //
  Root := WMIServices.ExecQuery('Select * From Win32_PnPAllocatedResource','WQL', 0, nil);
  Item :=  (Root._NewEnum) as IEnumVariant;
  while  (Item.Next(1, rgVar, pCelFetched) = S_OK) do
  begin
    SWbemObject := IUnknown(rgVar) as ISWBemObject;
    if (SWbemObject <> nil) then
    begin
      SWbemObject.Properties_;//Load the Properties to read
      Memo1.Lines.Add(SWbemObject.GetObjectText_(0));
    end;
  end;
end;

procedure TForm1.Button5Click(Sender: TObject);
var
  WMIServices  : ISWbemServices;
  WMILocator   : ISWbemLocator;
  Root         : ISWbemObjectSet;
  SWbemObject  : ISWbemObject;
  Item         : IEnumVariant;
  rgVar        : OleVariant;
  pCelFetched  : Cardinal;

begin
  Memo1.Lines.Clear;
  WMILocator := CoSWbemLocator.Create();
  WMIServices := WMILocator.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);    //
  Root := WMIServices.ExecQuery('Select * From Win32_PortResource','WQL', 0, nil);
  Item :=  (Root._NewEnum) as IEnumVariant;
  while  (Item.Next(1, rgVar, pCelFetched) = S_OK) do
  begin
    SWbemObject := IUnknown(rgVar) as ISWBemObject;
    if (SWbemObject <> nil) then
    begin
      SWbemObject.Properties_;//Load the Properties to read
      Memo1.Lines.Add(SWbemObject.GetObjectText_(0));
    end;
   end;
end;

procedure TForm1.Button6Click(Sender: TObject);
var
  WMIServices  : ISWbemServices;
  WMILocator   : ISWbemLocator;
  Root         : ISWbemObjectSet;
  SWbemObject  : ISWbemObject;
  Item         : IEnumVariant;
  rgVar        : OleVariant;
  pCelFetched  : Cardinal;

begin
  Memo1.Lines.Clear;
  WMILocator := CoSWbemLocator.Create();
  WMIServices := WMILocator.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);    //
  Root := WMIServices.ExecQuery('Select * From Win32_ParallelPort','WQL', 0, nil);
  Item :=  (Root._NewEnum) as IEnumVariant;
  while  (Item.Next(1, rgVar, pCelFetched) = S_OK) do
  begin
    SWbemObject := IUnknown(rgVar) as ISWBemObject;
    if (SWbemObject <> nil) then
    begin
      SWbemObject.Properties_;//Load the Properties to read
      Memo1.Lines.Add(SWbemObject.GetObjectText_(0));
    end;
   end;
end;

end.
Serg
This looks promising Serg - the addresses are my goal - any chance of some rough Delphi code? Thanks Brian.
Brian Frost
@Serg: Great - I'll experient. Thanks. Brian.
Brian Frost
@Serg: This works great, many thanks - exactly what I needed to get me started.
Brian Frost
+1  A: 

I do not understand what are the values you need.
If you need to know this:

alt text

I think you can find it in Win32_PortResource classes and Win32_portConnector

Can you confirm that this is so?
Make a test; Open a CMD windows and type:
> WMIC PORT List FULL

alt text

If this is the value that you are searching, you can develop a new component in GLibWMI (or say to me for help you) that retrieve this values.

Regards.

PD: Excuseme for the mistakes with english.

Neftalí
Yes! This is exactly what I would like. I do not understand how to show the information though, and a common problem is when there are two parallel ports, I need to know the information for both, not just the first. I hope I am not confusing. Your English is fine! Brian.
Brian Frost