Python 使用Windwos API DevicePowerEnumDevices 返回总是0

Python Using Windwos API DevicePowerEnumDevices Returning is always 0

Python 使用Windwos API DevicePowerEnumDevices 返回总是0 我找不到原因 https://docs.microsoft.com/zh-TW/windows/win32/api/powrprof/nf-powrprof-devicepowerenumdevices

import ctypes
from ctypes import windll
from ctypes import sizeof
from ctypes import create_string_buffer
from ctypes import POINTER,byref
from ctypes import wintypes


PowrProf = windll.LoadLibrary('PowrProf.dll')
Kernel32 = windll.LoadLibrary('Kernel32.dll')

DevicePowerOpen = PowrProf.DevicePowerOpen()

QueryIndex = 0
QueryInterpretationFlags = 0x08000000
QueryFlags = 0x00000001|0x00000004

pReturnBuffer = create_string_buffer(b'[=12=]0'*32)
pBufferSize = byref(ctypes.c_uint64(32))
pReturnBuffer = Kernel32.LocalAlloc(0x0040, pBufferSize)


Return = PowrProf.DevicePowerEnumDevices(
                                        QueryIndex,
                                        QueryInterpretationFlags,
                                        QueryFlags,
                                        pReturnBuffer,
                                        pBufferSize,
                                        )
print("Return = ",Return )


DevicePowerClose = PowrProf.DevicePowerClose()

Kernel32.LocalFree(pReturnBuffer)

您的缓冲区太小。来自你的 linked documentation:

[out, optional] pReturnBuffer

Pointer to a buffer that receives the requested information.

[in, out] pBufferSize

The size, in bytes, of the return buffer.

Note If pReturnBuffer is NULL, pBufferSize will be filled with the size needed to return the data.

使用空 return 缓冲区调用 DevicePowerEnumDevicespBufferSize 将包含 returned 索引的缓冲区大小:

import ctypes as ct
from ctypes import wintypes as w

PowrProf = ct.WinDLL('PowrProf')

# Recommend always defining .argtypes and .restype for each function.
# It helps ctypes convert parameters from Python to C and detect errors.
PowrProf.DevicePowerOpen.argtypes = w.ULONG,
PowrProf.DevicePowerOpen.restype = w.BOOLEAN
PowrProf.DevicePowerEnumDevices.argtypes = w.ULONG,w.ULONG,w.ULONG,w.PBYTE,w.PULONG
PowrProf.DevicePowerEnumDevices.restype = w.BOOLEAN
PowrProf.DevicePowerClose.argtypes = ()
PowrProf.DevicePowerClose.restype = w.BOOLEAN

DEVICEPOWER_HARDWAREID = 0x80000000
PDCAP_D0_SUPPORTED = 0x00000001
PDCAP_D2_SUPPORTED = 0x00000004

print('open =',PowrProf.DevicePowerOpen(0))

QueryIndex = 0
QueryInterpretationFlags = DEVICEPOWER_HARDWAREID
QueryFlags = PDCAP_D0_SUPPORTED | PDCAP_D2_SUPPORTED

while True:
    size = w.ULONG()

    # call with None to get required size of returned buffer
    PowrProf.DevicePowerEnumDevices(QueryIndex,
                                    QueryInterpretationFlags,
                                    QueryFlags,
                                    None,
                                    ct.byref(size))

    #allocate the buffer
    buffer = (w.BYTE * size.value)()

    if not PowrProf.DevicePowerEnumDevices(QueryIndex,
                                        QueryInterpretationFlags,
                                        QueryFlags,
                                        buffer,
                                        ct.byref(size)):
        break

    # Returned buffer for DEVICEPOWER_HARDWAREID is a wide multi-string value,
    # each null-terminated and the end double null-terminated
    result = ct.cast(buffer,ct.POINTER(w.WCHAR))[:size.value // ct.sizeof(w.WCHAR)]
    print(result.rstrip('\x00').split('\x00'))
    QueryIndex += 1

print('close =',PowrProf.DevicePowerClose())

输出(截断):

open = 1
['PCI\VEN_11AB&DEV_4364&SUBSYS_81F81043&REV_12', 'PCI\VEN_11AB&DEV_4364&SUBSYS_81F81043', 'PCI\VEN_11AB&DEV_4364&CC_020000', 'PCI\VEN_11AB&DEV_4364&CC_0200']
['ACPI\VEN_PNP&DEV_0C01', 'ACPI\PNP0C01', '*PNP0C01']
 ...
['PCI\VEN_8086&DEV_3A3E&SUBSYS_82EA1043&REV_00', 'PCI\VEN_8086&DEV_3A3E&SUBSYS_82EA1043', 'PCI\VEN_8086&DEV_3A3E&CC_040300', 'PCI\VEN_8086&DEV_3A3E&CC_0403']
['ms_l2tpminiport']
close = 1