Search code examples
pythonwindowspywin32

GetLastInputInfo and GetTickCount are not consistent with each other


I am trying to work out how long, approximately, the current user has been idle (e.g. like this question), from Python on a Windows machine.

To do that, I figure I need to compare the result of GetLastInputInfo with the result of GetTickCount. The results should be in milliseconds.

(I am expecting roll-over problems every 49.7 days, but I will solve that later.)

My code is straightforward:

import win32api

last_active = win32api.GetLastInputInfo()
now = win32api.GetTickCount()
elapsed_milliseconds = (now - last_active)

print(last_active, now, elapsed_milliseconds)

I expect to get two similar large numbers, and a difference of a few hundred milliseconds.

Instead, I get results like:

3978299058 -316668238 -4294967296

and

3978316717 -316650501 -4294967218

Between runs, they are both changing by roughly the same amount, but there is a large constant offset between them that I am not expecting.

What am I missing?


Solution

  • Looking at the numbers more closely, this is a signed/unsigned mismatch.

    3978299058 = 0xED2006B2

    -316668238 (in two's complement) = 0xED2006B2

    3978316717 = 0xED204BAD

    -316650501 (in two's complement) = 0xED204BFB

    So the times are consistent, it's just that win32.GetTickCount is interpreting the tick count as a signed 32-bit integer whereas win32.GetLastInputInfo is interpreting it as unsigned.

    (Specifically, GetLastInputInfo is using PyLong_FromUnsignedLong whereas GetTickCount casts the DWORD to a long and then calls Py_BuildValue. You might want to consider filing a bug, since the tick count should be an unsigned value.)