Microsoft documenteert wat het Package Support Framework is. Wat veel lastiger te vinden is, is wat u om vier uur op een donderdagmiddag echt nodig hebt: de applicatie is netjes verpakt, hij installeert, hij start, en dan doet hij iets fout. Welke fix-up geneest welk symptoom?

Dit is die koppeling. Het gaat ervan uit dat het package zelf geldig is en dat het probleem gedragsmatig is.

Wat PSF echt doet

Het Package Support Framework zit tussen een verpakte applicatie en Windows, en onderschept de aanroepen die de applicatie doet. MSIX draait applicaties in een container met omgeleide schrijfacties naar bestanden en register, en met een werkmap die niet altijd is wat de applicatie aannam. Oudere applicaties zijn geschreven voordat dat alles bestond, dus vragen ze om dingen op een manier die de container anders beantwoordt.

Mechanisch bestaat het uit drie delen. PSFLauncher32.exe of PSFLauncher64.exe vervangt uw applicatie als het Executable-attribuut van het Application-element in het packagemanifest, zodat het als eerste draait. Het leest config.json uit de root van het package. Vervolgens injecteert het de PSF-runtime en de fix-up-DLL's die u hebt genoemd in het applicatieproces, en start de applicatie daarachter. Weet u de architectuur van uw applicatie niet zeker, dan werkt de 32-bits launcher in elk geval.

Hoe het Package Support Framework binnen een MSIX-package zit. De Windows-shell start PSFLauncher, die config punt json uit de root van het package leest. Config punt json declareert de applicatie-id, het echte pad naar het uitvoerbare bestand en een optionele werkmap, en somt daarna de te laden fix-up-DLL's op. PSFLauncher injecteert de PSF-runtime plus de genoemde fix-ups in het proces, en start ten slotte het echte uitvoerbare bestand van de applicatie. Aanroepen die de applicatie doet naar het bestandssysteem, het register en het dynamisch laden van bibliotheken passeren de geïnjecteerde fix-ups voordat ze Windows bereiken.

PSFLauncher draait eerst, leest de configuratie, injecteert de fix-ups en draagt dan over aan de applicatie.

PSF repareert geen bugs. Het vertaalt aannames.

Dat onderscheid telt, want het vertelt u wanneer u moet stoppen met naar PSF grijpen en in plaats daarvan het package moet repareren.

De symptomentabel

De applicatie start maar kan direct zijn eigen bestanden niet vinden. Meestal de werkmap. De applicatie ging ervan uit dat hij in zijn installatiemap zou starten en start nu ergens anders, waardoor relatieve paden nergens naar verwijzen. Concreet: als er geen werkmap is gedeclareerd, gebruikt Windows de map System32, wat vrijwel nooit is wat een legacy applicatie verwachtte. Dit is de meest voorkomende enkele oorzaak en de goedkoopste om te verhelpen, want het vraagt om een workingDirectory-waarde in config.json en helemaal niet om een omleidings-fix-up. Controleer dit vóór al het andere.

De applicatie start, draait en verliest instellingen tussen sessies. Bestandsomleiding, via FileRedirectionFixup.dll. De applicatie schrijft configuratie naast zijn uitvoerbare bestand, binnen het package, waar schrijfacties niet blijven bestaan. De schrijfactie lijkt te slagen en verdwijnt stilletjes naar nergens nuttigs. Leid die paden om naar een locatie per gebruiker en de instellingen overleven.

De applicatie schrijft naar zijn eigen installatiemap en faalt dan bij de volgende start. Dezelfde grondoorzaak als hierboven, die zich heftiger toont omdat het bestand dat hij schreef een bestand is dat hij nodig heeft. Dezelfde oplossing. In Process Monitor leest dit als een resultaat toegang geweigerd op een pad onder de packagemap.

Iets faalt alleen voor standaardgebruikers en werkt voor beheerders. Meestal registertoegangsrechten, afgehandeld door RegLegacyFixups.dll. De applicatie opent een machinebrede sleutel en vraagt meer toegang dan hij nodig heeft, doorgaans volledig beheer terwijl hij alleen maar leest. Een beheerder komt ermee weg en een standaardgebruiker niet. De fix-up herschrijft de gevraagde toegang naar iets dat de container wel toestaat, met conversies zoals Full2RW en RW2R, zodat de aanroep slaagt zonder de applicatie te wijzigen. Hij kan ook het verwijderen van sleutels die de applicatie per se wil weghalen simuleren, en sleutels verbergen die binnen de container niet zichtbaar horen te zijn.

Een plug-in, add-in of hulpprogramma laadt niet. Dynamisch laden van bibliotheken, via DynamicLibraryFixup.dll. De applicatie laadt iets vanaf een pad dat de container anders oplost, of zoekt een dependency waarvan hij verwacht die machinebreed geïnstalleerd te vinden. De configuratie ervan zet forcePackageDllUse en somt daarna elke bibliotheek op met name naast het package-relatieve filepath waar hij eigenlijk vandaan moet komen. Dit is de fix-up die het vaakst onthult dat de applicatie een niet-verpakte dependency heeft, en dat is een ander en groter probleem dan een pad.

Niets voor de hand liggends, en geen duidelijk patroon. Trace eerst, met TraceFixup.dll. Gok niet. De tracing-fix-up registreert waar de applicatie werkelijk om vraagt, wat een gokspel omzet in een korte lijst. Elk uur besteed aan tracen bespaart er meerdere waarin u speculatief fix-ups toepast en zich afvraagt welke hielp.

Hoe de configuratie er echt uitziet

Het staat allemaal in één bestand in de root van het package. De vorm is hetzelfde ongeacht welke fix-up u toepast:

{
  "applications": [
    { "id": "ContosoApp", "executable": "ContosoApp/ContosoApp.exe", "workingDirectory": "ContosoApp/" }
  ],
  "processes": [
    { "executable": "ContosoApp",
      "fixups": [
        { "dll": "FileRedirectionFixup.dll",
          "config": { "redirectedPaths": { "packageRelative": [ { "base": "ContosoApp/", "patterns": [ ".*\\.ini", ".*\\.log" ] } ] } } }
      ] }
  ]
}

Drie dingen hieraan zijn het waard om te onthouden. De id moet overeenkomen met het Id-attribuut van het Application-element in het manifest, anders gebeurt er niets en krijgt u geen bruikbare fout. De executable onder processes is normaal de bestandsnaam zonder pad en extensie, en wordt behandeld als patroon, dus een onzorgvuldige waarde kan meer processen vangen dan u bedoelde. En applications, processes en fixups zijn allemaal arrays, en zo eindigt één package met een stapel fix-ups die later niemand kan verklaren.

Trace voordat u gokt

Twee tools doen bijna al het diagnostische werk, en ze beantwoorden verschillende vragen.

Process Monitor vertelt u wat er gebeurde op de grens met het besturingssysteem. Filter op uw uitvoerbare bestand, sluit vervolgens geslaagde resultaten uit, en lees dan van onderaan de lijst omhoog, want daar staan de meest recente gebeurtenissen. U zoekt twee formuleringen: toegang geweigerd, en pad of naam niet gevonden. De eerste wijst meestal op omleiding of registertoegangsrechten. De tweede wijst meestal op de werkmap.

De tracing-fix-up vertelt u hetzelfde verhaal vanuit het proces zelf, met als voordeel dat hij specifiek is ontworpen om compatibiliteitsfouten zichtbaar te maken. Voeg de DLL toe aan het package en voeg een fragment toe aan config.json:

{ "dll": "TraceFixup.dll", "config": { "traceLevels": { "filesystem": "allFailures" } } }

Standaard filtert de trace fouten weg die hij als verwacht beschouwt, wat meestal is wat u wilt, want applicaties proberen routinematig bestanden te verwijderen die er nooit waren en negeren het resultaat. De prijs van dat filteren is dat een echte fout verborgen kan zitten in de ruis die het weghaalt. Begin dus met de standaard, en verbreed pas naar allFailures voor het gebied dat u verdenkt zodra de standaardweergave het gedrag niet heeft verklaard.

De uitvoer gaat naar een gekoppelde debugger. Debugt u niet, draai dan DebugView van Sysinternals en lees het daar. Dat is de hele workflow, en hij is aanzienlijk sneller dan het alternatief van een fix-up toepassen en hopen.

De regel die de meeste tijd bespaart

Werk in deze volgorde:

  1. Reproduceer de fout met een standaardgebruikersaccount, niet met een beheerdersaccount. De helft van alle meldingen dat "MSIX het kapot heeft gemaakt" zijn rechtenaannames die er altijd al waren en eerder werden gemaskeerd.
  2. Trace voordat u repareert. Zoek uit waar de applicatie om vraagt.
  3. Repareer de werkmap voordat u naar enige omleiding grijpt.
  4. Pas één fix-up tegelijk toe en test opnieuw. Er drie tegelijk opstapelen betekent dat u nooit zult weten welke nodig was, en dat u alle drie voor altijd meedraagt.

Dat laatste punt telt zwaarder dan het klinkt. Fix-up-configuratie is iets dat de volgende persoon erft. Een package met drie fix-ups waar er één nodig was, is een package dat over twee jaar niemand nog durft aan te raken.

Er is een vijfde regel die pas na een paar dozijn packages opduikt: noteer waarom, naast het package, in een vorm die de persoon overleeft die de beslissing nam. Eén regel per fix-up, met het symptoom dat hij genas, is genoeg. Zonder dat moet de volgende beoordelaar de oorspronkelijke fout reproduceren voordat hij veilig iets kan verwijderen, en dat is waarom er zo weinig fix-ups ooit worden verwijderd.

Wanneer PSF het verkeerde antwoord is

PSF is een compatibiliteitsshim, en shims stapelen zich op. Grijp naar iets anders wanneer:

  • De applicatie heeft een driver of een service op systeemniveau nodig. Dat is geen containerprobleem en geen enkele fix-up lost het op. Dit hoort waarschijnlijk geen MSIX te zijn.
  • De applicatie moet echt machinebreed ergens schrijven en andere applicaties moeten dat lezen. Omleiding maakt die schrijfactie onzichtbaar voor iedereen anders, wat op een oplossing lijkt en dat niet is.
  • De applicatie faalt alleen wanneer een tweede applicatie draait. Communicatie tussen applicaties via gedeelde bestanden, gedeelde registersleutels of benoemde objecten overleeft containerisatie niet netjes, en geen enkele fix-up pakt dat aan.
  • U zit op uw vierde fix-up. Op dat punt is het eerlijke antwoord dat deze applicatie vandaag geen goede MSIX-kandidaat is. MSI of een PowerShell App Deployment Toolkit-package levert hem met minder ceremonie, en u kunt er later op terugkomen.

Weten wanneer u moet stoppen is het verschil tussen een packagingpraktijk en een groeiende stapel ongedocumenteerde shims. Het raakt ook de levering: een package met fix-ups gedraagt zich anders onder App Attach dan een schoon package, wat het onderwerp is van wat PSF betekent voor App Attach.

Dit herhaaldelijk doen

Eén applicatie op deze manier diagnosticeren is bevredigend. Het voor vierhonderd doen is een bezettingsprobleem, en daarom leeft de koppeling van symptoom naar fix-up meestal in het hoofd van één persoon en vertrekt ze wanneer die persoon vertrekt.

Op omgevingsschaal is de koppeling ook de verkeerde eenheid van werk. Wat u nodig hebt, is een uitspraak per applicatie: gaat mee zoals hij is, gaat mee met fix-ups, of kan nog niet mee. Snel tot die uitspraak komen is wat een legacy-naar-MSIX-conversie verandert van een open project in een planning, en het is de invalshoek die we gebruiken op de route legacy applicaties.

Waar EtherApps Forge past

EtherApps Forge zet PSF-fix-ups klaar als onderdeel van het packagen in plaats van als een apart herstelproject achteraf, zodat de beslissing bij het package wordt vastgelegd in plaats van onthouden. De bredere aanpak staat op onze route MSIX-packaging en uitrol, en het klaarzetten van fix-ups zelf kwam in EtherApps Forge 1.0.6.

Het praktische effect zit in de verdeling van uitspraken en niet in één enkel package. Applicaties die eerder geparkeerd zouden zijn omdat ze zich misdroegen binnen de container, verhuizen in plaats daarvan naar de categorie "gaat mee met fix-ups", met de reden erbij, zodat de volgende persoon die het package opent kan zien wat er is besloten en waarom. Dat telt het zwaarst bij de applicaties die niemand wil aanraken.

EtherApps Forge is een Windows-desktopapplicatie met een gratis proefperiode van 7 dagen, zodat u de diagnoselus kunt testen op een applicatie waarvan u al weet dat hij lastig is.

Ontdek MSIX-packaging en uitrol

Begin bij de werkmap, trace voordat u gokt, en voeg één fix-up tegelijk toe.