Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Eine standardmäßige ausführbare Desktopdatei , die mit dotnet buildMSBuild, CMake oder einer anderen Toolkette erstellt wurde, weist keine Paketidentität auf. Ohne Identität kann Ihre App nicht viele moderne Windows-APIs verwenden, z. B. Popupbenachrichtigungen, Hintergrundaufgaben, Freigabeziele, Startaufgaben und die App-Daten-APIs.
Geringe Verpackung gewährt Ihrer App Identität, ohne die Binärdateien in ein MSIX-Paket zu verschieben. Sie stellen ein winziges reines Identitätspaket .msix bereit, das nur ein Manifest enthält, und registrieren es unter Verwendung eines externen Speicherorts zusammen mit Ihrer regulär installierten App. Ihr .exe Bleibt genau dort, wo ihr Installationsprogramm es platziert.
In diesem Artikel erstellen Sie das Paket nur mit Identität, betten den Verweis auf die Identität in Ihre App ein, registrieren das Paket zum lokalen Testen und integrieren die Registrierung in Ihr Installationsprogramm.
Voraussetzungen
Windows 10, Version 2004 (Build 19041) oder höher. Geringe Pakete basieren auf
uap10:AllowExternalContent, was Build 19041 oder höher erfordert.Ein Terminal, z. B. Windows PowerShell oder Windows-Terminal, um die Befehle in diesem Artikel auszuführen.
Die winapp CLI. Installieren oder aktualisieren Sie es über Ihr Terminal mit Winget:
winget install Microsoft.winappcli --source wingetEin Codesignaturzertifikat, das auf dem Zielcomputer als vertrauenswürdig eingestuft wird. Generieren Sie für lokale Tests mit
winapp cert generateein Entwicklungszertifikat und vertrauen Sie ihm. Signieren Sie Produktionspakete mit einem Zertifikat, dessen Betreff dem ManifestPublisherentspricht.
Funktionsweise der sparsamen Verpackung
Sparse Packaging ist das Produktionsgegenstück zu winapp create-debug-identity, das nur zum Debuggen während der Entwicklung dient. Sie gewährt eine Paketidentität für eine App, die Sie mit Ihrem eigenen Installationsprogramm verteilen, sodass die App identitätsbezogene Windows APIs aufrufen kann.
Die CLI-Schritte in diesem Artikel entsprechen den ersten drei Schritten des Workflows Identität für nicht paketierte Apps gewähren:
| Schritt | Befehl | Result |
|---|---|---|
| 1. Erstellen des Identitätsmanifests | winapp init --exe <exe> --sparse |
sparse/appxmanifest.xml + sparse/Assets/ |
| 2. Erstellen und Signieren des Identitätspakets | winapp pack <appxmanifest.xml> --cert <pfx> |
<PackageName>.identity.msix |
| 3. Einbetten der Identität in die App | winapp embed-identity <exe> |
<msix> Element im Fusionsmanifest der Exe |
Schritt 4 dieses Workflows – Registrieren und Aufheben der Registrierung des Pakets – liegt in der Verantwortung Ihres Installers; Schritt 5 ist optional. In diesem Artikel wird erläutert, wie Sie sich für lokale Tests registrieren und die Registrierung in Ihr Installationsprogramm integrieren.
Verwenden Sie sparsame Verpackungen, wenn:
- Sie verfügen bereits über ein ausgereiftes Installationsprogramm (Inno Setup, WiX, NSIS, MSI) und möchten nicht zur Verteilung zu MSIX wechseln, sie benötigen jedoch identitätsgesteuerte Windows APIs.
- Ihre App muss auf einem Pfad oder mit einem Layout installieren, das MSIX nicht zulässt.
- Sie möchten eine minimale, additive Änderung: Halten Sie ihren vorhandenen Installationsablauf, und fügen Sie einen
.msixRegistrierungsschritt hinzu.
Wenn Sie neu beginnen und als MSIX verteilen können, ist eine vollständige verpackte App (winapp init + winapp pack <folder>) einfacher.
Ein vollständiges End-to-End-Beispiel (eine WPF-App mit einem Inno Setup-Installationsprogramm) finden Sie im Beispiel für sparse-app.
Die folgenden Beispiele setzen voraus, dass unter ./bin/Release/net8.0-windows/MyApp.exe eine erstellte ausführbare Datei vorhanden ist.
Sparse-Identity-Manifest erstellen
Generieren Sie das Sparse-Manifest aus Ihrer erstellten ausführbaren Datei:
winapp init --exe ./bin/Release/net8.0-windows/MyApp.exe --sparse
Dieser Befehl leitet den Paketnamen, den Herausgeber, die Version und die Beschreibung aus den Dateiversionsinformationen der EXE ab und fordert Sie auf, sie zu akzeptieren oder zu überschreiben. Fügen Sie --use-defaults (oder --no-prompt) hinzu, um die Abfragen in CI zu überspringen, und --name oder --publisher, um bestimmte Werte zu überschreiben:
winapp init --exe ./bin/Release/net8.0-windows/MyApp.exe --sparse --use-defaults `
--name "Contoso.MyApp" --publisher "CN=Contoso"
Standardmäßig schreibt der Befehl Folgendes in einen dedizierten sparse/ Ordner im aktuellen Verzeichnis (Außerkraftsetzung mit --output-dir):
-
appxmanifest.xml— ein minimales Manifest mit<uap10:AllowExternalContent>true</uap10:AllowExternalContent>(einem Element unter<Properties>),ProcessorArchitecture="neutral", einerwin32App-Anwendung und dem inExecutableeingetragenen EXE-Namen. -
Assets/— visuelle Platzhalter-Ressourcen, die wenn möglich aus dem Symbol der EXE-Datei extrahiert werden.
Das Manifest und Assets/ sind Eingaben zur Build-Zeit, die von winapp pack und winapp embed-identity verwendet werden. Nichts liest sie zur Laufzeit neben der EXE, sodass ein dedizierter, versionsverwalteter sparse/-Ordner sie aus einem Build-Ausgabeverzeichnis (wie bin/) heraushält, das bei einem Clean oder Rebuild gelöscht würde.
winapp pack und winapp embed-identity durchsuchen sparse/ automatisch, sodass Sie den Pfad nur selten angeben müssen.
Note
Der reduzierte Initialisierungsablauf lässt bewusst die gesamte SDK- und Paketinstallation aus. Pakete, die nur Identitäten enthalten, haben keine SDK-Abhängigkeiten.
Wenn im Zielverzeichnis bereits ein appxmanifest.xml vorhanden ist, bricht init ab, anstatt es (und sein Assets/) zu überschreiben. Führen Sie den Befehl mit --force erneut aus, um es neu zu generieren. Stellen Sie sicher, dass das Publisher im generierten Manifest mit dem Zertifikat übereinstimmt, mit dem Sie signieren – bearbeiten Sie appxmanifest.xml bei Bedarf oder übergeben Sie --publisher, wenn Sie es generieren.
Erstellen und Signieren des Identitätspakets
Verweisen Sie winapp pack auf das Sparse-Manifest (eine Datei, kein Ordner):
winapp pack ./sparse/appxmanifest.xml --cert ./devcert.pfx
Da das Manifest winapp pack deklariert, erstellt AllowExternalContent ein ausschließlich für die Identität bestimmtes .msix, das nur das Manifest enthält – keine Binärdateien, keine Assets. Gleichgeordnete Dateien neben dem Manifest werden ignoriert, sodass das Paket niemals Ihre Objekte oder Binärdateien enthält. Die Ausgabe wird standardmäßig in <PackageName>.identity.msix im aktuellen Verzeichnis gespeichert; verwenden Sie --output, um dies zu ändern. Das Signieren erfolgt nur, wenn Sie vorbeigehen --cert (oder --generate-cert).
Einbetten der Identität in Ihre App
Betten Sie das <msix> Element ein, damit Windows die ausgeführte EXE mit dem Identitätspaket verbindet. Sie können die erstellte Binärdatei direkt ändern oder ein versioniertes Begleitmanifest verwalten.
So ändern Sie die integrierte Binärdatei direkt:
# EXE mode — modify the built binary in place
winapp embed-identity ./bin/Release/net8.0-windows/MyApp.exe
Um das Side-by-Side-Manifest als eingecheckte Datei beizubehalten und neu zu erstellen:
# XML mode — update an external SxS manifest, then rebuild your app
winapp embed-identity ./app.manifest
Im XML-Modus wird das <msix> Element in das Zielmanifest eingefügt (oder ersetzt). Verweisen Sie auf dieses Manifest aus Ihrem Projekt (für .NET, festlegen<ApplicationManifest>app.manifest</ApplicationManifest>), und erstellen Sie es neu, damit das Element in die exe eingebettet ist.
Beide Modi ermitteln die Identität aus einem spärlichen appxmanifest.xml. Wenn Sie weglassen --manifest, sucht winapp zuerst in einem sparse/ Ordner neben dem Ziel und dann im aktuellen Verzeichnis. Übergeben Sie --manifest, um an anderer Stelle zu verweisen.
Note
Der EXE-Modus schreibt die Binärdatei neu, wodurch alle vorhandenen Authenticode-Signaturen ungültig werden. Signieren Sie die EXE-Datei (z. B. winapp sign ./MyApp.exe --cert ./devcert.pfx --cert-password <certificate-password>) erneut, bevor Sie sie verteilen.
Registrieren des Identitätspakets für lokale Tests
Die Registrierung ist Teil von Schritt 4 des Workflows. In der Produktion führt Ihr Installationsprogramm diesen Schritt aus; führen Sie sie selbst aus, um lokale Tests durchzuführen.
Stellen Sie vor der Registrierung sicher, dass das Zertifikat, mit dem Sie das Paket signiert haben, auf diesem Computer als vertrauenswürdig eingestuft ist – Windows ein von einem nicht vertrauenswürdigen Zertifikat signiertes Identitätspaket ablehnt. Öffnen Sie PowerShell oder Windows-Terminal für die lokale Entwicklung als Administrator, navigieren Sie zum Arbeitsverzeichnis, und installieren Sie das generierte PFX-Zertifikat im Speicher für vertrauenswürdige Personen des lokalen Computers:
winapp cert install .\devcert.pfx
Warning
Vertrauen Sie einem Zertifikat nur für die lokale Entwicklung auf Ihrem eigenen Computer. Verteilen Sie kein selbstsigniertes Entwicklungszertifikat auf Rechnern von Benutzern, und vertrauen Sie nicht darauf. Signieren Sie Produktionspakete mit einem Zertifikat von einer vertrauenswürdigen Zertifizierungsstelle, deren Betreff dem Manifest Publisherentspricht.
Die Logos des Manifests werden zur Laufzeit vom externen Speicherort aufgelöst, nicht aus dem reinen Identitätseintrag .msix. Kopieren Sie die generierten Ressourcen neben Ihre .exe-Datei (den externen Speicherort), bevor Sie die Registrierung durchführen — andernfalls registriert Windows ein Layout, dem jedes Logo fehlt, auf das das Manifest verweist:
# Copy the generated assets into the external location (beside your exe)
Copy-Item ./sparse/Assets -Destination .\bin\Release\net8.0-windows\Assets -Recurse -Force
Registrieren Sie das Identitätspaket für diesen Ordner (den externen Speicherort):
Add-AppxPackage -Path .\MyApp.identity.msix `
-ExternalLocation (Resolve-Path .\bin\Release\net8.0-windows)
Starten Sie die App, und bestätigen Sie, dass die Identität vorhanden ist. Gibt z. B. den Paketfamiliennamen zurück, Windows.ApplicationModel.Package.Current.Id.FamilyName anstatt sie zurückzuwerfen.
Aufheben der Registrierung des Pakets
Die Abmeldung ist auch Teil von Schritt 4 im Workflow. Entfernen Sie die Registrierung, wenn Sie lokale Tests abgeschlossen haben oder wenn das Installationsprogramm die App deinstalliert.
Suchen Sie das Paket mit Get-AppxPackage und leiten Sie es an Remove-AppxPackage weiter:
Get-AppxPackage -Name MyApp | Remove-AppxPackage
Ersetzen Sie MyApp durch Ihren Paketnamen. Wenn Sie den genauen Namen nicht sicher sind, stimmt die Liste zuerst mit Get-AppxPackage -Name *MyApp*.
Integrieren der Registrierung in Ihr Installationsprogramm
Registrierung und Aufhebung der Registrierung sind der Auftrag des Installers, und das Muster ist für alle Installationstools identisch:
-
Installieren: Kopieren Sie die App-Binärdateien, den
Assets/-Ordner und.msixin das Installationsverzeichnis und führen Sie dannAdd-AppxPackage -Path "<install-dir>\MyApp.identity.msix" -ExternalLocation "<install-dir>"aus. -
Deinstallieren: Vor dem Löschen von Dateien ausführen
Remove-AppxPackage <full-package-name>.
Da Ressourcen vom externen Speicherort aufgelöst werden, stellen Sie den Assets/ Ordner immer zusammen mit Ihrer App im Layout bereit, das das Manifest erwartet.
Warning
Das Installationsverzeichnis wird zur Installationszeit aufgelöst und kann Zeichen (z. B. ein einfaches Anführungszeichen) enthalten, die aus einem PowerShell-Zeichenfolgenliteral herausbrechen. Maskieren oder überprüfen Sie den Pfad immer, bevor Sie ihn in eine -Command-Zeichenfolge interpolieren. Bevorzugen Sie die Übergabe von Pfaden als Argumente an ein -File-Skript anstelle der Inline-Interpolation in -Command. Die nachstehenden Ausschnitte "WiX" und "NSIS" gehen von einem vertrauenswürdigen Installationspfad aus, während im Inno-Setupbeispiel die sichere Flucht veranschaulicht wird.
Inno Setup
Erstellen Sie die PowerShell-Argumente in einer Funktion [Code], damit der Installationspfad der Runtime für das in einfache Anführungszeichen gesetzte PowerShell-Literal maskiert wird (ein Installationsverzeichnis, das ein ' enthält, darf keine Skriptinjektion ermöglichen):
[Files]
Source: "dist\*"; DestDir: "{app}"; Flags: recursesubdirs
Source: "MyApp.identity.msix"; DestDir: "{app}"
[Run]
Filename: "powershell.exe"; Parameters: "{code:RegisterParams}"; Flags: runhidden
[UninstallRun]
Filename: "powershell.exe"; \
Parameters: "-NoProfile -ExecutionPolicy Bypass -Command ""Get-AppxPackage -Name 'MyApp' | Remove-AppxPackage"""; \
Flags: runhidden
[Code]
function EscapePSLiteral(const Value: string): string;
var S: string;
begin
S := Value; StringChange(S, '''', ''''''); Result := S;
end;
function RegisterParams(Param: string): string;
var AppDir: string;
begin
AppDir := ExpandConstant('{app}');
{ -ErrorAction Stop + try/catch make a registration failure terminating, so powershell.exe
exits nonzero and the AfterInstall callback (see the full sample) can abort with rollback. }
Result := '-NoProfile -ExecutionPolicy Bypass -Command "try { Add-AppxPackage -Path ''' +
EscapePSLiteral(AppDir + '\MyApp.identity.msix') +
''' -ExternalLocation ''' + EscapePSLiteral(AppDir) + ''' -ErrorAction Stop } catch { Write-Error $_; exit 1 }"';
end;
Ein vollständiges, funktionsfähiges setup.issBeispiel finden Sie im sparse-app-Beispiel.
Registrierungsskript für WiX und NSIS
In den WiX- und NSIS-Beispielen wird über register-sparse.ps1 bis -File ein kleines Skript aufgerufen, sodass der Installationspfad als Parameter übergeben wird (PowerShell behandelt ihn als Daten), anstatt in einen -Command-String interpoliert zu werden. Dadurch wird die Skripteinfügung über ein gestaltetes Installationsverzeichnis vermieden (z. B. ein Ordnername, der ein Anführungszeichen enthält oder $(...)):
# register-sparse.ps1 — ship this alongside your installer
param(
[Parameter(Mandatory)] [string] $MsixPath,
[Parameter(Mandatory)] [string] $ExternalLocation,
[Parameter(Mandatory)] [string] $PackageName
)
$ErrorActionPreference = 'Stop'
try {
# Add-AppxPackage emits NON-terminating errors by default, so a failure would otherwise leave
# the process exit code at 0 and let the installer complete without identity. Try the add
# directly first: a fresh install or a version-bumped upgrade registers/updates in place
# without touching any existing registration. -ErrorAction Stop + the outer trap make a real
# failure terminating so the installer (WiX Return="check" / NSIS) sees it.
try {
Add-AppxPackage -Path $MsixPath -ExternalLocation $ExternalLocation -ErrorAction Stop
} catch {
# Only ONE failure is safe to resolve by unregister+retry: the exact same version is already
# registered (HRESULT 0x80073CFB, ERROR_PACKAGE_ALREADY_EXISTS — "already installed,
# reinstallation blocked"), which Add-AppxPackage rejects. Re-throw everything else
# (untrusted/corrupt .msix, unsupported OS, ...) so a bad new package can NEVER unregister a
# working prior registration and strip the installed app of the identity it already had.
if ($_.Exception.HResult -ne 0x80073CFB) { throw }
Get-AppxPackage -Name $PackageName | Remove-AppxPackage -ErrorAction SilentlyContinue
Add-AppxPackage -Path $MsixPath -ExternalLocation $ExternalLocation -ErrorAction Stop
}
} catch {
Write-Error $_
exit 1
}
WiX (v3)
Pro Benutzer registrieren (Impersonate="yes"), da Add-AppxPackage das Paket für das Konto registriert, das es ausführt. Eine verzögerte Aktion mit Impersonate="no" wird als LocalSystem ausgeführt, wodurch dem installierenden Benutzer keine Identität bereitgestellt wird (und dies häufig abgelehnt wird). Führen Sie bei einer MSI-Installation pro Computer die Registrierung im Kontext des aufrufenden Benutzers aus, damit sie auf diesen Benutzer angewendet wird.
Eine verzögerte benutzerdefinierte Aktion kann INSTALLFOLDER nicht direkt lesen (verzögerte Aktionen werden in einem Kontext ohne Zugriff auf Eigenschaften ausgeführt), und die bloße Deklaration der Aktion führt nicht zu ihrer Ausführung. Schleusen Sie die Pfade über CustomActionData ein — eine unmittelbare Aktion vom Typ 51, deren Property-Name dem Id der verzögerten Aktion entspricht —, und planen Sie beide nach InstallFiles:
<!-- Immediate: stash the command line (with the resolved paths) into the deferred action's
CustomActionData. Windows Installer copies the value of the property named the same as a
deferred action into that action's CustomActionData. -->
<CustomAction Id="SetRegisterSparseCmd" Property="RegisterSparse" Execute="immediate"
Value="powershell.exe -NoProfile -ExecutionPolicy Bypass -File "[INSTALLFOLDER]register-sparse.ps1" -MsixPath "[INSTALLFOLDER]MyApp.identity.msix" -ExternalLocation "[INSTALLFOLDER]" -PackageName "MyPackageIdentityName"" />
<!-- Deferred + impersonated: CAQuietExec reads its command line from CustomActionData when run
deferred, so it registers the package for the invoking user. Return="check" fails the
install if registration fails. -->
<CustomAction Id="RegisterSparse" BinaryKey="WixCA" DllEntry="CAQuietExec"
Execute="deferred" Impersonate="yes" Return="check" />
<InstallExecuteSequence>
<Custom Action="SetRegisterSparseCmd" After="InstallFiles">NOT Installed</Custom>
<Custom Action="RegisterSparse" After="SetRegisterSparseCmd">NOT Installed</Custom>
</InstallExecuteSequence>
CAQuietExec ist in der WiX-Util-Erweiterung (WixUtilExtension) enthalten; verweisen Sie auf sie, damit die WixCA-Binärdatei verfügbar ist.
Note
Eine einzelne imitierte Aktion registriert die Identität nur für den Benutzer, der das Installationsprogramm ausführt. Um eine computerweite Installation für jeden Benutzer bereitzustellen, registrieren Sie sie stattdessen beim ersten Start pro Benutzer, oder verwenden Sie einen Bereitstellungsmechanismus wie Add-AppxProvisionedPackage.
NSIS
Section
# Capture the PowerShell exit code and abort if registration failed. register-sparse.ps1 exits
# nonzero on failure (it sets $ErrorActionPreference='Stop' and traps), so without this check the
# installer would complete even though the app has no identity.
ExecWait 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$INSTDIR\register-sparse.ps1" -MsixPath "$INSTDIR\MyApp.identity.msix" -ExternalLocation "$INSTDIR" -PackageName "MyPackageIdentityName"' $0
IntCmp $0 0 +2
Abort "Registering the sparse identity package failed (exit code $0). The app requires package identity."
SectionEnd
Häufige Probleme beheben
Package.Current löst zur Laufzeit keine Identität aus oder meldet keine Identität
- Das Identitätspaket ist nicht registriert, oder im Fusion-Manifest der EXE-Datei fehlt das Element
<msix>. Führen Sie die Ausführung erneut aus (und erstellen Sie neu, wenn Sie den XML-Moduswinapp embed-identityverwenden), und registrieren Sie sich dann erneut beiAdd-AppxPackage -ExternalLocation. - Das
<msix packageName>,publisher, undapplicationIdin der exe muss genau mit der Identität des registrierten Pakets übereinstimmen.
Objekte oder Logos werden nicht angezeigt
- Stellen Sie sicher, dass der
Assets/Ordner am externen Speicherort mit denselben relativen Pfaden bereitgestellt wird, die das Manifest erwartet. Ressourcen werden vom externen Speicherort aufgelöst, nicht vom.msix.
Add-AppxPackage schlägt mit einem Signatur- oder Vertrauensfehler fehl.
- Das
.msixMuss von einem Zertifikat signiert werden, das auf dem Computer vertrauenswürdig ist und dessen Betreff mit dem ManifestPublisherübereinstimmt. Generieren und vertrauen Sie für lokale Tests ein Entwicklungszertifikat mitwinapp cert generate, und stellen Sie sicher, dass das Manifest mit dem ZertifikatPublisherübereinstimmt.
MakeAppx meldet, dass eine win32App entryPoint nicht deklarieren darf
- Eine spärliche
win32AppAnwendung darf nicht deklarierenEntryPoint. Von ihnen generiertewinapp init --sparseManifeste sind bereits korrekt. Entfernen Sie jedesEntryPointAttribut, wenn Sie das Manifest manuell bearbeitet haben.
Die Eingabe ist eine Datei, aber kein Sparse-Manifest
-
winapp pack <file>akzeptiert nur ein Manifest, das<uap10:AllowExternalContent>true</uap10:AllowExternalContent>deklariert. Generieren Sie einen mitwinapp init --exe <exe> --sparse, oder übergeben Sie einen Eingabeordner, um einen vollständigen MSIX zu erstellen.
Verwandte Inhalte
Windows developer