Based on code from here and here I made my first steps with multithreading in PyQt5. After starting the program, the graphical user interface appears, but after several seconds it crashes with the following error
Process finished with exit code -1073740791 (0xC0000409)
After googling the error message, I am relatively sure that something is wrong with multithreading. Unfortunately I don't know what and how the error can be fixed.
Code
import sys
from datetime import datetime
import wmi
from PyQt5. QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QHeaderView
class KeyboardDetectorSignals(QObject):
keyboard_changed = pyqtSignal(str)
class KeyboardDetector(QRunnable):
def __init__(self):
super().__init__()
self.signals = KeyboardDetectorSignals()
def run(self):
device_connected_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"
device_disconnected_wql = "SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"
c = wmi.WMI()
connected_watcher = c.watch_for(raw_wql=device_connected_wql)
disconnected_watcher = c.watch_for(raw_wql=device_disconnected_wql)
while True:
try:
connected = connected_watcher(timeout_ms=10)
except wmi.x_wmi_timed_out:
pass
else:
if connected:
self.signals.keyboard_changed.emit("Keyboard connected.")
try:
disconnected = disconnected_watcher(timeout_ms=10)
except wmi.x_wmi_timed_out:
pass
else:
if disconnected:
self.signals.keyboard_changed.emit("Keyboard disconnected.")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("Keyboard Logger")
self.log_table = QTableWidget()
self.log_table.setColumnCount(2)
self.log_table.setShowGrid(True)
self.log_table.setHorizontalHeaderLabels(["Time", "Event"])
self.log_table.horizontalHeader().setStretchLastSection(True)
self.log_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.setCentralWidget(self.log_table)
self.show()
self.threadpool = QThreadPool()
keyboard_detector = KeyboardDetector()
keyboard_detector.signals.keyboard_changed.connect(self.add_row)
self.threadpool.start(keyboard_detector)
def add_row(self, event: str):
now = datetime.now()
datetime_string = now.strftime("%Y-%m-%d %H:%M:%S")
row_count = self.log_table.rowCount()
self.log_table.insertRow(row_count)
self.log_table.setItem(row_count, 0, QTableWidgetItem(datetime_string))
self.log_table.setItem(row_count, 1, QTableWidgetItem(event))
def main():
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Update 1: Removed @pyqtSlot()
.
Got the following error when running the script from the CMD:
Traceback (most recent call last):
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1340, in connect
obj = GetObject(moniker)
File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 72, in GetObject
return Moniker(Pathname, clsctx)
File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 87, in Moniker
moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
pywintypes.com_error: (-2147221020, 'Ung³ltige Syntax', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1354, in connect
handle_com_error()
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 258, in handle_com_error
raise klass(com_error=err)
wmi.x_wmi_uninitialised_thread: <x_wmi: Unexpected COM Error (-2147221020, 'Ung³ltige Syntax', None, None)>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "main.py", line 26, in run
c = wmi.WMI()
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1357, in connect
raise x_wmi_uninitialised_thread("WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex]")
wmi.x_wmi_uninitialised_thread: <x_wmi: WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex] (no underlying exception)>
PS C:\Users\ata\PycharmProjects\Snippets\KeyboardLogger>