如何使用Delphi和WMI查找可用的并行端口及其I/O地址

5
我看到WMI非常强大,似乎可以返回PC硬件的大多数属性。我想显示任何PC上可用的并口,并找到它们的I/O地址 - 我知道通常使用内核驱动程序来完成这项工作,但这是一个传统需求 - 不要问为什么!目前我们在设备管理器中查找,然后必须键入显示的地址。我想使用WMI查找此信息。 在1有一组出色的WMI类,但我不知道如何迭代。 谢谢。
4个回答

2

从WMI中提取复杂信息需要进行实验。我尝试在我的电脑上查找并报告了并口地址:

首先,我查询Win32_ParallelPort类以查找所有并口(使用与PRUZ在其帖子中相同的代码):'Select * From Win32_ParallelPort'。结果是(我系统中只有一个并口):

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";
};

其次,我查询了Win32_PNPAllocatedResource(“Select * From Win32_PnPAllocatedResource”)。这里有很多信息,但我只选择了PNPDeviceID =“ACPI \ PNP0401 \ 4& 25C6B52A& 0”的3个条目。

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\"";
};

第三个条目没有意义。前两个条目给我们两个(十进制)起始地址(888和1912)

最后,我查询了Win32_PortResource('Select * From Win32_PortResource'),以找到对应于起始地址888和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";
};

更新

我在GUI应用程序中使用了与RRUZ相同的代码(如下所示)。您需要编译的唯一内容是WbemScripting_TLB.pas单元。该单元由类型库导入向导生成,您可以在我的博客中了解有关该过程的信息。

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 - 地址是我的目标 - 有没有一些粗略的 Delphi 代码的机会?谢谢 Brian。 - Brian Frost
@Serg: 太好了 - 我会试试看。谢谢。Brian. - Brian Frost
@Serg:这个很好用,非常感谢——正是我需要的来帮助我入门。 - Brian Frost

1

也许这会对你有所帮助:

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;

1
@Brian,你只需要使用Win32_parallelPort类来获取信息。
检查一下这段代码。
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 谢谢,这段代码给了我一个起点。请问我如何找到“StartAddress”参数? Brian。 - Brian Frost

1

我不明白您需要哪些值。
如果您需要知道这个:

alt text http://img682.imageshack.us/img682/2382/imagen333.png

我认为您可以在Win32_PortResource类和Win32_portConnector中找到它。

您能确认一下吗?
进行一个测试;打开CMD窗口并输入:
> WMIC PORT List FULL

alt text http://img215.imageshack.us/img215/1696/imagen332.png

如果这就是您要查找的值,您可以开发一个GLibWMI中的新组件(或者让我帮助您)来检索这些值。

问候。

注:请原谅我的英语错误。


是的!这正是我想要的。但我不明白如何显示信息,而且常见的问题是当有两个并行端口时,我需要知道两个端口的信息,而不仅仅是第一个。希望我没有让你困惑。你的英语很好!Brian。 - Brian Frost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接