Seite 1 von 1

Liste die Pakete und ihren Status auf

Veröffentlicht: 28. November 2025 - 11:19 Uhr
von Mikael S
Hallo,

gibt es eine Möglichkeit, alle auf einem Rechner installierten Pakete zusammen mit ihrem Status und dem zugehörigen Protokoll aus einer setup.py-Datei aufzulisten?

Dies soll die automatische Behebung problematischer Installationen ermöglichen.



Viele Grüße,

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 2. Dez. 2025 - 07:18 Uhr
von b.ald
Guten Morgen,

Ich bin mir nicht ganz sicher, was Sie genau vorhaben, aber in einem meiner Pakete habe ich etwas in der Art:

Code: Alle auswählen

package_list = WAPT.installed_package_names()      # recup les paquets installés sur la machine
for package in sorted(package_list):
    WAPT.audit(package, force=False)               # fait un audit du paquet pour chaque paquet présent dans la liste



Nach alldem ist es bereits in der WAPT-Konsole sichtbar.

Kommandant.

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 8. Dez. 2025 - 16:28 Uhr
von Mikael S
Hallo,

ich kann den Status so nicht abrufen.

Ich möchte beispielsweise Microsoft Visual C++ 2015-2022 installieren. Da Windows aber so ein umfangreiches Tool ist, erfordert die MSI-Installation die Deinstallation der alten Version. Die Installationsdatei wurde jedoch gelöscht

. Daher stürzt das Installationsprogramm ab. Eine Deinstallation ist nicht möglich, da dasselbe Problem auftritt. Ich muss also die Registry löschen, damit Windows die alte Installation vergisst und eine neue Installation durchführen kann.
Diese Situation tritt bei vielen Produkten sehr häufig auf.

Durch die Erstellung eines Mediationspakets liste ich alle aktuellen Fehler auf und starte eine Fehlerbehebung. In diesem Beispiel ermöglicht das Löschen der Registry eine erfolgreiche Installation.

Derzeit führen wir dies manuell über die Konsole durch. Bei 10.000 zu verwaltenden Workstations, von denen 450 Fehler aufweisen, wird das jedoch schnell unpraktikabel.
Wir haben alles Mögliche im Einsatz, von KeePassXC über Seafile bis hin zu Jabra usw.
Einige Fehler sind auf unsere vorherige Lösung zurückzuführen und treten nicht auf Rechnern auf, die mit WAPT installiert sind.

Kurz gesagt, die Idee ist, alles so weit wie möglich zu automatisieren, ohne die Maschinen ständig zu überwachen.
Bedenken Sie, dass ein behobenes Problem nicht bedeutet, dass es nach dem nächsten Update nicht wieder auftritt. Es hängt maßgeblich von den Installationsprogrammen ab (die oft sehr gut programmiert sind! :mrgreen: ).

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 8. Dez. 2025 - 16:34 Uhr
von florentR2
Das ist sehr interessant, denn ich habe gerade viel Zeit damit verbracht, eine Lösung für den Nextcloud-Client zu finden, der etliche Fehler dieser Art produziert.
Ich habe dieses Problem bisher nur mit try-catch-Blöcken behoben, aber Ihre Idee eines allgemeinen Lösungspakets ist nicht schlecht. Ich werde das Thema abonnieren, falls eine Lösung gefunden wird.
Ich entferne dies aus der Registry:

Code: Alle auswählen

HKLM\SOFTWARE\\Microsoft\Windows\CurrentVersion\Uninstall\{guid}
HKLM\SOFTWARE\Classes\Installer\Products\{guid_key_wininstaller}

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 15. Dez. 2025 - 14:13 Uhr
von b.ald
Guten Morgen,

Bedeutet „Status“, ob sich das Paket in den Zuständen „OK“, „WARNUNG“ oder „FEHLER“ befindet?

Wenn das der Fall ist, dann versuchen Sie vielleicht Folgendes:

Code: Alle auswählen

package = WAPT.is_installed('nom_de_votre_paquet')
package_status = package['install_status']                          # recupère si status OK/WARNING/ERROR
Eine einfache print-Anweisung sollte den Status anzeigen:

Code: Alle auswählen

print(package_status)
Aber dann können Sie beispielsweise Folgendes tun:

Code: Alle auswählen

if package_status == 'ERROR' : 
       ce que vous voulez faire ensuite



Nachtrag: Selbstverständlich muss das betreffende Paket bereits auf dem Rechner vorhanden sein.

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 3. Februar 2026 - 13:24 Uhr
von Mikael S
Es gibt möglicherweise einen einfacheren Weg, aber so erhält man eine Liste der Pakete, deren Installation fehlgeschlagen ist.

Code: Alle auswählen

for package in WAPT.waptdb.installed_packages_inventory():
        if package[5] == 'ERROR':
            print(package[1])
Nun gilt es herauszufinden, was genau korrigiert werden muss, um das Problem zu beheben

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 16. März 2026 - 13:18 Uhr
von Mikael S
Es wird hier noch getestet, aber so sieht es aus

Ich speichere eine JSON-Datei im Speicher, die alle versuchten Pakete enthält, sodass nur ein einziger Versuch unternommen wird.

Bislang führt dies zu guten Ergebnissen

Code: Alle auswählen

# -*- coding: utf-8 -*-
from setuphelpers import *
import json
import datetime
import winreg
import re
from contextlib import suppress
import itertools

# Dictionnaire package wapt => nom de l'application en format regex
dict_package_app = {
    "tis-chrome" : "Google Chrome",
    "tis-element" : "Element",
    "tis-googleearth" : "Google Earth Pro",
    "tis-glpi-agent" : "GLPI agent [0-9.]+",
    "tis-keepassxc" : "KeePassXC",
    "tis-libreoffice-fresh" : "LibreOffice [0-9.]+",
    "tis-microsoft-edge" : "Microsoft Edge",
    "tis-onlyoffice-desktop" : "ONLYOFFICE [0-9.]+ \(x64\)",
    "tis-oracle-java8-jre-free" : "Java 8 Update [0-9]+(| x64 bit)",
    "tis-pdf24-creator" : "PDF24 Creator",
    "tis-seafile" : "Seafile [0-9.]+",
    "tis-microsoft-teams" : "Teams Machine-Wide Installer",
    "tis-teamviewer" : "TeamViewer",
    "tis-vcredist2015-2022" : "Microsoft Visual C\+\+ (2015-2022 Redistributable \(x(86|64)\)|2022 X64 Additional Runtime) - [0-9.]+",
    "tis-wazo" : "Wazo Desktop",
    "tis-webex" : "Webex",
    "tis-webview2" : "Microsoft Edge WebView2 Runtime",
    "tis-zoom" : "Zoom Workplace \(64-bit\)"
}

json_file = r"C:\Windows\wapt\autofix.json"

def install():
    generate_json()

def audit():
    if not isfile(json_file):
        generate_json()

    with open(json_file) as file:
        status = json.load(file)

    return_value = "OK"
    packages_installed = set() # Contient la liste des paquets installés pour purge le json ensuite
    for wapt_installed_package in WAPT.waptdb.installed_status(include_errors=True):
        packages_installed.add(wapt_installed_package['package'])

        # Gestion des installation en erreur si le paquet est déclaré dans dict_package_app
        # Tentative de purge de la des anciennes installations de la base de registre
        if wapt_installed_package['install_status'] == "ERROR" and wapt_installed_package['package'] in dict_package_app:
            if status['install'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'installation du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'installation du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['install'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

                    delete_key("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 'DisplayName', dict_package_app[wapt_installed_package['package']])
                    delete_key("SOFTWARE\\Classes\\Installer\\Products", 'ProductName', dict_package_app[wapt_installed_package['package']])

                    try:
                        WAPT.install(wapt_installed_package['package'])
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")
                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['install'].get(wapt_installed_package['package'], False):
            del status['install'][wapt_installed_package['package']]

        # Gestion des audit en erreur
        # Tentative d'une installation forcée
        if wapt_installed_package['last_audit_status'] == "ERROR" and wapt_installed_package['package'] != "tis-autofix-installation":
            if status['audit'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'audit du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'audit du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['audit'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    try:
                        WAPT.install(wapt_installed_package['package'], force=True)
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")

                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['audit'].get(wapt_installed_package['package'], False):
            del status['audit'][wapt_installed_package['package']]

    # Purge des anciennes tentative si le paquet n'est plus sur la machine
    for wapt_installed_package in status['install'].copy():
        if wapt_installed_package not in packages_installed:
            del  status['install'][wapt_installed_package]

    for wapt_installed_package in status['audit'].copy():
        if wapt_installed_package not in packages_installed:
            del status['audit'][wapt_installed_package]

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

    return return_value

def uninstall():
    if isfile(json_file):
        remove_file(json_file)

def generate_json():
    if not isdir(r'C:\Windows\wapt'):
        mkdirs(r'C:\Windows\wapt')

    status = {}
    status['install'] = {}
    status['audit'] = {}

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

def delete_key(key_uninstall, key_value, key_search):
    for subkey in subkeys(key_uninstall):
        appkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, rf"{key_uninstall}\{subkey}", 0, winreg.KEY_READ)
        try:
            key_find = reg_getvalue(appkey, key_value, '')

            if re.match(f"^{key_search}$", key_find):
                print(f'Suppression clé {key_uninstall}\{subkey}')
                winreg.DeleteKey(appkey, '')
        except FileNotFoundError:
            pass

def subkeys(path, hkey=HKEY_LOCAL_MACHINE):
    with suppress(WindowsError), winreg.OpenKey(hkey, path, 0, winreg.KEY_READ) as k:
        for i in itertools.count():
            yield winreg.EnumKey(k, i)

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 16. März 2026 - 13:58 Uhr
von florentR2
Danke fürs Teilen!
Mikael S schrieb: 16. März 2026 - 13:18 Uhr Es wird hier noch getestet, aber so sieht es aus

Ich speichere eine JSON-Datei im Speicher, die alle versuchten Pakete enthält, sodass nur ein einziger Versuch unternommen wird.

Bislang führt dies zu guten Ergebnissen

Code: Alle auswählen

# -*- coding: utf-8 -*-
from setuphelpers import *
import json
import datetime
import winreg
import re

# Dictionnaire package wapt => nom de l'application en format regex
dict_package_app = {
    "tis-chrome" : "Google Chrome",
    "tis-element" : "Element",
    "tis-googleearth" : "Google Earth Pro",
    "tis-glpi-agent" : "GLPI agent [0-9.]+",
    "tis-keepassxc" : "KeePassXC",
    "tis-libreoffice-fresh" : "LibreOffice [0-9.]+",
    "tis-microsoft-edge" : "Microsoft Edge",
    "tis-oracle-java8-jre-free" : "Java 8 Update [0-9]+(| x64 bit)",
    "tis-pdf24-creator" : "PDF24 Creator",
    "tis-seafile" : "Seafile [0-9.]+",
    "tis-microsoft-teams" : "Teams Machine-Wide Installer",
    "tis-teamviewer" : "TeamViewer",
    "tis-vcredist2015-2022" : "Microsoft Visual C++ 2015-2022 Redistributable \(x(86|64)\) - [0-9.]+",
    "tis-wazo" : "Wazo Desktop",
    "tis-webex" : "Webex",
    "tis-webview2" : "Microsoft Edge WebView2 Runtime",
    "tis-zoom" : "Zoom Workplace \(64-bit\)"
}
json_file = r"C:\Windows\wapt\autofix.json"

def install():
    if not isfile(json_file) or force:
        generate_json()

def audit():
    if not isfile(json_file):
        generate_json()

    with open(json_file) as file:
        status = json.load(file)

    return_value = "OK"
    packages_installed = set() # Contient la liste des paquets installés pour purge le json ensuite
    for wapt_installed_package in WAPT.waptdb.installed_status(include_errors=True):
        packages_installed.add(wapt_installed_package['package'])

        # Gestion des installation en erreur si le paquet est déclaré dans dict_package_app
        # Tentative de purge de la des anciennes installations de la base de registre
        if wapt_installed_package['install_status'] == "ERROR" and wapt_installed_package['package'] in dict_package_app:
            if status['install'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'installation du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'installation du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['install'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

                    delete_key("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 'DisplayName', dict_package_app[wapt_installed_package['package']])
                    if iswin64():
                        delete_key("Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 'DisplayName', dict_package_app[wapt_installed_package['package']])

                    delete_key("SOFTWARE\\Classes\\Installer\\Products", 'ProductName', dict_package_app[wapt_installed_package['package']])

                    try:
                        WAPT.install(wapt_installed_package['package'])
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")
                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['install'].get(wapt_installed_package['package'], False):
            del status['install'][wapt_installed_package['package']]

        # Gestion des audit en erreur
        # Tentative d'une installation forcée
        if wapt_installed_package['last_audit_status'] == "ERROR" and wapt_installed_package['package'] != "tis-autofix-installation":
            if status['audit'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'audit du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'audit du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['audit'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    try:
                        WAPT.install(wapt_installed_package['package'], force=True)
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")

                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['audit'].get(wapt_installed_package['package'], False):
            del status['audit'][wapt_installed_package['package']]

    # Purge des anciennes tentative si le paquet n'est plus sur la machine
    for wapt_installed_package in status['install'].copy():
        if wapt_installed_package not in packages_installed:
            del  status['install'][wapt_installed_package]

    for wapt_installed_package in status['audit'].copy():
        if wapt_installed_package not in packages_installed:
            del status['audit'][wapt_installed_package]

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

    return return_value

def uninstall():
    if isfile(json_file):
        remove_file(json_file)


def generate_json():
    if not isdir(r'C:\Windows\wapt'):
        mkdirs(r'C:\Windows\wapt')

    status = {}
    status['install'] = {}
    status['audit'] = {}

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

def delete_key(uninstall, key_value, key_search):
    with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, uninstall) as key:
        i = 0
        while True:
            try:
                subkey = winreg.EnumKey(key, i)
                appkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "%s\\%s" % (uninstall, subkey))
                key_find = reg_getvalue(appkey, key_value, '')

                if re.match(f"^{key_search}$", key_find):
                    print(f'Suppression clé {uninstall}\{subkey}')
                    registry_deletekey(root=HKEY_LOCAL_MACHINE, path=uninstall, keyname=subkey, force=True, recursive=True)

                i += 1
            except WindowsError as e:
                # WindowsError: [Errno 259] No more data is available
                if e.winerror == 259:
                    break
                else:
                    raise

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 24. März 2026 - 08:00 Uhr
von Mikael S
Ein kurzes Update mit den neuesten Erkenntnissen.

Betreff: Auflistung der Pakete und deren Status

Veröffentlicht: 7. Mai 2026 - 14:06 Uhr
von Mikael S
Eine etwas finalere Version. Aktuell wurden mit diesem Paket etwa 75 % der fehleranfälligen Workstations in unserem Netzwerk automatisch korrigiert.
Unter anderem durch die Behebung der Probleme mit tis-vcredist2015-2022, von dem viele Pakete abhängig sind.

Code: Alle auswählen

# -*- coding: utf-8 -*-
from setuphelpers import *
import json
import datetime
import winreg
import re
from contextlib import suppress
import itertools

# Dictionnaire package wapt => nom de l'application en format regex
dict_package_app = {
    "tis-chrome" : "Google Chrome",
    "tis-element" : "Element",
    "tis-googleearth" : "Google Earth Pro",
    "tis-glpi-agent" : "GLPI Agent [0-9.]+",
    "tis-keepassxc" : "KeePassXC",
    "tis-libreoffice-fresh" : "LibreOffice [0-9.]+",
    "tis-microsoft-edge" : "Microsoft Edge(| Update)",
    "tis-onlyoffice-desktop" : "ONLYOFFICE [0-9.]+ \(x64\)",
    "tis-oracle-java8-jre-free" : "Java 8 Update [0-9]+(| x64 bit)",
    "tis-paint.net" : "Paint.NET",
    "tis-pdf24-creator" : "PDF24 Creator",
    "tis-seafile" : "Seafile [0-9.]+",
    "tis-microsoft-teams" : "Teams Machine-Wide Installer",
    "tis-teamviewer" : "TeamViewer",
    "tis-vcredist2015-2022" : "Microsoft Visual C\+\+ (2015-(2019|2022) Redistributable \(x(86|64)\)|(2019|2022) X(86|64) (Additional|Minimum) Runtime) - [0-9.]+",
    "tis-wazo" : "Wazo Desktop",
    "tis-webex" : "Webex",
    "tis-webview2" : "Microsoft Edge WebView2 Runtime",
    "tis-zoom" : "Zoom Workplace \(64-bit\)"
}

json_file = r"C:\Windows\wapt\autofix.json"

def install():
    generate_json()

def audit():
    if not isfile(json_file):
        generate_json()

    with open(json_file) as file:
        status = json.load(file)

    return_value = "OK"
    packages_installed = set() # Contient la liste des paquets installés pour purge le json ensuite
    for wapt_installed_package in WAPT.waptdb.installed_status(include_errors=True):
        packages_installed.add(wapt_installed_package['package'])

        # Gestion des installation en erreur si le paquet est déclaré dans dict_package_app
        # Tentative de purge de la des anciennes installations de la base de registre
        if wapt_installed_package['install_status'] == "ERROR" and wapt_installed_package['package'] in dict_package_app:
            if status['install'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'installation du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'installation du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['install'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

                    delete_key("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 'DisplayName', dict_package_app[wapt_installed_package['package']])
                    delete_key("Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 'DisplayName', dict_package_app[wapt_installed_package['package']], winreg.KEY_WOW64_32KEY)
                    delete_key("SOFTWARE\\Classes\\Installer\\Products", 'ProductName', dict_package_app[wapt_installed_package['package']])

                    try:
                        WAPT.install(wapt_installed_package['package'])
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")
                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['install'].get(wapt_installed_package['package'], False):
            del status['install'][wapt_installed_package['package']]

        # Gestion des audit en erreur
        # Tentative d'une installation forcée
        if wapt_installed_package['last_audit_status'] == "ERROR" and wapt_installed_package['package'] not in ("tis-audit-battery", "tis-autofix-installation"):
            if status['audit'].get(wapt_installed_package['package'], False):
                print(f"Réparation de l'audit du paquet {wapt_installed_package['package']} déjà tenté")
                return_value = "ERROR"
            else:
                print(f"Tentative de réparation de l'audit du paquet {wapt_installed_package['package']}")
                if WAPT.waptserver.available():
                    status['audit'][wapt_installed_package['package']] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    try:
                        WAPT.install(wapt_installed_package['package'], force=True)
                    except:
                        print(f"Erreur d'installation de {wapt_installed_package['package']}")

                    if return_value != "ERROR":
                        return_value = "WARNING"
                else:
                    print("Serveur WAPT non joignable - une tentative sera faite au prochain audit")

        # Si le paquet n'est pas en erreur, on le retire du json s'il existe
        elif status['audit'].get(wapt_installed_package['package'], False):
            del status['audit'][wapt_installed_package['package']]

    # Purge des anciennes tentative si le paquet n'est plus sur la machine
    for wapt_installed_package in status['install'].copy():
        if wapt_installed_package not in packages_installed:
            del  status['install'][wapt_installed_package]

    for wapt_installed_package in status['audit'].copy():
        if wapt_installed_package not in packages_installed:
            del status['audit'][wapt_installed_package]

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

    return return_value

def uninstall():
    if isfile(json_file):
        remove_file(json_file)

def generate_json():
    if not isdir(r'C:\Windows\wapt'):
        mkdirs(r'C:\Windows\wapt')

    status = {}
    status['install'] = {}
    status['audit'] = {}

    with open(json_file, 'w') as autofix:
        json.dump(status, autofix)

def delete_key(key_uninstall, key_value, key_search, access=winreg.KEY_WOW64_64KEY):
    for subkey in subkeys(key_uninstall, access):
        appkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, rf"{key_uninstall}\{subkey}", 0, winreg.KEY_READ | access)

        key_find = reg_getvalue(appkey, key_value, '')

        if re.match(f"^{key_search}$", key_find):
            print(f'Suppression clé {key_uninstall}\{subkey}')
            registry_deletekey(winreg.HKEY_LOCAL_MACHINE, key_uninstall, subkey, force=True, recursive=True)

def subkeys(path, access=winreg.KEY_WOW64_64KEY, hkey=HKEY_LOCAL_MACHINE,):
    with suppress(WindowsError), winreg.OpenKey(hkey, path, 0, winreg.KEY_READ | access) as k:
        for i in itertools.count():
            yield winreg.EnumKey(k, i)