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

前端之家收集整理的这篇文章主要介绍了delphi – 如何正确检索电池序列号?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在Delphi 7中,我正在开发一个实现一个对象的库,该对象封装了有关连接到系统的电池的信息.除了检索电池的序列号外,它运行良好.

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

  1. function TBattery.GetSerialNumber(hbat: THandle): boolean;
  2. var
  3. bqi: TBatteryQueryInformation;
  4. Serial: PWideChar;
  5. SerialSize,dwOut: DWORD;
  6. begin
  7. Result := False;
  8.  
  9. if hbat <> INVALID_HANDLE_VALUE then
  10. begin
  11. ZeroMemory(@bqi,SizeOf(bqi));
  12. dwOut := 0;
  13.  
  14. bqi.BatteryTag := FBatteryTag;
  15. bqi.InformationLevel := BatterySerialNumber;
  16.  
  17. SerialSize := 2048;
  18. GetMem(Serial,SerialSize);
  19. try
  20. ZeroMemory(Serial,SerialSize);
  21.  
  22. Result := DeviceIoControl(hbat,IOCTL_BATTERY_QUERY_INFORMATION,@bqi,SizeOf(bqi),Serial,SerialSize,@dwOut,nil);
  23.  
  24. if Result then
  25. FSerialNumber := Serial;
  26. finally
  27. FreeMem(Serial,SerialSize);
  28. end;
  29. end;
  30. end;

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

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

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

解决方法

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

所以替换你的代码

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

必须解决问题.

WinAPI的

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

  1. uses
  2. SetupApi,Windows,SysUtils;
  3.  
  4. type
  5.  
  6. BATTERY_QUERY_INFORMATION_LEVEL = (
  7. BatteryInformation,BatteryGranularityInformation,BatteryTemperature,BatteryEstimatedTime,BatteryDeviceName,BatteryManufactureDate,BatteryManufactureName,BatteryUniqueID,BatterySerialNumber);
  8. TBatteryQueryInformationLevel = BATTERY_QUERY_INFORMATION_LEVEL;
  9.  
  10. _BATTERY_QUERY_INFORMATION = record
  11. BatteryTag: ULONG;
  12. InformationLevel: BATTERY_QUERY_INFORMATION_LEVEL;
  13. AtRate: Longint;
  14. end;
  15. BATTERY_QUERY_INFORMATION = _BATTERY_QUERY_INFORMATION;
  16. PBATTERY_QUERY_INFORMATION = ^BATTERY_QUERY_INFORMATION;
  17. TBatteryQueryInformation = BATTERY_QUERY_INFORMATION;
  18.  
  19.  
  20. const
  21. GUID_DEVCLASS_BATTERY:TGUID='{72631E54-78A4-11D0-BCF7-00AA00B7B32A}';
  22. //DEFINE_GUID( GUID_DEVCLASS_BATTERY,0x72631E54,0x78A4,0x11D0,0xBC,0xF7,0x00,0xAA,0xB7,0xB3,0x2A );
  23. METHOD_BUFFERED = 0;
  24. FILE_DEVICE_BATTERY = $00000029;
  25. FILE_READ_ACCESS = $0001; // for files and pipes
  26.  
  27. IOCTL_BATTERY_QUERY_TAG =
  28. (FILE_DEVICE_BATTERY shl 16) or (FILE_READ_ACCESS shl 14) or ($10 shl 2) or (METHOD_BUFFERED);
  29. IOCTL_BATTERY_QUERY_INFORMATION =
  30. (FILE_DEVICE_BATTERY shl 16) or (FILE_READ_ACCESS shl 14) or ($11 shl 2) or (METHOD_BUFFERED);
  31.  
  32. function GetBatteryInfo(InformationLevel : BATTERY_QUERY_INFORMATION_LEVEL) : string;
  33. var
  34. cbrequired : DWORD;
  35. hdev : HDEVINFO;
  36. idev : Integer;
  37. did : TSPDeviceInterfaceData;
  38. pdidd : PSPDeviceInterfaceDetailData;
  39. hBattery : THandle;
  40. bqi : TBatteryQueryInformation;
  41. dwWait,dwOut : DWORD;
  42. lpOutBuffer: PWideChar;
  43. begin
  44. // enumerate the batteries
  45. hdev := SetupDiGetClassDevs(@GUID_DEVCLASS_BATTERY,nil,DIGCF_PRESENT OR DIGCF_DEVICEINTERFACE);
  46. if ( INVALID_HANDLE_VALUE <> THandle(hdev) ) then
  47. begin
  48. idev:=0;//first battery
  49. ZeroMemory(@did,SizeOf(did));
  50. did.cbSize := SizeOf(did);
  51. if (SetupDiEnumDeviceInterfaces(hdev,GUID_DEVCLASS_BATTERY,idev,did)) then
  52. begin
  53. try
  54. cbrequired := 0;
  55. SetupDiGetDeviceInterfaceDetail(hdev,@did,cbrequired,nil);
  56. if (ERROR_INSUFFICIENT_BUFFER= GetLastError()) then
  57. begin
  58. pdidd:=AllocMem(cbrequired);
  59. try
  60. pdidd.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
  61. if (SetupDiGetDeviceInterfaceDetail(hdev,pdidd,nil)) then
  62. begin
  63. hBattery :=CreateFile(pdidd.DevicePath,GENERIC_READ OR GENERIC_WRITE,FILE_SHARE_READ OR FILE_SHARE_WRITE,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  64. if (INVALID_HANDLE_VALUE <> hBattery) then
  65. begin
  66. try
  67. ZeroMemory(@bqi,SizeOf(bqi));
  68. // With the tag,you can query the battery info.
  69. dwWait := 0;
  70. if (DeviceIoControl(hBattery,IOCTL_BATTERY_QUERY_TAG,@dwWait,sizeof(dwWait),@bqi.BatteryTag,sizeof(bqi.BatteryTag),nil)) then
  71. begin
  72. lpOutBuffer:=AllocMem(MAX_PATH);
  73. try
  74. ZeroMemory(lpOutBuffer,MAX_PATH);
  75. bqi.InformationLevel:=InformationLevel;
  76. if DeviceIoControl(hBattery,SizeOf(BATTERY_QUERY_INFORMATION),lpOutBuffer,255,nil) then
  77. Result:= WideCharToString(lpOutBuffer);
  78. finally
  79. FreeMem(lpOutBuffer);
  80. end;
  81. end;
  82. finally
  83. CloseHandle(hBattery)
  84. end;
  85. end;
  86. end;
  87. finally
  88. FreeMem(pdidd);
  89. end;
  90. end;
  91. finally
  92. SetupDiDestroyDeviceInfoList(hdev);
  93. end;
  94. end;
  95. end;
  96. end;
  97.  
  98. begin
  99. try
  100. if not LoadsetupAPI then exit;
  101. Writeln(GetBatteryInfo(BatterySerialNumber));
  102. except
  103. on E: Exception do
  104. Writeln(E.ClassName,': ',E.Message);
  105. end;
  106. readln;
  107. end.

WMI

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

  1. {$APPTYPE CONSOLE}
  2.  
  3. uses
  4. SysUtils,ActiveX,ComObj,Variants;
  5.  
  6. // Battery Static Data
  7.  
  8. procedure GetBatteryStaticDataInfo;
  9. const
  10. WbemUser ='';
  11. WbemPassword ='';
  12. WbemComputer ='localhost';
  13. wbemFlagForwardOnly = $00000020;
  14. var
  15. FSWbemLocator : OLEVariant;
  16. FWMIService : OLEVariant;
  17. FWbemObjectSet: OLEVariant;
  18. FWbemObject : OLEVariant;
  19. oEnum : IEnumvariant;
  20. iValue : LongWord;
  21. begin;
  22. FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  23. FWMIService := FSWbemLocator.ConnectServer(WbemComputer,'root\WMI',WbemUser,WbemPassword);
  24. FWbemObjectSet:= FWMIService.ExecQuery('SELECT SerialNumber FROM BatteryStaticData','WQL',wbemFlagForwardOnly);
  25. oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  26. while oEnum.Next(1,FWbemObject,iValue) = 0 do
  27. begin
  28. Writeln(Format('SerialNumber %s',[String(FWbemObject.SerialNumber)]));// String
  29.  
  30. Writeln('');
  31. FWbemObject:=Unassigned;
  32. end;
  33. end;
  34.  
  35.  
  36. begin
  37. try
  38. CoInitialize(nil);
  39. try
  40. GetBatteryStaticDataInfo;
  41. finally
  42. CoUninitialize;
  43. end;
  44. except
  45. on E:EOleException do
  46. Writeln(Format('EOleException %s %x',[E.Message,E.ErrorCode]));
  47. on E:Exception do
  48. Writeln(E.Classname,':',E.Message);
  49. end;
  50. Writeln('Press Enter to exit');
  51. Readln;
  52. end.

猜你在找的Delphi相关文章