Page 1 sur 1

Lister les paquets et leur état

Publié : 28 nov. 2025 - 11:19
par Mikael S
Bonjour,

Existe-t-il un moyen de lister tous les paquets installés sur une machine ainsi que leur état et leur audit depuis un setup.py ?

L'idée serait de mettre en place des remédiations automatiques dans certains cas avec des installations problématiques.



Cordialement,

Re: Lister les paquets et leur état

Publié : 02 déc. 2025 - 07:18
par b.ald
Bonjour,

je ne suis pas très sûr de ce que vous cherchez à faire mais dans un de mes paquets j'ai quelque chose dans le genre :

Code : Tout sélectionner

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



Après.. tout cela est déjà visible dans la console WAPT.

Cdt.

Re: Lister les paquets et leur état

Publié : 08 déc. 2025 - 16:28
par Mikael S
Bonjour,

Cela ne me permet pas d'obtenir le statut.

L'idée, c'est par exemple, je veux installer les microsoft visual c++ 2015-2022, mais windows étant un outil formidable, l'installation du msi requiert de désinstaller l'ancien, mais le fichier d'installation a depuis été supprimé.

L'installateur part donc en erreur. Il est impossible de désinstaller, même problème, il faut donc purger la base de registre pour faire oublier à windows la présence de cette installation et donc d'en faire une nouvelle.
Ce type de cas se produit très souvent sur plein de produit.

En faisant un paquet médiation, je liste toutes les erreurs en cours et je lance une remédiation. Dans l'exemple, purger la base de registre pour permettre ensuite la bonne installation.

Actuellement, nous l'avons dans la console, et nous le faisons à la main. Mais avec 10 000 postes à gérer dont 450 avec des erreurs, c'est vite intenable.
On a de tout, du keepassxc, seafile, jabra, etc.
Certaines erreurs sont dues à notre précédente solution et n'apparaissent pas sur les postes installés avec WAPT.

Bref, l'idée est de gérer tout ça au maximum automatiquement et sans être derrière les postes tout le temps.
Sachant qu'un poste corrigé ne veut pas dire que le problème ne se posera pas à la prochaine mise à jour. Cela dépend beaucoup d'installateurs (souvent très bien codé ! :mrgreen: )

Re: Lister les paquets et leur état

Publié : 08 déc. 2025 - 16:34
par florentR2
C'est très intéressant car je viens justement de passer pas mal de temps pour trouver une solution pour le client Nextcloud qui nous produit pas mal d'erreur de ce type.
J'ai corrigé seulement ce package avec des try catch mais votre idée d'un paquet de remédiation général est pas mal, je m'abonne au topic si y'a une solution qui tombe.
Je purge ceci dans le registre :

Code : Tout sélectionner

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

Re: Lister les paquets et leur état

Publié : 15 déc. 2025 - 14:13
par b.ald
Bonjour,

par "status", est-ce si le paquet est en "OK"/"WARNING"/"ERROR" ?

Si c'est le cas, alors essayez peut-être :

Code : Tout sélectionner

package = WAPT.is_installed('nom_de_votre_paquet')
package_status = package['install_status']                          # recupère si status OK/WARNING/ERROR
un simple print devrait afficher le status :

Code : Tout sélectionner

print(package_status)
mais vous pouvez ensuite faire par exemple un

Code : Tout sélectionner

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



edit : après il faut bien entendu que le paquet en question soit déjà présent sur la machine

Re: Lister les paquets et leur état

Publié : 03 févr. 2026 - 13:24
par Mikael S
Il doit peut-être avoir plus simple, mais ceci marche pour avoir la liste des paquets dont l'installation est en erreur.

Code : Tout sélectionner

for package in WAPT.waptdb.installed_packages_inventory():
        if package[5] == 'ERROR':
            print(package[1])
Reste encore à tenter de corriger en trouvant quoi corriger

Re: Lister les paquets et leur état

Publié : 16 mars 2026 - 13:18
par Mikael S
C'est encore en test chez nous, mais ça donne ça

Je garde en mémoire dans un json tous les paquets tenté pour ne faire qu'une seule tentative.

Cela donne pour l'instant de bons résultats

Code : Tout sélectionner

# -*- 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)

Re: Lister les paquets et leur état

Publié : 16 mars 2026 - 13:58
par florentR2
Merci pour le partage !
Mikael S a écrit : 16 mars 2026 - 13:18 C'est encore en test chez nous, mais ça donne ça

Je garde en mémoire dans un json tous les paquets tenté pour ne faire qu'une seule tentative.

Cela donne pour l'instant de bons résultats

Code : Tout sélectionner

# -*- 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

Re: Lister les paquets et leur état

Publié : 24 mars 2026 - 08:00
par Mikael S
Une petite maj avec les dernières trouvailles.