Fehler: Updatepaket (1603)

Fragen zu WAPT-Paketen / Anfragen und Hilfe bezüglich WAPT-Paketen.
Forumregeln
Community-Forumregeln
* Englischer Support auf www.reddit.com/r/wapt
* Französischer Community-Support ist in diesem Forum verfügbar.
* Bitte kennzeichnen Sie gelöste Themen mit [GELÖST].
* Bitte bearbeiten Sie keine Themen, die mit [GELÖST] markiert sind. Erstellen Sie stattdessen ein neues Thema und verweisen Sie auf das alte.
* Geben Sie die installierte WAPT-Version, die vollständige Versionsnummer und die Build-Nummer (2.2.1.11957 / 2.2.2.12337 / usw.) sowie die Enterprise-/Discovery-Edition an.
* Versionen 1.8.2 und älter werden nicht mehr unterstützt. Fragen zu Version 1.8.2 werden nur beantwortet, wenn sie sich auf ein Upgrade auf eine unterstützte Version (2.1, 2.2 usw.) beziehen.
* Geben Sie das Server-Betriebssystem (Linux/Windows) und die Version (Debian Buster/Bullseye – CentOS 7 – Windows Server 2012/2016/2019) an.
* Geben Sie gegebenenfalls das Betriebssystem des Administrations-/Paketerstellungsrechners und des Rechners mit dem problematischen Agenten an (Windows 7/10/11/Debian 11/etc.).
* Vermeiden Sie es, mehrere Fragen in einem Thema zu stellen, da diese sonst möglicherweise ignoriert werden. Falls mehrere Themen relevant sind, erstellen Sie bitte separate Themen, vorzugsweise nacheinander und nicht gleichzeitig (d. h. vermeiden Sie Spam im Forum).
* Fügen Sie Code-Snippets, Screenshots und andere Bilder direkt in Ihren Beitrag ein. Links zu Pastebin, Bitly und anderen Drittanbieterseiten werden systematisch entfernt.
* Wie in jedem Community-Forum erfolgt die Unterstützung freiwillig durch die Mitglieder. Für kommerziellen Support kontaktieren Sie bitte den Vertrieb von Tranquil IT unter +44 2 40 97 57 55.
ddcorazon
Nachrichten: 37
Anmeldung: 30. Mai 2023 - 23:53 Uhr

20. August 2025 - 00:41 Uhr

(folgend)

Wenn alles gut gelaufen ist, wird dies nach Abschluss der Arbeiten im Browser-MSI-After-Fix-Audit sichtbar sein
Screenshot 2025-08-20 001828.png
Screenshot 2025-08-20 001828.png (42,03 KB) 11693 Mal angesehen
Und normalerweise schaffe ich es dann, sobald es fertig ist, meine Upgrades von Wapt aus durchzuführen
Screenshot 2025-08-20 003943.png
Screenshot 2025-08-20 003943.png (58,23 KB) 11693 Mal angesehen
Ich habe ein paar Maschinen, bei denen es nicht funktioniert hat (es funktioniert auch nicht direkt auf den Maschinen, selbst mit der korrekten MSI-Datei der korrekten Version)

Nachfolgend der Code (zugegeben, er könnte noch optimiert werden)😅)

Code: Alle auswählen

#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
Nachrichten: 37
Anmeldung: 30. Mai 2023 - 23:53 Uhr

3. September 2025 – 15:30 Uhr

Hallo zusammen,

Da es nahezu unmöglich ist, alte Chrome Enterprise MSI-Dateien zu finden, habe ich mich für eine andere Lösung entschieden (die übrigens auch für Edge und „jede andere MSI-Datei“ funktioniert)
Es ist zwar eine recht drastische Lösung, aber wenn es keine andere Möglichkeit gibt, besteht die Idee darin, ein älteres Microsoft-Tool namens msizap zu verwenden. Indem wir die Kennung der installierten MSI-Datei ermitteln, können wir alle Einträge dieser MSI-Datei aus der Registrierung entfernen. So werden beispielsweise Chrome oder Edge in der Systemsteuerung nicht mehr als installiert angezeigt, obwohl sie es weiterhin sind.
Hier rufen wir also die Kennung ab
Get-WmiObject Win32_Product | Where-Object { $_.Name -like "*chrome*" } | Select-Object Name, Version, IdentifyingNumber

Name Version Identifikationsnummer
---- ------- -----------------
Google Chrome 139.0.7258.155 {AC157B81-B63F-3C87-802D-6A050E1EFBE7}

Anschließend wird mit MSIzap.exe T {die abgerufene Kennung}

Nachdem dies erledigt war, erkannte Windows Chrome nicht als installiert. Daher erzwangen wir die Installation über WAPT, wodurch eine Neuinstallation durchgeführt wurde. Nach der Behebung des Problems konnte ich das nachfolgende Update problemlos abschließen.

Nachfolgend der Code (er kann optimiert werden; es gibt noch einige Dinge, die nicht verwendet werden, angesichts der vielen Dinge, die ich ausprobiert habe)

Code: Alle auswählen

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

Bitteschön, falls es von Nutzen ist. 🙃
Antwort