Here my code:
from ctypes import byref, c_uint, c_ulong, sizeof, Structure, windll
import ctypes
import random
import sys
import time
import win32api
class LASTINPUTINFO(Structure):
"""Мы импортировали необходимые модули и создали структуру LASTINPUTINFO
для хранения временной метки (в миллисекундах), обозначающей момент
обнаружения последнего события ввода в системе. """
fields_ = [
('cbSize', ctypes.c_uint),
('dwTime', ctypes.c_ulong)
]
def get_last_input():
"""Дальше создаем функцию get_last_input, чтобы, собственно, определить этот момент."""
struct_lastinputinfo = LASTINPUTINFO()
# Обратите
# внимание на то, что прежде чем выполнять вызов, переменную cbSize
# нужно инициализировать с использованием размера структуры.
struct_lastinputinfo.cbSize = sizeof(LASTINPUTINFO) #
# Затем мы
# вызываем функцию GetLastInputInfo, которая присваивает полю struct_
# lastinputinfo.dwTime временную метку.
windll.user32.GetLastInputInfo(byref(struct_lastinputinfo))
# Следующий шаг состоит в определении того,
# как долго проработала система. Для этого применяется вызов
# функции GetTickCount .
run_time = windll.kernel32.GetTickCount() #
# Переменная elapsed должна быть равна разности
# между временем работы системы и временем последнего ввода.
elapsed = run_time - struct_lastinputinfo.dwTime
print(f"[*] It's been {elapsed} milliseconds since the last event.")
return elapsed
# Небольшой
# фрагмент кода, размещенный в конце , позволяет выполнить простую проверку
while True: #
get_last_input()
time.sleep(1)
But I get this error:
Traceback (most recent call last): File "C:\Users\user\PycharmProjects\sandbox_detected\sandbox_detect.py", line 49, in get_last_input() File "C:\Users\user\PycharmProjects\sandbox_detected\sandbox_detect.py", line 41, in get_last_input elapsed = run_time - struct_lastinputinfo.dwTime AttributeError: 'LASTINPUTINFO' object has no attribute 'dwTime'
Help me please.
UPD:
@MegaEmailman Thank you, the code now does not throw exceptions, but it is not clear why it does not work correctly and displays only this:
[*] It's been 0 milliseconds since the last event.
[*] It's been 0 milliseconds since the last event.
[*] It's been 0 milliseconds since the last event.
[*] It's been 0 milliseconds since the last event.
[*] It's been 0 milliseconds since the last event.
[*] It's been 0 milliseconds since the last event.
There are a bunch of critical errors in your code (besides the wrong indentation - which I consider a formatting issue):
According to [Python.Docs]: ctypes - Structures and unions (emphasis is mine):
Structures and unions must derive from the Structure and Union base classes which are defined in the ctypes module. Each subclass must define a _fields_ attribute. _fields_ must be a list of 2-tuples, containing a field name and a field type.
So, it's _fields_ (surrounded by UnderScores)
Always define argtypes and restype for the functions you call via CTypes. Check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for more details
Not critical, but when working with WinAPI, use the WinTypes module which defines some types (which are practically aliases)
I modified your code with some improvements:
Moved the cbSize member set in the initializer, so it is no longer necessary every time the class gets instantiated
Exit when Esc is pressed
code00.py:
#!/usr/bin/env python
import ctypes as ct
import msvcrt
import sys
import time
from ctypes import wintypes as wt
class LASTINPUTINFO(ct.Structure):
_fields_ = (
("cbSize", wt.UINT),
("dwTime", wt.DWORD),
)
def __init__(self, dwTime=0):
super().__init__(ct.sizeof(self.__class__), dwTime)
PLASTINPUTINFO = ct.POINTER(LASTINPUTINFO)
kernel32 = ct.WinDLL("Kernel32")
user32 = ct.WinDLL("User32")
GetTickCount = kernel32.GetTickCount
GetTickCount.argtypes = ()
GetTickCount.restype = wt.DWORD
GetLastInputInfo = user32.GetLastInputInfo
GetLastInputInfo.argtypes = (PLASTINPUTINFO,)
GetLastInputInfo.restype = wt.BOOL
def get_last_input():
lii = LASTINPUTINFO()
GetLastInputInfo(ct.byref(lii))
run_time = GetTickCount()
print("\nLast input time: {:d}\nTick count: {:d}\nElapsed: {:d}".format(lii.dwTime, run_time, run_time - lii.dwTime))
def main(*argv):
while True:
get_last_input()
time.sleep(1)
if msvcrt.kbhit():
if ord(msvcrt.getch()) == 0x1B:
break
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output (run the program while moving mouse and pressing keys):
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q072887838]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Last input time: 392676796 Tick count: 392676921 Elapsed: 125 Last input time: 392676921 Tick count: 392677937 Elapsed: 1016 Last input time: 392676921 Tick count: 392678953 Elapsed: 2032 Last input time: 392676921 Tick count: 392679968 Elapsed: 3047 Last input time: 392676921 Tick count: 392680968 Elapsed: 4047 Last input time: 392681421 Tick count: 392681984 Elapsed: 563 Last input time: 392682812 Tick count: 392682984 Elapsed: 172 Last input time: 392683937 Tick count: 392684000 Elapsed: 63 Last input time: 392684078 Tick count: 392685000 Elapsed: 922 Last input time: 392685687 Tick count: 392686015 Elapsed: 328 Last input time: 392686828 Tick count: 392687031 Elapsed: 203 Last input time: 392688046 Tick count: 392688046 Elapsed: 0 Last input time: 392688484 Tick count: 392689062 Elapsed: 578 Done.