在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,'root\WMI',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.
原文地址:https://www.jb51.cc/delphi/102015.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。