Microsoft dokumenterar vad Package Support Framework är. Det som är betydligt svårare att hitta är det du faktiskt behöver klockan fyra en torsdag: applikationen paketerades rent, den installeras, den startar, och sedan gör den något fel. Vilken fix botar vilket symtom?

Det här är den kopplingen. Den förutsätter att själva paketet är giltigt och att problemet är beteendemässigt.

Vad PSF faktiskt gör

Package Support Framework sitter mellan en paketerad applikation och Windows, och fångar upp de anrop applikationen gör. MSIX kör applikationer i en container med omdirigerade skrivningar till filer och register, och med en arbetskatalog som inte alltid är den applikationen antog. Äldre applikationer skrevs innan något av det fanns, så de ber om saker på sätt som containern besvarar annorlunda.

Mekaniskt är det tre delar. PSFLauncher32.exe eller PSFLauncher64.exe ersätter din applikation som attributet Executable på elementet Application i paketmanifestet, så att det är det första som körs. Den läser config.json från paketets rot. Sedan injicerar den PSF-runtime och de fix-DLL:er du namngett i applikationsprocessen, och applikationen startar bakom dem. Är du inte säker på din applikations arkitektur fungerar 32-bitarslauncherns i samtliga fall.

Hur Package Support Framework sitter inuti ett MSIX-paket. Windows-skalet startar PSFLauncher, som läser config punkt json från paketets rot. Config punkt json deklarerar applikationens id, den verkliga sökvägen till det körbara programmet och en valfri arbetskatalog, och listar sedan de fix-DLL:er som ska laddas. PSFLauncher injicerar PSF-runtime plus de namngivna fixarna i processen, och startar slutligen applikationens verkliga körbara program. Anrop som applikationen gör till filsystemet, registret och dynamisk biblioteksladdning passerar de injicerade fixarna innan de når Windows.

PSFLauncher körs först, läser konfigurationen, injicerar fixarna och lämnar sedan över till applikationen.

PSF rättar inte buggar. Det översätter antaganden.

Den skillnaden betyder något, för den talar om när du ska sluta gripa efter PSF och i stället laga paketet.

Symtomtabellen

Applikationen startar men hittar omedelbart inte sina egna filer. Vanligen arbetskatalogen. Applikationen antog att den skulle starta i sin installationsmapp och startar nu någon annanstans, så relativa sökvägar leder ingenstans. Konkret: när ingen arbetskatalog deklareras använder Windows katalogen System32, vilket nästan aldrig är vad en äldre applikation förväntade sig. Detta är den vanligaste enskilda orsaken och den billigaste att åtgärda, eftersom den behöver ett workingDirectory-värde i config.json snarare än någon omdirigeringsfix alls. Kontrollera detta före allt annat.

Applikationen startar, körs och tappar inställningar mellan sessioner. Filomdirigering, via FileRedirectionFixup.dll. Applikationen skriver konfiguration bredvid sitt körbara program, inuti paketet, där skrivningar inte består. Skrivningen ser ut att lyckas och försvinner tyst till ingen nytta. Dirigera om de sökvägarna till en plats per användare så överlever inställningarna.

Applikationen skriver till sin egen installationsmapp och misslyckas sedan vid nästa start. Samma grundorsak som ovan, som visar sig våldsammare eftersom filen den skrev är en fil den behöver. Samma åtgärd. I Process Monitor läses detta som ett resultat med nekad åtkomst på en sökväg under paketmappen.

Något misslyckas bara för standardanvändare och fungerar för administratörer. Vanligen registerbehörigheter, hanterade av RegLegacyFixups.dll. Applikationen öppnar en maskinomfattande nyckel och ber om mer åtkomst än den behöver, typiskt fullständig kontroll när den bara läser. En administratör kommer undan med det och en standardanvändare gör det inte. Fixen skriver om den begärda åtkomsten till något containern beviljar, med konverteringar som Full2RW och RW2R, så att anropet lyckas utan att applikationen ändras. Den kan också simulera borttagning av nycklar som applikationen envisas med att ta bort, och dölja nycklar som inte bör vara synliga inuti containern.

Ett insticksprogram, tillägg eller hjälpprogram laddas inte. Dynamisk biblioteksladdning, via DynamicLibraryFixup.dll. Applikationen laddar något från en sökväg som containern löser upp annorlunda, eller letar efter ett beroende den förväntar sig hitta installerat maskinomfattande. Dess konfiguration sätter forcePackageDllUse och listar sedan varje bibliotek med name bredvid den paketrelativa filepath det egentligen ska komma från. Detta är den fix som oftast avslöjar att applikationen har ett opaketerat beroende, vilket är ett annat och större problem än en sökväg.

Inget uppenbart, och inget tydligt mönster. Spåra först, med TraceFixup.dll. Gissa inte. Spårningsfixen registrerar vad applikationen faktiskt ber om, vilket förvandlar en gissningslek till en kort lista. Varje timme lagd på spårning sparar flera timmar på att tillämpa fixar spekulativt och undra vilken som hjälpte.

Hur konfigurationen faktiskt ser ut

Allt bor i en enda fil i paketets rot. Formen är densamma oavsett vilken fix du tillämpar:

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

Tre saker om detta är värda att lägga på minnet. id måste matcha attributet Id på elementet Application i manifestet, annars händer ingenting och du får inget användbart fel. executable under processes är normalt filnamnet med sökväg och filändelse borttagna, och det behandlas som ett mönster, så ett slarvigt värde kan fånga fler processer än du menade. Och applications, processes och fixups är alla arrayer, vilket är så ett enda paket slutar med en trave fixar som ingen kan förklara senare.

Spåra innan du gissar

Två verktyg gör nästan allt diagnostiskt arbete, och de besvarar olika frågor.

Process Monitor berättar vad som hände vid operativsystemets gräns. Filtrera till ditt körbara program, uteslut sedan lyckade resultat, och läs sedan listan nerifrån och upp eftersom de senaste händelserna finns där. Du letar efter två formuleringar: nekad åtkomst, och sökväg eller namn hittades inte. Den första pekar vanligen på omdirigering eller registerbehörigheter. Den andra pekar vanligen på arbetskatalogen.

Spårningsfixen berättar samma historia inifrån processen, med fördelen att den är utformad för att just lyfta fram kompatibilitetsfel. Lägg till DLL:en i paketet och lägg till ett fragment i config.json:

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

Som standard filtrerar spårningen bort fel den betraktar som väntade, vilket vanligen är vad du vill, eftersom applikationer rutinmässigt försöker radera filer som aldrig fanns och struntar i resultatet. Priset för den filtreringen är att ett äkta fel kan gömma sig i bruset den tar bort. Börja därför med standardläget, och vidga till allFailures bara för det område du misstänker när standardvyn inte har förklarat beteendet.

Utdata går till en ansluten felsökare. Felsöker du inte, kör DebugView från Sysinternals och läs det där. Det är hela arbetsflödet, och det är betydligt snabbare än alternativet att tillämpa en fix och hoppas.

Regeln som sparar mest tid

Arbeta i denna ordning:

  1. Reproducera felet med ett standardanvändarkonto, inte ett administratörskonto. Hälften av alla rapporter om att "MSIX gjorde sönder det" är behörighetsantaganden som alltid fanns där och som tidigare maskerades.
  2. Spåra innan du åtgärdar. Ta reda på vad applikationen ber om.
  3. Åtgärda arbetskatalogen innan du griper efter någon omdirigering.
  4. Tillämpa en fix i taget och testa om. Att stapla tre samtidigt betyder att du aldrig får veta vilken som behövdes, och att du bär alla tre för alltid.

Den sista punkten betyder mer än den låter. Fixkonfiguration är något nästa person ärver. Ett paket som bär tre fixar där en behövdes är ett paket ingen vågar röra om två år.

Det finns en femte regel som visar sig först efter några dussin paket: skriv ner varför, bredvid paketet, i en form som överlever personen som fattade beslutet. En rad per fix, med det symtom den botade, räcker. Utan den måste nästa granskare reproducera det ursprungliga felet innan hen tryggt kan ta bort något, vilket är varför så få fixar någonsin tas bort.

När PSF är fel svar

PSF är en kompatibilitetsshim, och shimmar samlas på hög. Grip efter något annat när:

  • Applikationen behöver en drivrutin eller en tjänst på systemnivå. Det är inte ett containerproblem och ingen fix löser det. Det bör förmodligen inte vara MSIX.
  • Applikationen måste skriva någonstans verkligt maskinomfattande och andra applikationer måste läsa det. Omdirigering gör den skrivningen osynlig för alla andra, vilket ser ut som en lösning och inte är det.
  • Applikationen misslyckas bara när en andra applikation körs. Kommunikation mellan applikationer via delade filer, delade registernycklar eller namngivna objekt överlever inte containerisering rent, och ingen enskild fix hanterar det.
  • Du är inne på din fjärde fix. Vid den punkten är det ärliga svaret att den här applikationen inte är en bra MSIX-kandidat i dag. MSI eller ett PowerShell App Deployment Toolkit-paket levererar den med mindre ceremoni, och du kan återkomma senare.

Att veta när man ska sluta är skillnaden mellan en paketeringspraktik och en växande hög odokumenterade shimmar. Det påverkar även leveransen: ett paket som bär fixar beter sig annorlunda under App Attach än ett rent paket, vilket är ämnet för vad PSF betyder för App Attach.

Att göra detta upprepade gånger

Att diagnostisera en applikation på det här sättet är tillfredsställande. Att göra det för fyrahundra är ett bemanningsproblem, vilket är varför kopplingen från symtom till fix tenderar att bo i en persons huvud och försvinna när den personen gör det.

I miljöskala är kopplingen dessutom fel arbetsenhet. Det du behöver är ett utlåtande per applikation: går som den är, går med fixar, eller kan inte flyttas än. Att snabbt nå det utlåtandet är vad som förvandlar en konvertering av äldre appar till MSIX från ett öppet projekt till en tidplan, och det är inramningen vi använder över rutten äldre applikationer.

Var EtherApps Forge passar in

EtherApps Forge förbereder PSF-fixar som en del av paketeringen snarare än som ett separat åtgärdsprojekt efteråt, så att beslutet registreras med paketet i stället för att kommas ihåg. Det bredare angreppssättet finns på vår rutt MSIX-paketering och utrullning, och själva förberedelsen av fixar kom i EtherApps Forge 1.0.6.

Den praktiska effekten ligger i fördelningen av utlåtanden snarare än på något enskilt paket. Applikationer som tidigare hade parkerats för att de misskötte sig inuti containern flyttar i stället till kategorin "går med fixar", med skälet bifogat, så att nästa person som öppnar paketet kan se vad som beslutades och varför. Det betyder mest för de applikationer ingen vill röra.

EtherApps Forge är en Windows-skrivbordsapplikation med en kostnadsfri provperiod på 7 dagar, så du kan testa diagnosslingan mot en applikation du redan vet är besvärlig.

Utforska MSIX-paketering och utrullning

Börja med arbetskatalogen, spåra innan du gissar, och lägg till en fix i taget.