Search code examples
pythonpywin32

Python does not find the dwTime attribute of the Structure class


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.

Solution

  • There are a bunch of critical errors in your code (besides the wrong indentation - which I consider a formatting issue):

    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.