0

How do I set an alarm using pywin32? I can't understand. Alarm returns None. If possible, then please in the example, I would appreciate it!

hTimer = win32event.CreateWaitableTimer(None, True,'test')

alarm = win32event.SetWaitableTimer(hTimer,10, 10, None, None, True)

1 Answers1

0

Check [ME.TimGolden]: Python for Win32 Extensions Help ((officially) referenced by [GitHub]: mhammond/pywin32 - pywin32).

The supplied arguments are not correct (they are not incorrect per se but from expected outcome PoV). Check [MS.Docs]: SetWaitableTimer function (synchapi.h) for more details.

Unfortunately, the PyWin32 wrapper doesn't handle the callback feature (None must be supplied), so the usecases are reduced (although it didn't happen in the question).

Here's how it can be used.

code00.py:

#!/usr/bin/env python

import sys
import time

import win32api as wapi
import win32event as wevt


SEC = 10000000


def main(*argv):
    timer = wevt.CreateWaitableTimer(None, True, "Test")
    due = 2
    period = 500
    print("Setting timer to {:.3f} seconds".format(due))
    wevt.SetWaitableTimer(timer, due * -SEC, period, None, None, True)
    time_start = time.time()
    res = wevt.WaitForSingleObject(timer, -1)
    print("{:.3f} seconds elapsed. Result: {:d}".format(time.time() - time_start, res))
    wapi.CloseHandle(timer)


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:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073524234]> "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

Setting timer to 2.000 seconds
2.001 seconds elapsed. Result: 0

Done.

If you want a callback function to be automatically called at a given interval, you could use PyWin32's Timer module.

code01.py:

#!/usr/bin/env python

import msvcrt
import sys
import time

import timer as wtmr
import win32con as wcon
import win32gui as wgui


def timer_callback(tid, tm):
    print("Timer callback ({:}, {:}): {:}".format(tid, tm, time.gmtime()))


def main(*argv):
    due = 1
    print("Setting timer to {:.3f} seconds. Press a key to stop...".format(due))
    timer = wtmr.set_timer(due * 1000, timer_callback)
    while not msvcrt.kbhit():
        msg = wgui.GetMessage(None, 0, 0)
        if msg[0] != -1 and msg[1][1] == wcon.WM_TIMER:
            wgui.DispatchMessage(msg[1])
    wtmr.kill_timer(timer)


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:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073524234]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code01.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

Setting timer to 1.000 seconds. Press a key to stop...
Timer callback (29224, 174310765): time.struct_time(tm_year=2022, tm_mon=9, tm_mday=2, tm_hour=6, tm_min=4, tm_sec=27, tm_wday=4, tm_yday=245, tm_isdst=0)
Timer callback (29224, 174311765): time.struct_time(tm_year=2022, tm_mon=9, tm_mday=2, tm_hour=6, tm_min=4, tm_sec=28, tm_wday=4, tm_yday=245, tm_isdst=0)
Timer callback (29224, 174312765): time.struct_time(tm_year=2022, tm_mon=9, tm_mday=2, tm_hour=6, tm_min=4, tm_sec=29, tm_wday=4, tm_yday=245, tm_isdst=0)
Timer callback (29224, 174313765): time.struct_time(tm_year=2022, tm_mon=9, tm_mday=2, tm_hour=6, tm_min=4, tm_sec=30, tm_wday=4, tm_yday=245, tm_isdst=0)
Timer callback (29224, 174314765): time.struct_time(tm_year=2022, tm_mon=9, tm_mday=2, tm_hour=6, tm_min=4, tm_sec=31, tm_wday=4, tm_yday=245, tm_isdst=0)

Done.

Note: There is another way of calling SetWaitableTimer with a callback. It can be done via [Python.Docs]: ctypes - A foreign function library for Python, but requires lots of boilerplate code and C knowledge. [SO]: Get the title of a window of another program using the process name (@CristiFati's answer) contains code using both PyWin32 and CTypes, you could check the differences between them.

CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • is it possible to somehow record an alarm clock in windows so that at the end a notification of the windows itself about the time comes out? 'built-in clock in windows 10' – MrManchkin Sep 12 '22 at 10:32
  • I don't understand the question. In both examples when time elapses, you could do whatever you want (I displayed a text, but you could display an image, play a song, ...). – CristiFati Sep 12 '22 at 10:52