Skip to content

Python Desktop-Tool als MSIX für den Microsoft Store verpacken

2026-04-27

Tags: Tutorial · Python · Windows · MSIX · Verpackung

Einleitung

In einem früeren Artikel habe ich über die Motivation und den Prozess der Entwicklung von RDP Heartbeat geschrieben. Am Ende dieses Beitrags erwähnte ich:

Ich plane, einen Artikel zu schreiben, der die gesamte Pipeline von Python zu MSIX im Detail beschreibt, wenn ich Zeit habe.

Hier ist er.

Offen gesagt: Ein in Python geschriebenes Desktop-Tool in den Microsoft Store zu bringen, ist deutlich aufwendiger als mit C# / WinUI 3. Letzteres erledigt Visual Studio mit wenigen Klicks. Wenn Sie aber wie ich Python verwenden, sieht der Weg so aus:

Python-Quellcode → PyInstaller → EXE → Inno Setup → Installer → MSIX Packaging Tool → MSIX → Store

Jeder Schritt kann Probleme bereiten, aber für jeden gibt es eine Lösung. Dieser Artikel ist die Landkarte und der Leitfaden.

Dieser Artikel verwendet das RDP Heartbeat-Projekt als Beispiel, aber die Methoden und Ansätze gelten für jedes Windows-Tool, das mit Python + Tkinter (oder PyQt, wxPython usw.) geschrieben wurde.

Ein Hinweis: Theoretisch könnte man die von PyInstaller erzeugte EXE möglicherweise direkt mit dem MSIX Packaging Tool konvertieren und Inno Setup überspringen. Wir haben uns entschieden, zunächst Inno Setup zu verwenden, hauptsächlich um die Eigenverteilung zu erleichtern (z.B. eine Setup.exe auf GitHub Releases zum Download anzubieten). Es ist möglicherweise nicht die theoretisch optimale Lösung, aber dieser Weg hat für uns funktioniert, daher teilen wir ihn.

Referenz-Quellcode: Der vollständige Projektcode dieses Artikels ist unter [email protected] verfügbar, einschließlich build_release.py, setup.iss und allen Paketierungskonfigurationen.

Überblick: Die vierteilige Pipeline

Bevor wir beginnen, lassen Sie uns die gesamte Kette betrachten:

  • PyInstaller: .py.exe
  • Inno Setup: .exe → Installer
  • MSIX Packaging Tool: Installer → .msix
  • Microsoft Store: Einreichung

Warum so umständlich? Weil der Microsoft Store letztendlich ein MSIX-Format-Paket benötigt. Das MSIX Packaging Tool funktioniert, indem es einen bereits funktionierenden herkömmlichen Installer „konvertiert" — es überwacht den Installationsprozess, erfasst alle Dateischreibvorgänge, Registrierungsänderungen und Verknüpfungs-Erstellungen und generiert dann automatisch ein MSIX. Daher benötigen Sie zuerst ein sauberes, vollständiges herkömmliches Installationsprogramm.

Anders gesagt: PyInstaller sorgt für „es läuft", Inno Setup für „es installiert", und das MSIX Packaging Tool für „es kann in den Store".

Gehen wir es Schritt für Schritt durch.

Schritt 1: PyInstaller — Python in eine EXE verwandeln

1.1 Projekt vorbereiten

Stellen Sie vor dem Start sicher, dass Ihre Python-Projektstruktur klar ist und der Einstiegspunkt gut definiert ist. Am Beispiel von RDP Heartbeat:

prune-rdp-heartbeat/
├── main.py              # Einstiegsskript
├── heartbeat_window.py  # Kern-Fensterlogik
├── win_utils.py         # Win32 API-Wrapper
├── tray_icon.py         # System-Tray
├── settings_dialog.py   # Einstellungsdialog
├── about_dialog.py      # Info-Dialog
├── config_manager.py    # Konfigurationsverwaltung
├── i18n.py              # Internationalisierung
├── startup.py           # Autostart
├── logger.py            # Protokollierung
├── version.py           # Versionsnummer
├── icon.ico             # Anwendungssymbol
├── icon.png             # Quell-Symbol (für MSIX-Ressourcen)
├── requirements.txt     # Abhängigkeiten
└── packaging/           # MSIX-bezogene Ressourcen (wird später verwendet)

Abhängigkeiten in requirements.txt:

pystray
Pillow
pywin32
customtkinter
packaging

1.2 „Versteckte Abhängigkeiten" von PyInstaller behandeln

PyInstaller erkennt Abhängigkeiten durch statische Analyse, aber einige Bibliotheken (insbesondere pystray, PIL) werden nicht erkannt und müssen manuell deklariert werden:

python
# Wichtige Konfiguration in build_release.py
cmd = [
    sys.executable, "-m", "PyInstaller",
    "--noconsole",           # Kein Konsolenfenster
    "--onefile",             # In eine einzelne EXE packen
    "--name=RDPHeartbeat",
    "--clean",
    "--icon=icon.ico",
    "--add-data=icon.ico;.", # Windows verwendet Semikolons, Linux/macOS Doppelpunkte
    "--hidden-import=PIL._tkinter_finder",
    "--hidden-import=pystray",
    "main.py"
]

Außerdem werden Ressourcendateien (wie Symbole) nach dem Packen in ein temporäres Verzeichnis entpackt, sodass resource_path() für Kompatibilität benötigt wird:

python
# Ansatz in tray_icon.py
def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS   # PyInstallers temporäres Verzeichnis
    except Exception:
        base_path = os.path.abspath(".")  # Entwicklungsmodus: aktuelles Verzeichnis
    return os.path.join(base_path, relative_path)

Alle Ressourcen, die aus dem Dateisystem gelesen werden müssen (Symbole, Schriftarten, Konfigurationsvorlagen usw.), sollten über diese Funktion laufen.

1.3 Ein-Klick-Build-Skript

Verpacken Sie den PyInstaller-Befehl in build_release.py:

python
# Zuerst version.py lesen, um die Versionsnummer zu erhalten
from version import APP_VERSION

def run_build():
    # 0. Vorherige Build-Artefakte bereinigen
    if os.path.exists("build"): shutil.rmtree("build")
    if os.path.exists("dist"):  shutil.rmtree("dist")

    # 1. PyInstaller ausführen
    subprocess.check_call([...])

    # 2. Ausgabe überprüfen
    exe_path = os.path.join("dist", "RDPHeartbeat.exe")
    assert os.path.exists(exe_path), "Build failed!"

Führen Sie python build_release.py aus. Wenn alles glatt geht, erhalten Sie RDPHeartbeat.exe in dist/.

Sie können einen Doppelklick ausführen, um zu überprüfen, ob alles funktioniert.

Schritt 2: Inno Setup — Aus der EXE ein ordentliches Installationsprogramm machen

Das MSIX Packaging Tool benötigt ein Installationsprogramm als Konvertierungsquelle. In der Windows-Ökosystem ist Inno Setup ein kostenloses, ausgereiftes, skriptbasiertes Tool zur Erstellung von Installationsprogrammen.

2.1 Inno Setup installieren

Laden Sie es von jrsoftware.org herunter und installieren Sie es. Es wird empfohlen, auch Inno Script Studio (einen visuellen Editor) zu installieren.

2.2 Installationsskript schreiben

Die Kerndatei setup.iss:

ini
#define MyAppName "RDP Heartbeat"
#define MyAppVersion "1.1.3.0"
#define MyAppPublisher "Prune Lab"
#define MyAppExeName "RDPHeartbeat.exe"

[Setup]
AppId={{DDEC247A-5DC0-4393-BB13-466CCAD7F90B}   ; Eindeutige GUID pro Anwendung
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={autopf}\{#MyAppName}             ; Standardmäßig nach Program Files
ArchitecturesAllowed=x64compatible                ; 64-Bit-Systeme
ArchitecturesInstallIn64BitMode=x64compatible
DisableProgramGroupPage=yes                       ; Seite „Programmgruppe auswählen" überspringen
OutputBaseFilename=RDPHeartbeat_Setup             ; Ausgabedateiname
SolidCompression=yes
WizardStyle=modern                                ; Moderner Assistentenstil
SetupIconFile=icon.ico

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion

[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}";  Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; Flags: unchecked

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,...}"; Flags: nowait postinstall skipifsilent

Einige wichtige Hinweise:

  • AppId muss eindeutig sein: Dies ist die Grundlage für Windows zur Identifizierung der Anwendung. Keine Konflikte mit anderer Software. Inno Setup IDE kann eine GUID mit einem Klick generieren.
  • Keine Registrierungseinträge nötig: Die MSIX-Konvertierung verarbeitet Registrierungsschreibvorgänge während der Installation automatisch, aber unsere Anwendung benötigt sie ohnehin nicht, daher ist es sauberer, sie wegzulassen.

2.3 Automatische Versionsnummern-Synchronisation

Ihre Versionsnummer ist möglicherweise im Python-Code (version.py) definiert, und es gibt auch eine Kopie in setup.iss. Manuelle Synchronisation führt früher oder später zu Fehlern. Fügen Sie daher einen automatischen Patch in build_release.py hinzu:

python
def patch_setup_iss():
    with open("setup.iss", 'r', encoding='utf-8') as f:
        content = f.read()
    content = re.sub(
        r'#define MyAppVersion ".*?"',
        f'#define MyAppVersion "{APP_VERSION}"',
        content
    )
    with open("setup.iss", 'w', encoding='utf-8') as f:
        f.write(content)

Wenn Sie nun python build_release.py ausführen, wird automatisch die neueste Versionsnummer in setup.iss geschrieben und danach PyInstaller ausgeführt.

2.4 Installationsprogramm kompilieren

Öffnen Sie Inno Setup IDE, laden Sie setup.iss und klicken Sie auf Compile. Das Ergebnis ist RDPHeartbeat_Setup.exe.

Überprüfung: Führen Sie das Installationsprogramm auf einer sauberen VM oder einem anderen Computer aus und bestätigen Sie:

  • Es installiert korrekt
  • Das Programm startet
  • Keine Rückstände nach der Deinstallation (Inno Setups Deinstallationsprogramm liegt in {app}\unins000.exe, MSIX packt es mit ein — kein Problem)

Schritt 3: MSIX Packaging Tool — Vom Installer zum Store-Format

Wenn Sie eine Veröffentlichung im Microsoft Store planen, empfiehlt es sich, zuerst die Partner Center-Registrierung abzuschließen und einen App-Namen zu reservieren (siehe Schritt 4), da die in MPT eingegebenen Package Name und Publisher mit den im Store reservierten Informationen übereinstimmen müssen. Wenn Sie nur selbst testen, können Sie die Registrierung überspringen und einen beliebigen Namen verwenden.

3.1 Umgebung vorbereiten

Sie benötigen:

  • MSIX Packaging Tool (Offizielle Dokumentation)
  • Eine saubere Umgebung (VM oder separater Computer empfohlen, da MPT den gesamten Installationsprozess überwacht und andere Programme auf Ihrem System als Rauschen erfasst werden könnten)
  • Signaturzertifikat: In der Testphase können Sie ein selbstsigniertes Zertifikat verwenden. In PowerShell (Administrator) ausführen:
powershell
New-SelfSignedCertificate -Type Custom -Subject "CN=YourName" -KeyUsage DigitalSignature -FriendlyName "Your Cert" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")

Zertifikat exportieren:

powershell
$password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert "Cert:\CurrentUser\My\<Thumbprint>" -FilePath "C:\cert.pfx" -Password $password

Bei der offiziellen Veröffentlichung signiert der Microsoft Store mit seinem eigenen Zertifikat neu, sodass Sie kein Code-Signaturzertifikat kaufen müssen. Wenn Sie jedoch außerhalb des Stores verteilen möchten (z.B. MSIX-Download auf Ihrer eigenen Website), benötigen Sie ein ordnungsgemäßes Code-Signaturzertifikat.

3.2 MSIX Packaging Tool ausführen

  1. MPT öffnen, "Application package""Create a new package" wählen.
  2. Im Schritt "Select environment" die Standardeinstellungen beibehalten und Next klicken.
  3. Wichtiger Schritt: MPT fordert Sie auf, den Pfad zum Installationsprogramm auszuwählen. Wählen Sie die soeben erstellte RDPHeartbeat_Setup.exe.
  4. MPT beginnt mit der Systemüberwachung und startet das Installationsprogramm. Schließen Sie die Installation normal ab — wenn das Installationsprogramm am Ende "Launch RDP Heartbeat" aktiviert hat, ist das auch in Ordnung.
  5. Nach Abschluss der Installation auf "Next" klicken — MPT stoppt die Überwachung.
  6. MPT listet alle erkannten Prozesse auf. Deaktivieren Sie alle, die nicht zu Ihrer App gehören (z.B. Systemprozesse, Antivirus-Updates). Normalerweise behalten Sie nur RDPHeartbeat.exe, unins000.exe usw.
  7. Anwendungsinformationen ausfüllen:
    • Package name: Für den Store den bei Partner Center reservierten Namen (z.B. PruneLab.RDPHeartbeat) eingeben. Für lokale Tests einen beliebigen Namen verwenden, empfohlenes Format: YourName.YourApp.
    • Package display name: Anzeigename der App, z.B. RDP Heartbeat.
    • Publisher display name: Herausgebername, z.B. Prune Lab.
    • Publisher: Für den Store das Publisher-Zertifikat-Subject aus dem Partner Center-Konto (z.B. CN=21C32622-53AF-45A6-8AB1-B35BCD475CAD). Für lokale Tests das Subject des selbstsignierten Zertifikats (z.B. CN=YourName).
    • Version: Wird automatisch aus dem Installer extrahiert.
  8. Ausgabeverzeichnis angeben und MSIX-Paket generieren.

3.3 MSIX-Paket testen

Nachdem die .msix-Datei erstellt wurde, bearbeiten Sie noch nicht das Manifest. Doppelklicken Sie zum Installieren und prüfen Sie, ob alles ordnungsgemäß funktioniert. Bei Verwendung eines selbstsignierten Zertifikats müssen Sie es zuvor in den „Vertrauenswürdige Personen"-Speicher des Systems importieren (siehe den Export-Befehl im vorherigen Abschnitt, Import-PfxCertificate verwenden).

Schritt 4: Beim Microsoft Store einreichen

4.1 Registrierung und Namensreservierung

  1. Ein Microsoft Partner Center-Entwicklerkonto registrieren.
  2. Im Partner Center App-Namen reservieren (Products → New Product → Name eingeben). Nach der Reservierung erhalten Sie Package Name und Publisher-Informationen, die mit der AppxManifest.xml im MSIX-Paket übereinstimmen müssen.

4.2 Einreichungsprozess

  1. Zu Ihrer App → SubmissionsNew submission navigieren.
  2. Felder ausfüllen:
    • Packages: .msix-Datei hochladen
    • Description: App-Beschreibung (mehrsprachig unterstützt, mindestens Englisch und Chinesisch empfohlen)
    • Screenshots: Mindestens ein 1366×768 App-Screenshot
    • Store listing: Symbole, Werbebilder, Funktionsliste
  3. Zur Prüfung einreichen. Die Erstprüfung dauert in der Regel 1-3 Werktage.

Fazit: Lohnt sich dieser Weg?

Wenn Sie mit einem Python-Tool großes Geld verdienen wollen, lautet die Antwort „wahrscheinlich nicht". Eine Neuschreibung mit WinUI 3 / .NET würde ein deutlich besseres Paketierungserlebnis bieten.

Wenn Sie aber wie ich sind — Sie haben bereits ein in Python geschriebenes Tool, das Sie regelmäßig verwenden, und möchten es mit mehr Menschen teilen — dann ist dieser Prozess zwar umständlich, aber er funktioniert zumindest.

Rückblick auf die Pipeline:

SchrittWerkzeugAusgabe
.py → .exePyInstallerEinzelne exe
.exe → InstallerInno SetupSetup.exe
Installer → MSIXMSIX Packaging Tool.msix
EinreichungPartner CenterStore-Eintrag

Hoffentlich hilft dieser Artikel, einige Umwege zu vermeiden. Wenn Sie ebenfalls ein Python-Tool in den Store gebracht haben, freuen wir uns über Austausch auf RDP Heartbeats GitHub.