DllCall to get idle time until computer sleeps Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
sn0skier
Posts: 7
Joined: 21 Dec 2016, 10:49

DllCall to get idle time until computer sleeps

21 Dec 2016, 11:46

Code: Select all

hModule := DllCall("LoadLibrary", "str", "PowrProf.dll") : Is this best practice?
DllCall("PowrProf\PowerGetActiveScheme", "Ptr", 0, "Ptr*", pguid)
; Saves Current Scheme GUID as pguid. Returns 9509584 which doesn't seem like it can possible be correct
DllCall("PowrProf\PowerReadACValue", "Ptr", 0, "Ptr", pguid, "Ptr", 238C9FA8-0AAD-41ED-83F4-97BE242C8F20, "Ptr", 29f6c1db-86da-48c5-9fdb-f2b67b1f44da, "Ptr", 0, "Ptr*", SleepTime)
; is supposed to look up the active scheme from above and tell me idle time untill sleep when plugged in.
; Once I get this figure out I don't think it'll be hard to get the same number for DC (battery)
MsgBox, %SleepTime% ; display the sleep time. Currently returns 0.
DllCall("FreeLibrary", "ptr", hModule) ; Is this best practice?
return
It's a disaster and I have no idea what I'm doing. What I'm trying to do is save a variable with the idle time in seconds until my computer sleeps. Even if this code was correct I think I would still have to convert a hex to an base 10 integer, but first, getting it to return the correct value in any format.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: DllCall to get idle time until computer sleeps  Topic is solved

21 Dec 2016, 13:08

Code: Select all

hModule := DllCall("LoadLibrary", "str", "PowrProf.dll")

hr := DllCall("PowrProf\PowerGetActiveScheme", "Ptr", 0, "Ptr*", pguid)
if (hr != 0)
    MsgBox, % "hr: " hr "`nLastError: " A_LastError
else
    MsgBox, % "GUID: " StringFromCLSID(pguid)

; BufferSize parameter receives the required buffer size.
hr := DllCall("PowrProf\PowerReadACValue"
    , "Ptr", 0                                                                              ; HKEY    RootPowerKey
    , "Ptr", pguid                                                                          ; GUID    *SchemeGuid
    , "Ptr", GUID(SubGroupOfPowerSettingsGuid, "{238C9FA8-0AAD-41ED-83F4-97BE242C8F20}")    ; GUID    *SubGroupOfPowerSettingsGuid
    , "Ptr", GUID(PowerSettingGuid,            "{29f6c1db-86da-48c5-9fdb-f2b67b1f44da}")    ; GUID    *PowerSettingGuid
    , "Ptr", 0                                                                              ; PULONG  Type
    , "Ptr", 0                                                                              ; LPBYTE  Buffer
    , "UInt*", BufferSize)                                                                  ; LPDWORD BufferSize
if (hr != 0)
    MsgBox, % "hr: " hr "`nLastError: " A_LastError "`nBufferSize: " BufferSize
else
    MsgBox, % "BufferSize: " BufferSize
    
VarSetCapacity(Buffer, BufferSize, 0)
hr := DllCall("PowrProf\PowerReadACValue"
    , "Ptr", 0                              ; HKEY    RootPowerKey
    , "Ptr", pguid                          ; GUID    *SchemeGuid
    , "Ptr", &SubGroupOfPowerSettingsGuid   ; GUID    *SubGroupOfPowerSettingsGuid
    , "Ptr", &PowerSettingGuid              ; GUID    *PowerSettingGuid
    , "Ptr", 0                              ; PULONG  Type
    , "Ptr", &Buffer                        ; LPBYTE  Buffer
    , "Ptr", &BufferSize)                   ; LPDWORD BufferSize
if (hr != 0)
    MsgBox, % "hr: " hr "`nLastError: " A_LastError "`nBufferSize: " BufferSize
else
    MsgBox, % "Buffer: " NumGet(Buffer, 0, "UInt")

DllCall("Kernel32\LocalFree", "Ptr", pguid, "Ptr")
DllCall("Kernel32\FreeLibrary", "Ptr", hModule)
return

GUID(ByRef GUID, sGUID)  ; Converts a string to a binary GUID and returns its address.
{   ; src = https://autohotkey.com/docs/commands/ComObjQuery.htm#ExIE
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

StringFromCLSID(rclsid)  ; Converts a binary GUID to a string.
{
    DllCall("ole32\StringFromCLSID", "Ptr", &rclsid, "Ptr*", lplpsz)
    s := StrGet(lplpsz, "UTF-16")
    DllCall("ole32\CoTaskMemFree", "Ptr", lplpsz)
    return s
}
Edit: For the second call of PowerReadACValue, I think , "UInt", &BufferSize) should be "Ptr" instead of "UInt". It seems to work either way though.
Last edited by kon on 22 Dec 2016, 00:16, edited 2 times in total.
sn0skier
Posts: 7
Joined: 21 Dec 2016, 10:49

Re: DllCall to get idle time until computer sleeps

21 Dec 2016, 13:12

Are you a Wizard? Seriously though, tested it and it seems to work. I'm going to look at it more to see if I can understand how and where I went wrong, thanks for the help!
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: DllCall to get idle time until computer sleeps

24 Dec 2016, 13:54

I wanted to add that you can get the type in the same way you get the buffer size. Which would allow you to write a function wrapper that handles various types (like in the incomplete example below).

And, no, I am not a wizard. I'm not even particularly knowledgeable about this and my code is not guaranteed to be error free. In fact there was an error in how I used the StringFromCLSID function above. &rclsid should have been rclsid because pguid already contains the address of a GUID it doesn't need to be dereferenced. As a result, the function was returning the wrong GUID string.

Code: Select all

hModule := DllCall("Kernel32\LoadLibrary", "str", "PowrProf.dll")
DllCall("PowrProf\PowerGetActiveScheme", "Ptr", 0, "Ptr*", pguid)
MsgBox, % "GUID: " StringFromCLSID(pguid) "`n"
    . "Seconds until sleep: " PowerReadACValue(pguid, GUID(SubGroupOfPowerSettingsGuid, "{238C9FA8-0AAD-41ED-83F4-97BE242C8F20}")
                                                    , GUID(PowerSettingGuid,            "{29f6c1db-86da-48c5-9fdb-f2b67b1f44da}"))
DllCall("Kernel32\LocalFree", "Ptr", pguid, "Ptr")
DllCall("Kernel32\FreeLibrary", "Ptr", hModule)
return

PowerReadACValue(pSchemeGuid, pSubGroupOfPowerSettingsGuid, pPowerSettingGuid) {
    hr := DllCall("PowrProf\PowerReadACValue"
        , "Ptr",    0                               ; HKEY    RootPowerKey
        , "Ptr",    pSchemeGuid                     ; GUID    *SchemeGuid
        , "Ptr",    pSubGroupOfPowerSettingsGuid    ; GUID    *SubGroupOfPowerSettingsGuid
        , "Ptr",    pPowerSettingGuid               ; GUID    *PowerSettingGuid
        , "Ptr",    0                               ; PULONG  Type
        , "Ptr",    0                               ; LPBYTE  Buffer
        , "UInt*",  BufferSize)                     ; LPDWORD BufferSize  ; BufferSize parameter receives the required buffer size.
    if (hr != 0)  ; Replace with appropriate error handling.
        MsgBox, % "hr: " hr "`nLastError: " A_LastError "`nBufferSize: " BufferSize
    VarSetCapacity(Buffer, BufferSize, 0)
    hr := DllCall("PowrProf\PowerReadACValue"
        , "Ptr",    0                               ; HKEY    RootPowerKey
        , "Ptr",    pSchemeGuid                     ; GUID    *SchemeGuid
        , "Ptr",    pSubGroupOfPowerSettingsGuid    ; GUID    *SubGroupOfPowerSettingsGuid
        , "Ptr",    pPowerSettingGuid               ; GUID    *PowerSettingGuid
        , "UInt*",  Type                            ; PULONG  Type  ; Type parameter receives the type of data retrieved.
        , "Ptr",    &Buffer                         ; LPBYTE  Buffer
        , "Ptr",    &BufferSize)                    ; LPDWORD BufferSize
    if (hr != 0)  ; Replace with appropriate error handling.
        MsgBox, % "hr: " hr "`nLastError: " A_LastError "`nBufferSize: " BufferSize
    else if (Type = 4)  ; REG_DWORD := 4
        return NumGet(Buffer, 0, "UInt")
    ; else if (Type = ...   ; Handle other types here
    else
        MsgBox, % "Type: " Type
    return
}

GUID(ByRef GUID, sGUID)  ; Converts a string to a binary GUID and returns its address.
{ ; source = https://autohotkey.com/docs/commands/ComObjQuery.htm#ExIE
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

StringFromCLSID(rclsid)  ; Converts a binary GUID to a string. rclsid is the address of the GUID.
{
    DllCall("ole32\StringFromCLSID", "Ptr", rclsid, "Ptr*", lplpsz)
    s := StrGet(lplpsz, "UTF-16")
    DllCall("ole32\CoTaskMemFree", "Ptr", lplpsz)
    return s
}

Return to “Ask for Help”

Who is online

Users browsing this forum: Descolada, felix_liter and 48 guests