MSIX Lab – Das Package Support Framework (PSF)

Erstellt am 11. April 2019

Thema heute im MSIX-Lab: Ein MSIX-Paket mit Hilfe des Package Support Framework (PSF) analysieren und modifizieren.

Teil 1  – Warum MSIX?

Wir sollten zuerst den Grund kennen, warum Microsoft das MSIX-Package-Format überhaupt entwickelt hat: Man will damit in erster Linie die Anzahl Packages auf dem Microsoft Store erhöhen. Der Ansatz der «Desktop Bridge Applikation», welche noch ein APPX-Paket erzeugt hatte, brachte nicht den gewünschten Erfolg. Zudem wurden die Konvertierungen nicht in der entsprechenden Qualität gemacht und Microsoft hat festgestellt, dass ein neues Format entwickelt werden muss, welche die Qualität der Konvertierung verbessert.

Man kann in der Kürze also sagen, dass MSIX-Packages eine
Erweiterung der APPX-Packages sind.

Der Microsoft Store

Alle Pakete, die im Microsoft Store veröffentlicht werden, müssen den Entwickler-Richtlinien der Universal Windows Platform entsprechen. Und die Liste der Stolpersteine ist beachtlich. Für alle Cases werden auf der oben verlinkten Webseite aber auch gleich Lösungen aufgezeigt.

Kurz einige Beispiele der möglichen Probleme:

  • Your
    application modifies the HKEY_LOCAL_MACHINE (HKLM) registry hive
  • Your
    application writes to the AppData folder or to the registry with the intention
    of sharing data with another app
  • Your
    application writes to the install directory for your app
  • Your
    application uses the Current Working Directory

Problematik einer Konvertierung einer Win32-Applikation zu MSIX

Wie man an den obigen Beispielen sehen kann, ist die
Wahrscheinlichkeit gross, dass das Konvertieren einer Win32-Applikation in ein
MSIX-Package nicht funktioniert. Hat man Zugriff auf die Sourcen der
Applikation, kann man diese entsprechend der Packaging-Richtlinien anpassen.
Wenn diese aber nicht der Fall ist, gibt es ein Open Source Tool von Microsoft,
das helfen kann: Das Package Support Framework oder eben PSF. Dieses Tool hilft
uns, die Fehler in der neu paketierten Win32-Applikation zu korrigieren.

Teil 2 – Fehlersuche im MSIX-Package

Zu Demozwecken habe ich eine kleine Testanwendung, eben eine
Win32-App, programmiert. Die App kann eine Config-Datei lesen und darin
schreiben, in diesem Fall heisst diese app.json und liegt im
Arbeitsverzeichnis. Der Inhalt ist wie folgt:

{ "appname": "PSFDemo", "version": "1.0.0" }

Methode mit Procmon

Das Ziel: Eine Win32-WPF-Anwendung in ein MSIX Package
konvertieren.

Wenn wir das Paket starten, schliesst sich die Applikation aber, ohne jede Fehlermeldung. Dieses Verhalten untersuchen wir mit dem Process Monitor (Procmon), der bei den Sysinternals herunterzuladen ist.

Im Procmon setzen wir folgende Filter und starten den
Prozess mit OK:

Das Ergebnis sieht dann so aus:

Nun filtern wir in der Result-Spalte noch nach «NAME NOT
FOUND» und überprüfen die Dateien. Wir stellen fest: Die app.json-Datei, die in
unserem Package eingebaut wurde, ist hier nicht zu finden.

Mit der Technik aus dem ersten Blogbeitrag suchen wir nach unserem Paket und checken den entsprechenden Ordner, indem wir den Installationspfad öffnen:

Das File ist also definitiv vorhanden.

Es gäbe auch die Option, den Fehler via Visuals Studio (VS) eindeutiger
zu finden. Dazu brauchen wir das die Debugger-Version des Produktes. Unter dem
Menupunkt «Debugging» in VS und navigieren zum entsprechenden Prozess:

Methode mit WER und EventLog

Für Applikationen, die sich scheinbar grundlos schliessen,
gibt es auch das «Windows Error Reporting» (WER). Dieses befindet sich unter
folgendem Pfad: C:\ProgramData\Microsoft\Windows\WER\ReportArchive

Unter diesem Pfad findet sich eine Datei namens Report.wer, welche
mit einem Editor geöffnet werden kann. Der Inhalt des Files zeigt auf, welche
Module geladen worden sind, zeigt uns aber auch nicht direkt den Fehler.

Der zweite Ansatz ist, den EventLog einzusehen. Bei unserem
Beispiel sehen wir unter Application zwei Fehler:

Beim .NET-Fehler sehen wir eine Exception, welche mit dem
FileNotFound-Fehler zutun hat:

Dieser Hinweis zeigt uns, dass wir in unserem Package etwas
ändern müssen. Das heisst, wir können das Paket mit dem PSF korrigieren.

Teil 3 – Pakete mit dem PSF korrigieren

Wir benötigen für den nächsten Schritt das Makeappx.exe, welches im Windows SDK zu finden ist, hier herunterzuladen. Dann den Installer laufen lassen.

Ebenfalls brauchen wir NuGet.exe, um das Package Support Framework (PSF) zu installieren, NuGet.exe gibt es hier herunterzuladen (ich habe mit v4.9.4 gearbeitet). Dann NuGet.exe regulär installieren.

Öffnen wir nun CMD mit Admin-Rechten, um das PSF zu installieren. Dazu folgendes Kommando laufen lassen:

Nuget install Microsoft.PackageSupportFramework

Im Ordner, in dem die Prompt ausgeführt wird, werden die PSF-Files extrahiert (Gelb markiert).

Wechseln wir also zu diesem Folder und öffnen den bin-Folder im PSF:

Das Makeappx-Package, welches wir ebenfalls benötigen, liegt
im Folder des SDK, normalerweise hier zu finden:

„C:\Program Files (x86)\Windows Kits\10\bin\<VERSIONSNUMMER>\x64\makeappx.exe“

In unserem Admin-CMD lassen wir folgendes Kommando laufen:

makeappx unpack -p "<name of the package>.appx" -d "PackageFolder"

Das Ergebnis ist unser Testpaket in entpackter Form.

Im nächsten Schritt kopieren wir aus dem PSF-Bin-Folder (..\Microsoft.PackageSupportFramework.1.0.190325.5\bin)
die Files FileRedirectionFixup32.dll, PsfLauncher32.exe, PsfRunDll32.exe und PsfRuntime32.dll
in den Root-Folder des Pakets.

Im Appxmanifest.xml ersetzen wir die markierte Zeile mit
folgendem Code:

<Application Id=”App” Executable=”PsfLauncher32.exe” EntryPoint=”Windows.FullTrustApplication”>

Davor

Danach

Konfiguration des Packages Support Framework

Dank dem obigen Schritt wird unseres Package nun durch den PsfLauncher32.exe
gestartet an Stelle des ursprünglichen .exe. Nun müssen wir dem PsfLuncher mitteilen,
welche Applikation gestartet werden soll.

Der erste Fix betrifft das WorkingDirectory. Diese
Anpassungen schreiben wir in eine neue config.json-Datei, welche wir im Root
des Packages erstellen.

Das .json File sollte folgenden Inhalt haben:

{
  "applications": [
    {
      "id": "App",
      "executable": "ClearbyteMSIXSample/ClearbyteMSIXSample.exe",
      "workingDirectory": "ClearbyteMSIXSample/"
    }
  ]
}

Fortführende Infos zum Script gibt es hier in der Sektion config.json.

Somit sollte das Lesen der App.json Datei nun funktionieren.

Zum Testen muss die Applikation jetzt wieder zu einem
MSIX-Paket verpackt werden. Mit folgendem Befehl machbar:

makeappx pack /d PackageContents /p PSFSamplePackageFixup.msix

Nicht vergessen, das Paket anschliessend wieder zu signieren (wer den Beitrag verpasst hat, hier spreche ich über das Signieren von Packages).

Laufzeitkorrektur integrieren

Wir brauchen für diesen Schritt wieder das ent-zippte Paket.
Die Json-Datei wird jetzt folgendermassen erweitert und im Paketfolder
abgespeichert:

"applications": [
    {
      "id": "App",
      "executable": "ClearbyteMSIXSample/ClearbyteMSIXSample.exe",
      "workingDirectory": "ClearbyteMSIXSample/"
    }
  ],
  "processes": [
    {
        "executable": "ClearbyteMSIXSample",
        "fixups": [
            {
                "dll": "FileRedirectionFixup32.dll",
                "config": {
                    "redirectedPaths": {
                        "packageRelative": [
                            {
                                "base": "ClearbyteMSIXSample/",
                                "patterns": [
                                    ".*\\.json"
                                ]
                            }
                        ]
                    }
                }
            }
        ]
    }
]
}

Anschliessend das Paket wieder paketieren, signieren und
testen. Läuft!

Happy Packaging!
-Peter

Quellen & Links für diesen Artikel:

https://docs.microsoft.com/de-ch/windows/uwp/porting/package-support-framework

https://developer.microsoft.com/de-de/windows/downloads/windows-10-sdk

https://www.nuget.org/downloads

Erstellt am 11. April 2019

Vielleicht auch interessant…

This Area is Widget-Ready

You can place here any widget you want!

You can also display any layout saved in Divi Library.

Let’s try with contact form: