Sysprep errore 0x80073cf2 in Windows Server 24H2: fix per Microsoft.Winget.Source, script e best practice

Se Sysprep /generalize su Windows Server 24H2 si ferma con l’errore 0x80073cf2 e nel log compare Microsoft.Winget.Source, questa guida spiega perché accade e come risolvere in modo sicuro, con comandi PowerShell pronti all’uso, script automatizzato e pratiche per prevenire il problema.

Indice

Scenario e sintomi

Durante la preparazione di una “golden image” di Windows Server 24H2 (Build 26100.2314), l’esecuzione di Sysprep /generalize può interrompersi con l’errore 0x80073cf2. Nel file di log di Sysprep (cartella C:\Windows\System32\Sysprep\Panther) compaiono messaggi simili a questi:

Package Microsoft.Winget.Source_... was installed for a user, but not provisioned for all users.
SYSPRP Failed to remove apps for the current user: 0x80073cf2
A fatal error occurred while trying to sysprep the machine.

Il significato è chiaro: è presente almeno un pacchetto UWP (AppX) installato solo per l’utente corrente e non “provisionato” nell’immagine del sistema. In particolare Microsoft.Winget.Source risulta installato per un profilo, ma non registrato come app predefinita per tutti i nuovi utenti. Sysprep richiede coerenza tra lo strato utente e lo strato immagine; quando trova una discrepanza che non può gestire in autonomia, si ferma.

Perché accade: UWP, AppX e provisioning in breve

Le app UWP (Universal Windows Platform) vengono installate in due piani distinti:

  • Per-utente (visibili con Get‑AppxPackage): l’app è registrata nel profilo di uno specifico account.
  • Provisioned (visibili con Get‑AppxProvisionedPackage): l’app è “impacchettata” nell’immagine del sistema; ogni nuovo profilo che si crea la riceverà automaticamente.

Sysprep verifica che non restino app per-utente che non esistono anche nello strato provisioned (o viceversa, app provisioned mai installate in nessun profilo quando si aspettano determinate condizioni). Se trova pacchetti “orfani”, li prova a rimuovere; se la rimozione fallisce, termina con 0x80073cf2 (install failed in ambito AppX).

Soluzione rapida (TL;DR)

  1. Individuare i pacchetti Winget residui con PowerShell: Get-AppxPackage -AllUsers | Where-Object {$_.PackageFamilyName -like "Winget"}
  2. Rimuovere la app per tutti gli utenti ed eventualmente dal provisioning: # Disinstallazione dall’account locale e globalmente Get-AppxPackage -Name Microsoft.Winget.Source -AllUsers | Remove-AppxPackage -AllUsers Se presente anche nel provisioning dell’immagine Get-AppxProvisionedPackage -Online | Where-Object {$_.PackageName -like "Winget"} | Remove-AppxProvisionedPackage -Online
  3. Pulire i componenti (consigliato): DISM /Online /Cleanup-Image /StartComponentCleanup
  4. Riavviare ed eseguire di nuovo Sysprep (esempio): Sysprep /oobe /generalize /shutdown

Dopo questa sequenza, la generalizzazione completa con successo seguendo le indicazioni anche presenti nella documentazione Microsoft dedicata ai problemi di Sysprep con app dello Store.

Procedura dettagliata e verifiche

Verificare lo stato delle app UWP

Esegui PowerShell come amministratore e controlla la presenza di pacchetti Winget (o di altre app non desiderate):

# Elenco sintetico per famiglia
Get-AppxPackage -AllUsers |
  Where-Object {$_.PackageFamilyName -like "Winget"} |
  Select-Object Name, PackageFamilyName, PackageFullName, @{n="User";e={$_.UserSid}}

Controlla anche il piano “provisioned” dell’immagine corrente:

Get-AppxProvisionedPackage -Online |
  Where-Object {$_.PackageName -like "Winget"} |
  Select-Object DisplayName, PackageName

Rimuovere in modo sicuro Microsoft.Winget.Source

Se il pacchetto è presente solo come per‑utente, elimina le registrazioni per tutti gli account locali:

Get-AppxPackage -Name Microsoft.Winget.Source -AllUsers |
  Remove-AppxPackage -AllUsers

Se il pacchetto compare anche nello strato provisioned, rimuovilo dall’immagine per evitare che torni con i nuovi profili:

Get-AppxProvisionedPackage -Online |
  Where-Object {$_.PackageName -like "Winget"} |
  Remove-AppxProvisionedPackage -Online

Nota: su alcune build il cmdlet Remove‑AppxProvisionedPackage dispone dell’opzione -AllUsers per rimuovere l’app anche dai profili esistenti; se disponibile nel tuo ambiente puoi aggiungerla. In caso contrario esegui comunque la rimozione per‑utente come da comando precedente.

Pulizia componenti e riavvio

La pulizia con DISM non è obbligatoria, ma riduce pacchetti e metadati residui che a volte riattivano dipendenze inaspettate:

DISM /Online /Cleanup-Image /StartComponentCleanup

Al termine, riavvia e ripeti Sysprep:

Sysprep /oobe /generalize /shutdown

Confermare la correzione

Dopo il riavvio (prima di lanciare Sysprep o subito dopo il suo completamento), verifica che non esistano più pacchetti Winget per-utente non provisionati:

$perUser = Get-AppxPackage -AllUsers | Select-Object -ExpandProperty PackageFamilyName -Unique
$prov    = (Get-AppxProvisionedPackage -Online).PackageName
Deriva la "family" dal nome completo dello strato provisioned
$provFamilies = $prov | ForEach-Object { if ($ -match '^(?[^]+[^]+)') { $matches.fam } } | Sort-Object -Unique
$orphan = $perUser | Where-Object { $provFamilies -notcontains $_ }
$orphan

Se la variabile $orphan è vuota, la situazione è coerente e Sysprep non dovrebbe più bloccarsi su questo errore.

Conservare Winget invece di rimuoverlo (opzione di provisioning)

In alcuni ambienti è utile mantenere Winget (o altre UWP) anche dopo la cattura dell’immagine. In tal caso:

  1. Recupera il pacchetto (bundle MSIX/appx) e le eventuali dipendenze.
  2. Aggiungi l’app allo strato provisioned: Add-AppxProvisionedPackage -Online ` -PackagePath "D:\Pacchetti\Microsoft.Winget.Source.msixbundle" ` -SkipLicense
  3. Verifica che compaia nell’elenco provisioned: Get-AppxProvisionedPackage -Online | Where-Object {$_.PackageName -like "Winget"}

Importante: Winget include componenti differenti (client, sorgenti, runtime VC, ecc.). Se decidi di “tenere” Winget, assicurati di includere tutte le dipendenze richieste, altrimenti potresti ritrovarti con pacchetti frammentati e nuovamente a rischio errore in fase Sysprep.

Script pronto all’uso: rimozione sicura dei pacchetti Winget “orfani”

Lo script seguente individua e rimuove in modo difensivo Microsoft.Winget.Source ovunque sia emerso (profili utente e/o immagine), con log a video. Puoi inserirlo in una Task Sequence (MDT/ConfigMgr) o in una pipeline di preparazione immagini.

# Fix-WingetSysprep.ps1
Esegue come amministratore. Rimuove Microsoft.Winget.Source per tutti gli utenti e dal provisioning.

[CmdletBinding()]
param(
[switch]$WhatIfOnly
)

function Write-Info($msg){ Write-Host "[INFO] $msg" }
function Write-Warn($msg){ Write-Host "[WARN] $msg" -ForegroundColor Yellow }
function Write-Err ($msg){ Write-Host "[ERR ] $msg"  -ForegroundColor Red }

try {
$ErrorActionPreference = "Stop"
Write-Info "Ricerca pacchetti Winget per-utente..."
$perUserWinget = Get-AppxPackage -AllUsers | Where-Object {
$.PackageFamilyName -like "Microsoft.Winget." -or $.Name -like "Microsoft.Winget."
}
```
if ($perUserWinget) {
    $perUserWinget | ForEach-Object {
        Write-Info "Trovato per-utente: $($_.PackageFullName) (UserSid=$($_.UserSid))"
    }
    if (-not $WhatIfOnly) {
        Write-Info "Rimozione per tutti gli utenti..."
        $perUserWinget | ForEach-Object {
            try {
                Get-AppxPackage -AllUsers -Package $_.PackageFullName |
                    Remove-AppxPackage -AllUsers -ErrorAction Continue
            } catch {
                Write-Warn "Rimozione per-utente fallita per $($_.PackageFullName): $($_.Exception.Message)"
            }
        }
    }
} else {
    Write-Info "Nessun pacchetto Winget per-utente trovato."
}

Write-Info "Ricerca pacchetti Winget nello strato 'provisioned'..."
$provWinget = Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like "*Winget*" }
if ($provWinget) {
    $provWinget | ForEach-Object {
        Write-Info "Provisioned: $($_.DisplayName) - $($_.PackageName)"
    }
    if (-not $WhatIfOnly) {
        Write-Info "Rimozione dal provisioning dell'immagine..."
        $provWinget | ForEach-Object {
            try {
                $_ | Remove-AppxProvisionedPackage -Online -ErrorAction Continue
            } catch {
                Write-Warn "Rimozione provisioning fallita per $($_.PackageName): $($_.Exception.Message)"
            }
        }
    }
} else {
    Write-Info "Nessun pacchetto Winget nello strato 'provisioned'."
}

Write-Info "Operazione completata. Esegui un riavvio prima di Sysprep."
```
} catch {
Write-Err  $_.Exception.Message
exit 1
}
exit 0

Variante per immagini offline (WIM montata)

Se stai lavorando su un’immagine offline montata in D:\Mount:

# Elenco pacchetti provisioned nell'immagine
Get-AppxProvisionedPackage -Path "D:\Mount" | Where-Object {$_.PackageName -like "Winget"}

Rimozione dall'immagine offline

Get-AppxProvisionedPackage -Path "D:\Mount" |
Where-Object {$_.PackageName -like "Winget"} |
Remove-AppxProvisionedPackage -Path "D:\Mount"

Ricorda di smontare e salvare l’immagine quando hai finito (DISM /Unmount-Image /MountDir:D:\Mount /Commit).

Dove guardare i log

  • C:\Windows\System32\Sysprep\Panther\setupact.log e setuperr.log: log principali di Sysprep.
  • Visualizzatore eventi → Microsoft‑Windows‑AppXDeploymentServer/Operational: dettagli sugli errori di install/rimozione AppX (incluso 0x80073cf2).
  • %ProgramData%\Microsoft\Windows\AppRepository: database locale delle app (non modificare manualmente).

Buone pratiche per evitare l’errore in fase di cattura

PassoCosa farePerché
Controllo appVerificare con Get‑AppxPackage -AllUsers che non vi siano app installate per singoli utenti ma non provisionate.Sysprep richiede coerenza tra pacchetti utente e immagine.
Lavorare offlineDisattivare la connessione a Internet o bloccare gli aggiornamenti Microsoft Store durante la preparazione.Evita che nuove UWP vengano installate tra un passaggio e l’altro.
Provisioning intenzionaleSe occorre conservare un’app UWP (es. Winget), aggiungerla con Add‑AppxProvisionedPackage -Online + dipendenze.L’app risulta presente per tutti i futuri utenti e Sysprep la accetta.
Pulizia periodicaEseguire DISM /StartComponentCleanup o Remove‑AppxProvisionedPackage su pacchetti obsoleti.Riduce pacchetti “orphan” che potrebbero bloccare Sysprep.
Policy di contenutoAbilitare “Turn off Microsoft consumer experiences” e disattivare gli aggiornamenti automatici dello Store tramite criteri.Impedisce che vengano aggiunte app consumer durante la preparazione della VM.
Sequenza operativaStabilire un ordine fisso: installazioni → rimozioni UWP → pulizia → snapshot → Sysprep.Riduce variazioni e incongruenze tra profili.

“Hardening” di preparazione: script di prevenzione

Se prepari spesso immagini, automatizza un controllo pre‑Sysprep che blocchi l’operazione quando esistono UWP per‑utente non allineate all’immagine:

# Test-PreSysprep.ps1 - restituisce codice 0 se "OK", 1 se anomalie
$ErrorActionPreference = "Stop"
$perUser = Get-AppxPackage -AllUsers | Where-Object { -not $_.IsFramework }
$provFam = (Get-AppxProvisionedPackage -Online).PackageName |
  ForEach-Object { if ($ -match '^(?[^]+[^]+)') { $matches.f } } |
  Sort-Object -Unique

$orphans = $perUser | Where-Object { $provFam -notcontains $_.PackageFamilyName }
if ($orphans) {
Write-Host "Rilevate app per-utente non provisionate:" -ForegroundColor Yellow
$orphans | Select Name, PackageFamilyName, UserSid | Format-Table -AutoSize
exit 1
}
Write-Host "Coerenza app OK. Puoi procedere con Sysprep." -ForegroundColor Green
exit 0

Domande frequenti

Rimuovere Microsoft.DesktopAppInstaller (client Winget) è necessario?

No, di solito l’errore è causato da Microsoft.Winget.Source. Mantieni il client se serve, ma assicurati che le sorgenti non restino installate solo per un profilo. In caso di dubbi, rimuovi solo le famiglie legate a “Winget.Source”.

Il comando Remove‑AppxPackage fallisce con “package not found”

È normale se stai puntando a un profilo che non lo ha installato o se l’app è già stata rimossa. Assicurati di usare l’opzione -AllUsers e di passare il nome completo del pacchetto (PackageFullName) recuperato da Get‑AppxPackage.

Devo disattivare i servizi dello Store?

In ambienti chiusi può aiutare temporaneamente disattivare il servizio “Microsoft Store Install Service” durante la finestra di preparazione, per impedire installazioni spurie. Ricorda però di ripristinare la configurazione secondo le policy aziendali.

È sicuro rimuovere qualsiasi app UWP?

No. Evita di rimuovere framework e componenti essenziali (es. VCLibs, .NET UWP framework). Filtra sempre con IsFramework -eq $false quando fai operazioni generiche e lavora per famiglie note (in questo caso “Winget.Source”).

Esempio di integrazione in una Task Sequence (MDT/ConfigMgr)

  1. Step “Run PowerShell Script” → esegui Fix-WingetSysprep.ps1.
  2. Step “Command Line” → DISM /Online /Cleanup-Image /StartComponentCleanup.
  3. Step “Restart Computer”.
  4. Step finale “Sysprep” → Sysprep /oobe /generalize /shutdown.

Questo ordine riduce quasi a zero la probabilità che un aggiornamento dello Store reinserisca l’app tra il fix e la generalizzazione.

Checklist finale prima di Sysprep

  • Eseguita scansione app per‑utente con Get‑AppxPackage -AllUsers.
  • Rimossi i pacchetti Winget.Source per tutti gli utenti (Remove‑AppxPackage).
  • Rimosso l’eventuale Winget dallo strato provisioned (Remove‑AppxProvisionedPackage).
  • Eseguito DISM /StartComponentCleanup.
  • Riavvio completato.
  • Riesecuzione Sysprep /oobe /generalize senza errori.

Riepilogo operativo

L’errore 0x80073cf2 in Windows Server 24H2 durante Sysprep è quasi sempre riconducibile a una UWP installata per un singolo profilo ma non presente nello strato provisioned. Nel caso specifico, Microsoft.Winget.Source è l’innesco più frequente. La soluzione consiste nel rimuovere coerentemente il pacchetto da tutti gli utenti e (se presente) dall’immagine, eseguire una breve pulizia componenti e ripetere la generalizzazione. Le procedure e gli script forniti qui sono stati pensati per essere rapidi, ripetibili e sicuri in contesti enterprise.


Appendice: comandi chiave raccolti

# 1) Scansione pacchetti Winget su tutti gli utenti
Get-AppxPackage -AllUsers | Where-Object {$_.PackageFamilyName -like "Winget"}

2) Rimozione per-utente (tutti gli account)

Get-AppxPackage -Name Microsoft.Winget.Source -AllUsers | Remove-AppxPackage -AllUsers

3) Rimozione dallo strato provisioned

Get-AppxProvisionedPackage -Online |
Where-Object {$_.PackageName -like "Winget"} |
Remove-AppxProvisionedPackage -Online

4) Pulizia componenti

DISM /Online /Cleanup-Image /StartComponentCleanup

5) Sysprep

Sysprep /oobe /generalize /shutdown

Trappole comuni e come evitarle

  • Rimozioni troppo aggressive: eliminare framework UWP può rompere altre app o il client Winget. Limita l’azione alla sola famiglia “Winget.Source”.
  • Connessione Internet attiva: anche pochi minuti online possono introdurre nuove app dello Store. Considera di isolare temporaneamente la VM fino al termine della cattura.
  • Ordine dei passaggi: rimuovere, pulire, riavviare, poi Sysprep. Invertire l’ordine può lasciare residui che riaccendono l’errore.
  • Immagini offline dimenticate: se crei WIM master, pulisci anche il provisioning nell’immagine montata oltre che nel sistema live.

Conclusioni

Allineare lo strato per‑utente con quello provisioned è la chiave per un Sysprep /generalize affidabile su Windows Server 24H2. Intervenire su Microsoft.Winget.Source con i comandi e lo script proposti elimina il principale fattore di blocco (0x80073cf2) e rende la tua pipeline di imaging più pulita e ripetibile. Una volta impostate le policy di prevenzione e la checklist, la correzione diventa un’operazione di pochi minuti e soprattutto prevedibile in ogni ciclo di build.

Tip finale: salva questa pagina nella tua documentazione interna e integra lo script nella sequenza di preparazione: ridurrai drasticamente i tempi di troubleshooting alla prossima release.

Indice