加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 如何正确检索电池序列号?

发布时间:2020-12-15 04:12:17 所属栏目:大数据 来源:网络整理
导读:在Delphi 7中,我正在开发一个实现一个对象的库,该对象封装了有关连接到系统的电池的信息.除了检索电池的序列号外,它运行良好. 我用于此次调用的代码如下: function TBattery.GetSerialNumber(hbat: THandle): boolean;var bqi: TBatteryQueryInformation; S
在Delphi 7中,我正在开发一个实现一个对象的库,该对象封装了有关连接到系统的电池的信息.除了检索电池的序列号外,它运行良好.

我用于此次调用的代码如下:

function TBattery.GetSerialNumber(hbat: THandle): boolean;
var
  bqi:          TBatteryQueryInformation;
  Serial:       PWideChar;
  SerialSize,dwOut:        DWORD;
begin
  Result := False;

  if hbat <> INVALID_HANDLE_VALUE then
  begin
    ZeroMemory(@bqi,SizeOf(bqi));
    dwOut := 0;

    bqi.BatteryTag := FBatteryTag;
    bqi.InformationLevel := BatterySerialNumber;

    SerialSize := 2048;
    GetMem(Serial,SerialSize);
    try
      ZeroMemory(Serial,SerialSize);

      Result := DeviceIoControl(hbat,IOCTL_BATTERY_QUERY_INFORMATION,@bqi,SizeOf(bqi),Serial,SerialSize,@dwOut,nil);

      if Result then
        FSerialNumber := Serial;
    finally
      FreeMem(Serial,SerialSize);
    end;
  end;
end;

不幸的是,DeviceIoControl()总是返回False,如果我之后检查GetLastError(),那么它返回错误87,“参数不正确”.

这没有多大意义,因为如果我只是简单地将InformationLevel从BatterySerialNumber更改为BatteryUniqueID,那么代码的效果非常好.另外,我在GetSerialNumber之前的代码中的其他调用中使用了电池的句柄(hbat)并且它们都工作正常,并且在此之后我也可以调用其他调用,所以这不是问题.

有任何想法吗?我真的很茫然.

解决方法

这个问题似乎与dwOut变量有关,它以@dwOut的形式传递,这个变量代表 DeviceIoControl的var lpBytesReturned参数,定义为
function DeviceIoControl(hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer;
  nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD;
  var lpBytesReturned: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;

所以替换你的代码

Result := DeviceIoControl(hbat,dwOut,nil);

必须解决问题.

WinAPI的

另请查看此msdn条目Enumerating Battery Devices中转换为delphi的代码,它可以帮助您检测代码的任何其他问题.

uses
  SetupApi,Windows,SysUtils;

type

  BATTERY_QUERY_INFORMATION_LEVEL = (
    BatteryInformation,BatteryGranularityInformation,BatteryTemperature,BatteryEstimatedTime,BatteryDeviceName,BatteryManufactureDate,BatteryManufactureName,BatteryUniqueID,BatterySerialNumber);
  TBatteryQueryInformationLevel = BATTERY_QUERY_INFORMATION_LEVEL;

  _BATTERY_QUERY_INFORMATION = record
    BatteryTag: ULONG;
    InformationLevel: BATTERY_QUERY_INFORMATION_LEVEL;
    AtRate: Longint;
  end;
  BATTERY_QUERY_INFORMATION = _BATTERY_QUERY_INFORMATION;
  PBATTERY_QUERY_INFORMATION = ^BATTERY_QUERY_INFORMATION;
  TBatteryQueryInformation = BATTERY_QUERY_INFORMATION;


const
  GUID_DEVCLASS_BATTERY:TGUID='{72631E54-78A4-11D0-BCF7-00AA00B7B32A}';
  //DEFINE_GUID( GUID_DEVCLASS_BATTERY,0x72631E54,0x78A4,0x11D0,0xBC,0xF7,0x00,0xAA,0xB7,0xB3,0x2A );
  METHOD_BUFFERED     = 0;
  FILE_DEVICE_BATTERY = $00000029;
  FILE_READ_ACCESS    = $0001;    // for files and pipes

  IOCTL_BATTERY_QUERY_TAG =
    (FILE_DEVICE_BATTERY shl 16) or (FILE_READ_ACCESS shl 14) or ($10 shl 2) or (METHOD_BUFFERED);
  IOCTL_BATTERY_QUERY_INFORMATION =
    (FILE_DEVICE_BATTERY shl 16) or (FILE_READ_ACCESS shl 14) or ($11 shl 2) or (METHOD_BUFFERED);

function GetBatteryInfo(InformationLevel : BATTERY_QUERY_INFORMATION_LEVEL) : string;
var
   cbRequired : DWORD;
   hdev     : HDEVINFO;
   idev     : Integer;
   did      : TSPDeviceInterfaceData;
   pdidd    : PSPDeviceInterfaceDetailData;
   hBattery : THandle;
   bqi      : TBatteryQueryInformation;
   dwWait,dwOut : DWORD;
   lpOutBuffer: PWideChar;
begin
  // enumerate the batteries
  hdev :=  SetupDiGetClassDevs(@GUID_DEVCLASS_BATTERY,nil,DIGCF_PRESENT OR DIGCF_DEVICEINTERFACE);
  if ( INVALID_HANDLE_VALUE <>  THandle(hdev) ) then
  begin
      idev:=0;//first battery
      ZeroMemory(@did,SizeOf(did));
      did.cbSize := SizeOf(did);
      if (SetupDiEnumDeviceInterfaces(hdev,GUID_DEVCLASS_BATTERY,idev,did)) then
      begin
        try
          cbRequired := 0;
          SetupDiGetDeviceInterfaceDetail(hdev,@did,cbRequired,nil);
         if (ERROR_INSUFFICIENT_BUFFER= GetLastError()) then
         begin
            pdidd:=AllocMem(cbRequired);
            try
              pdidd.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
              if (SetupDiGetDeviceInterfaceDetail(hdev,pdidd,nil)) then
              begin
                 hBattery :=CreateFile(pdidd.DevicePath,GENERIC_READ OR GENERIC_WRITE,FILE_SHARE_READ OR FILE_SHARE_WRITE,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
                 if (INVALID_HANDLE_VALUE <> hBattery) then
                 begin
                  try
                    ZeroMemory(@bqi,SizeOf(bqi));
                     // With the tag,you can query the battery info.
                    dwWait := 0;
                      if (DeviceIoControl(hBattery,IOCTL_BATTERY_QUERY_TAG,@dwWait,sizeof(dwWait),@bqi.BatteryTag,sizeof(bqi.BatteryTag),nil)) then
                      begin
                        lpOutBuffer:=AllocMem(MAX_PATH);
                        try
                          ZeroMemory(lpOutBuffer,MAX_PATH);
                          bqi.InformationLevel:=InformationLevel;
                          if DeviceIoControl(hBattery,SizeOf(BATTERY_QUERY_INFORMATION),lpOutBuffer,255,nil) then
                            Result:= WideCharToString(lpOutBuffer);
                        finally
                          FreeMem(lpOutBuffer);
                        end;
                      end;
                  finally
                    CloseHandle(hBattery)
                  end;
                 end;
              end;
            finally
              FreeMem(pdidd);
            end;
         end;
        finally
          SetupDiDestroyDeviceInfoList(hdev);
        end;
      end;
  end;
end;

begin
  try
    if not LoadsetupAPI then exit;
     Writeln(GetBatteryInfo(BatterySerialNumber));
  except
    on E: Exception do
      Writeln(E.ClassName,': ',E.Message);
  end;
  readln;
end.

WMI

最后请注意,您可以使用WMI检索相同的信息,在本例中使用BatteryStaticData WMI类

{$APPTYPE CONSOLE}

    uses
      SysUtils,ActiveX,ComObj,Variants;

    // Battery Static Data

    procedure  GetBatteryStaticDataInfo;
    const
      WbemUser            ='';
      WbemPassword        ='';
      WbemComputer        ='localhost';
      wbemFlagForwardOnly = $00000020;
    var
      FSWbemLocator : OLEVariant;
      FWMIService   : OLEVariant;
      FWbemObjectSet: OLEVariant;
      FWbemObject   : OLEVariant;
      oEnum         : IEnumvariant;
      iValue        : LongWord;
    begin;
      FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
      FWMIService   := FSWbemLocator.ConnectServer(WbemComputer,'rootWMI',WbemUser,WbemPassword);
      FWbemObjectSet:= FWMIService.ExecQuery('SELECT SerialNumber FROM BatteryStaticData','WQL',wbemFlagForwardOnly);
      oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
      while oEnum.Next(1,FWbemObject,iValue) = 0 do
      begin
        Writeln(Format('SerialNumber    %s',[String(FWbemObject.SerialNumber)]));// String

        Writeln('');
        FWbemObject:=Unassigned;
      end;
    end;


    begin
     try
        CoInitialize(nil);
        try
          GetBatteryStaticDataInfo;
        finally
          CoUninitialize;
        end;
     except
        on E:EOleException do
            Writeln(Format('EOleException %s %x',[E.Message,E.ErrorCode])); 
        on E:Exception do
            Writeln(E.Classname,':',E.Message);
     end;
     Writeln('Press Enter to exit');
     Readln;      
    end.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读