2

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?

Community
  • 1
  • 1
Oddthinking
  • 24,359
  • 19
  • 83
  • 121

2 Answers2

2

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.)

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • I understand the theory, but inspecting the pywin32 code (win32apimodule.cpp:1671) it says "return PyLong_FromUnsignedLong(lii.dwTime);" which looks right. – Oddthinking Mar 31 '16 at 08:30
  • Yep, I should have looked at the actual numbers more closely. The problem is simply that one value is being returned as unsigned and the other as signed. – Harry Johnston Mar 31 '16 at 21:01
  • I have filed a [bug report](https://sourceforge.net/p/pywin32/bugs/718/). Thanks. – Oddthinking Apr 02 '16 at 02:51
0

ONce again, posting to Stack Overflow is the quickest way to find the answer to my own problem.

It is a roll-over problem.

The two values are very similar when they are mod 232.

GetTickCount64 would be a better call, but it is not included in win32API.

Oddthinking
  • 24,359
  • 19
  • 83
  • 121
  • 1
    I don't think using GetTickCount64 would help, since according to the documentation, GetLastInputInfo returns only a 32-bit tick count. – Harry Johnston Mar 31 '16 at 05:52