Errore: pacchetto di aggiornamento (1603)

Domande sul packaging WAPT / Richieste e assistenza sui pacchetti Wapt.
Regole del forum
Regole del forum della community
* Supporto in inglese su www.reddit.com/r/wapt
* Supporto della community in francese disponibile su questo forum
* Si prega di anteporre [RISOLTO] al titolo dell'argomento se è stato risolto.
* Si prega di non modificare un argomento contrassegnato con [RISOLTO]. Aprire un nuovo argomento facendo riferimento a quello precedente.
* Specificare la versione di WAPT installata, la versione completa e il numero di build (2.2.1.11957 / 2.2.2.12337 / ecc.) nonché l'edizione Enterprise/Discovery.
* Le versioni 1.8.2 e precedenti non sono più supportate. Le uniche domande accettate relative alla versione 1.8.2 riguardano l'aggiornamento a una versione supportata (2.1, 2.2, ecc.).
* Specificare il sistema operativo del server (Linux/Windows) e la versione (Debian Buster/Bullseye - CentOS 7 - Windows Server 2012/2016/2019).
* Specificare il sistema operativo della macchina di amministrazione/creazione dei pacchetti e della macchina con l'agente problematico, se applicabile (Windows 7/10/11/Debian 11/ecc.).
* Evitare di porre più domande quando si apre una discussione, altrimenti potrebbe essere ignorata. Se ci sono più discussioni, aprirle separatamente, preferibilmente una dopo l'altra e non tutte contemporaneamente (ovvero, non intasare il forum).
* Includere frammenti di codice, screenshot e altre immagini direttamente nel post. I link a Pastebin, Bitly e altri siti di terze parti verranno sistematicamente rimossi.
* Come in qualsiasi forum della community, il supporto è fornito volontariamente dai membri. Se si necessita di supporto commerciale, è possibile contattare il reparto vendite di Tranquil IT al numero 02.40.97.57.55
ddcorazon
Messaggi: 37
Registrazione: 30 maggio 2023 - 23:53

20 agosto 2025 - 00:41

(seguente)

Una volta terminato, se tutto è andato bene, lo vedremo nell'audit browser-msi-after-fix
Schermata 2025-08-20 001828.png
Screenshot 2025-08-20 001828.png (42,03 KB) Visualizzato 11550 volte
E di solito, una volta terminato, riesco a effettuare gli aggiornamenti da Wapt
Schermata 2025-08-20 003943.png
Screenshot 2025-08-20 003943.png (58,23 KB) Visualizzato 11550 volte
Ho alcune macchine su cui non ha funzionato (e non funziona direttamente sulle macchine, nemmeno con l'MSI corretto della versione corretta)

Di seguito è riportato il codice (lo ammetto, potrebbe essere più ottimizzato)😅)

Codice: Seleziona tutto

#Auteur ddcorazon
# -*- coding: utf-8 -*-
from setuphelpers import *
import os, glob, shutil, traceback

# === CONFIG ===
tools = ["chrome", "edge"]
AUDIT_SCOPE_BEFORE = "browser-msi"
AUDIT_SCOPE_AFTER  = "browser-msi-after-fix"

_UNINSTALL_KEYS = [
    r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKCU\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
]

def install():
    """Copie le dossier 'msi' du paquet vers persistent_dir\\msi pour l'audit."""
    src_dir = makepath(os.getcwd(), "msi")  # côté build/exec, cwd = racine du paquet
    dst_dir = makepath(persistent_dir, "msi")
    if os.path.isdir(src_dir):
        print("[INSTALL] Sync MSIs ->", dst_dir)
        if os.path.isdir(dst_dir):
            shutil.rmtree(dst_dir, ignore_errors=True)
        shutil.copytree(src_dir, dst_dir)
    else:
        print("[INSTALL] Aucun dossier 'msi' à copier (", src_dir, ")")

def uninstall():
    pass

# ----------------- Helpers -----------------
def _normalize_tools(t):
    if isinstance(t, (list, tuple)):
        lst = [str(x).strip() for x in t]
    else:
        lst = [s.strip() for s in str(t).split(",")]
    return [s.lower() for s in lst if s]

def _scan_registry(term):
    """Retourne (DisplayName, LocalPackagePath, DisplayVersion)."""
    for base in _UNINSTALL_KEYS:
        try:
            for sub in glob.glob(base + r'\*'):
                try:
                    dn = registry_readstring(sub, 'DisplayName', '')
                    if not dn or term not in dn.lower():
                        continue
                    lp = registry_readstring(sub, 'LocalPackage', '')
                    dv = registry_readstring(sub, 'DisplayVersion', '')
                    return ((dn or '').strip(), (lp or '').strip(), (dv or '').strip())
                except Exception:
                    continue
        except Exception:
            continue
    return (None, None, None)

def _scan_wmi(term):
    """Fallback WMI (Win32_Product)."""
    try:
        ps = (
            r"Get-WmiObject -Class Win32_Product | "
            r"Where-Object { $_.Name -ne $null -and $_.Name -like '*" + term + r"*' } | "
            r"Select-Object Name, LocalPackage, Version"
        )
        data = run_powershell(ps)
        if not data:
            return (None, None, None)
        row = data[0] if isinstance(data, list) else data
        name  = (row.get('Name') or '').strip()
        local = (row.get('LocalPackage') or '').strip()
        ver   = (row.get('Version') or '').strip()
        return (name or None, local or None, ver or None)
    except Exception:
        return (None, None, None)

def _detect_one(term):
    """Retourne (name, pkg_basename, version, file_flag)."""
    name, local, ver = _scan_registry(term)
    if not name and not local and not ver:
        name, local, ver = _scan_wmi(term)

    pkg = os.path.basename(local) if local else ""
    file_flag = "Unknown"
    if pkg:
        installer_dir = os.path.join(os.environ.get("SystemRoot", r"C:\Windows"), "Installer")
        candidate1 = os.path.join(installer_dir, pkg)
        candidate2 = local
        if (candidate2 and os.path.exists(candidate2)) or os.path.exists(candidate1):
            file_flag = "Found"
        else:
            file_flag = "Missing"

    return name or "", pkg, ver or "", file_flag

def _run_audit(scope):
    """Exécute l’audit pour tous les tools, retourne (result_data, found_any)."""
    result_data = {}
    found_any = False

    for term in _normalize_tools(tools):
        section = term.capitalize()
        name, pkg, ver, file_flag = _detect_one(term)

        result_data[section] = {
            "Name": name,
            "Package": pkg,
            "Version": ver,
            "File": file_flag
        }
        if name or pkg or ver:
            found_any = True

    WAPT.write_audit_data_if_changed(scope, "audit_data", result_data)
    WAPT.write_audit_data_if_changed(scope, "result", "OK" if found_any else "NotFound")
    return result_data, found_any

def _fix_missing(result_data):
    """
    Copie les MSI manquants depuis persistent_dir\\msi\\<tool>-<version>.msi
    -> C:\\Windows\\Installer\\<package>
    """
    installer_dir = os.path.join(os.environ.get("SystemRoot", r"C:\Windows"), "Installer")
    src_dir = makepath(persistent_dir, "msi")
    print(f"[INFO] Dossier source MSI: {src_dir}")

    for app, info in result_data.items():
        tool = app.lower()
        pkg  = info.get("Package")   # ex: 16af95e8.msi
        ver  = info.get("Version")   # ex: 139.0.x.x
        flag = info.get("File")

        if flag == "Missing" and pkg and ver:
            src = makepath(src_dir, f"{tool}-{ver}.msi")
            dst = makepath(installer_dir, pkg)
            if os.path.exists(src):
                print(f"[FIX] Copie {src} -> {dst}")
                os.makedirs(installer_dir, exist_ok=True)
                shutil.copyfile(src, dst)
            else:
                print(f"[WARN] MSI source introuvable pour {app}: {src}")

def _cleanup_persistent_msis():
    """Supprime persistent_dir\\msi pour ne rien laisser sur le poste."""
    msi_dir = makepath(persistent_dir, "msi")
    if os.path.isdir(msi_dir):
        print(f"[CLEANUP] Suppression du répertoire: {msi_dir}")
        shutil.rmtree(msi_dir, ignore_errors=True)

# ----------------- Audit principal -----------------
def audit():
    try:
        # 1) Audit avant
        before_data, found_any = _run_audit(AUDIT_SCOPE_BEFORE)

        # 2) Corrections si nécessaires
        if found_any:
            needs_fix = any(info.get("File") == "Missing" for info in before_data.values())
            if needs_fix:
                _fix_missing(before_data)
                # 3) Audit après correction
                _run_audit(AUDIT_SCOPE_AFTER)
            return "OK"
        else:
            return "NotFound"

    except Exception as e:
        print("[ERROR] Exception durant l'audit :", e)
        print(traceback.format_exc())
        return "ERROR"

    finally:
        # 4) Toujours nettoyer le persistent_dir\msi en fin d’audit
        _cleanup_persistent_msis()
 
ddcorazon
Messaggi: 37
Registrazione: 30 maggio 2023 - 23:53

3 settembre 2025 - 15:30

Ciao a tutti,

Data la quasi impossibilità di trovare i vecchi file MSI di Chrome Enterprise, ho optato per un'altra soluzione (che tra l'altro funziona per Edge e "qualsiasi altro MSI")
È una soluzione piuttosto drastica, ma se non abbiamo altra scelta, l'idea è quella di utilizzare una vecchia utility Microsoft chiamata msizap. Recuperando l'identificativo dell'MSI installato, possiamo rimuovere "tutti i riferimenti" a quell'MSI dal registro. Quindi, ad esempio, Chrome o Edge non appariranno più come installati nel Pannello di controllo, anche se lo sono ancora.
Quindi qui recuperiamo l'identificatore
Get-WmiObject Win32_Product | Where-Object { $_.Name -like "*chrome*" } | Select-Object Nome, Versione, IdentifyingNumber

Nome Versione Numero Identificativo
---- ------- -----------------
Google Chrome 139.0.7258.155 {AC157B81-B63F-3C87-802D-6A050E1EFBE7}

Quindi, utilizzando MSIzap.exe T {l'identificatore che abbiamo recuperato}

Fatto ciò, Windows ha considerato Chrome non installato, quindi abbiamo forzato l'installazione da WAPT e ha eseguito un'installazione pulita. Una volta risolto il problema, sono riuscito a completare l'aggiornamento successivo senza problemi.

Di seguito è riportato il codice (può essere ottimizzato; ci sono ancora alcune cose che non vengono utilizzate, nonostante le numerose prove che ho fatto)

Codice: Seleziona tutto

# -*- coding: utf-8 -*-
from setuphelpers import *
import os, glob, shutil, traceback

# === CONFIG ===
tools = ["chrome"]
AUDIT_SCOPE_BEFORE = "chrome-msi"
AUDIT_SCOPE_AFTER  = "chrome-msi-after-fix"

_UNINSTALL_KEYS = [
    r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
    r'HKCU\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
]

def install():
    """Copie msizap.exe dans persistent_dir\\msi pour utilisation locale."""
    src_dir = makepath(os.getcwd(), "msi")  # côté paquet WAPT
    dst_dir = makepath(persistent_dir, "msi")
    if os.path.isdir(src_dir):
        print("[INSTALL] Sync MSIs ->", dst_dir)
        if os.path.isdir(dst_dir):
            shutil.rmtree(dst_dir, ignore_errors=True)
        shutil.copytree(src_dir, dst_dir)
    else:
        print("[INSTALL] Aucun dossier 'msi' à copier (", src_dir, ")")

def uninstall():
    pass

# ----------------- Helpers -----------------
def _normalize_tools(t):
    if isinstance(t, (list, tuple)):
        lst = [str(x).strip() for x in t]
    else:
        lst = [s.strip() for s in str(t).split(",")]
    return [s.lower() for s in lst if s]

def _scan_registry(term):
    """Retourne (DisplayName, LocalPackagePath, DisplayVersion)."""
    for base in _UNINSTALL_KEYS:
        try:
            for sub in glob.glob(base + r'\*'):
                try:
                    dn = registry_readstring(sub, 'DisplayName', '')
                    if not dn or term not in dn.lower():
                        continue
                    lp = registry_readstring(sub, 'LocalPackage', '')
                    dv = registry_readstring(sub, 'DisplayVersion', '')
                    return ((dn or '').strip(), (lp or '').strip(), (dv or '').strip())
                except Exception:
                    continue
        except Exception:
            continue
    return (None, None, None)

def _scan_wmi(term):
    """Retourne (Name, LocalPackage, Version, IdentifyingNumber)."""
    try:
        ps = (
            r"Get-WmiObject -Class Win32_Product | "
            r"Where-Object { $_.Name -ne $null -and $_.Name -like '*" + term + r"*' } | "
            r"Select-Object Name, LocalPackage, Version, IdentifyingNumber"
        )
        data = run_powershell(ps)
        if not data:
            return (None, None, None, None)
        row = data[0] if isinstance(data, list) else data
        name  = (row.get('Name') or '').strip()
        local = (row.get('LocalPackage') or '').strip()
        ver   = (row.get('Version') or '').strip()
        prod  = (row.get('IdentifyingNumber') or '').strip()
        return (name or None, local or None, ver or None, prod or None)
    except Exception:
        return (None, None, None, None)

def _detect_one(term):
    """Retourne (name, pkg_basename, version, file_flag, product_id)."""
    name, local, ver = _scan_registry(term)
    prod_id = ""
    if not name and not local and not ver:
        name, local, ver, prod_id = _scan_wmi(term)
    else:
        # récupère aussi via WMI pour ProductCode
        _, _, _, prod_id = _scan_wmi(term)

    pkg = os.path.basename(local) if local else ""
    file_flag = "Unknown"
    if pkg:
        installer_dir = os.path.join(os.environ.get("SystemRoot", r"C:\Windows"), "Installer")
        candidate1 = os.path.join(installer_dir, pkg)
        candidate2 = local
        if (candidate2 and os.path.exists(candidate2)) or os.path.exists(candidate1):
            file_flag = "Found"
        else:
            file_flag = "Missing"

    return name or "", pkg, ver or "", file_flag, prod_id

def _run_audit(scope):
    """Exécute l’audit pour Chrome, retourne (result_data, found_any)."""
    result_data = {}
    found_any = False

    for term in _normalize_tools(tools):
        section = term.capitalize()
        name, pkg, ver, file_flag, prod_id = _detect_one(term)

        result_data[section] = {
            "Name": name,
            "Package": pkg,
            "Version": ver,
            "File": file_flag,
            "Id": prod_id
        }
        if name or pkg or ver:
            found_any = True

    WAPT.write_audit_data_if_changed(scope, "audit_data", result_data)
    WAPT.write_audit_data_if_changed(scope, "result", "OK" if found_any else "NotFound")
    return result_data, found_any

def _zap_chrome(result_data):
    """Exécute msizap.exe T {GUID} pour Chrome trouvé."""
    zap_exe = makepath(persistent_dir, "msi", "msizap.exe")
    if not os.path.exists(zap_exe):
        print(f"[ERROR] msizap.exe introuvable : {zap_exe}")
        return

    for app, info in result_data.items():
        prod_id = info.get("Id") or ""
        if prod_id and prod_id.startswith("{"):
            cmd = f'"{zap_exe}" T {prod_id}'
            print(f"[ZAP] {cmd}")
            run(cmd)

def _cleanup_persistent_msis():
    """Supprime persistent_dir\\msi après utilisation."""
    msi_dir = makepath(persistent_dir, "msi")
    if os.path.isdir(msi_dir):
        print(f"[CLEANUP] Suppression du répertoire: {msi_dir}")
        shutil.rmtree(msi_dir, ignore_errors=True)

# ----------------- Audit principal -----------------
def audit():
    try:
        # 1) Audit avant
        before_data, found_any = _run_audit(AUDIT_SCOPE_BEFORE)

        # 2) Si Chrome trouvé, zapper avec msizap
        if found_any:
            _zap_chrome(before_data)

        # 3) Audit après
        _run_audit(AUDIT_SCOPE_AFTER)
        return "OK" if found_any else "NotFound"

    except Exception as e:
        print("[ERROR] Exception durant l'audit :", e)
        print(traceback.format_exc())
        return "ERROR"

    finally:
        # 4) Nettoyage final
        _cleanup_persistent_msis()

Ecco qua, se può servire a qualcosa. 🙃
Risposta