Microsoft documenta qué es el Package Support Framework. Lo que resulta mucho más difícil de encontrar es lo que de verdad necesita a las cuatro de la tarde de un jueves: la aplicación se empaquetó limpiamente, se instala, arranca, y luego hace algo mal. ¿Qué ajuste cura qué síntoma?

Este es ese mapeo. Da por hecho que el paquete en sí es válido y que el problema es de comportamiento.

Qué hace realmente PSF

El Package Support Framework se sitúa entre una aplicación empaquetada y Windows, e intercepta las llamadas que hace la aplicación. MSIX ejecuta las aplicaciones en un contenedor con escrituras de archivos y de registry redirigidas, y con un directorio de trabajo que no siempre es el que la aplicación supuso. Las aplicaciones más antiguas se escribieron antes de que nada de eso existiera, así que piden cosas de formas que el contenedor responde de otra manera.

Mecánicamente son tres piezas. PSFLauncher32.exe o PSFLauncher64.exe sustituye a su aplicación como atributo Executable del elemento Application en el manifiesto, para que se ejecute primero. Lee config.json desde la raíz del paquete. Después inyecta el runtime de PSF y las DLL de ajuste que haya nombrado en el proceso de la aplicación, y la aplicación arranca detrás de ellas. Si no tiene certeza de la arquitectura de la aplicación, el lanzador de 32 bits funciona en todos los casos.

Cómo se sitúa el Package Support Framework dentro de un paquete MSIX. El shell de Windows inicia PSFLauncher, que lee config punto json desde la raíz del paquete. Ese archivo declara el id de la aplicación, la ruta del ejecutable real, un directorio de trabajo opcional y las DLL de ajuste que se deben cargar. PSFLauncher inyecta el runtime de PSF más los ajustes nombrados en el proceso, y después inicia el ejecutable real. Las llamadas de sistema de archivos, de registry y de carga de bibliotecas de la aplicación pasan por los ajustes inyectados antes de llegar a Windows.

PSFLauncher se ejecuta primero, lee la configuración, inyecta los ajustes y luego cede el paso.

PSF no corrige errores. Traduce suposiciones.

Esa distinción importa, porque le dice cuándo dejar de recurrir a PSF y arreglar el paquete en su lugar.

La tabla de síntomas

La aplicación arranca pero enseguida no encuentra sus propios archivos. Normalmente el directorio de trabajo. La aplicación supuso que arrancaría en su carpeta de instalación y ahora arranca en otro sitio, así que las rutas relativas no resuelven a nada. Cuando no se declara ningún directorio de trabajo, Windows usa System32, que casi nunca es lo que una aplicación heredada esperaba. Esta es la causa individual más común y la más barata de arreglar, porque necesita un valor workingDirectory en config.json y no un ajuste de redirección. Compruébelo antes que nada.

La aplicación arranca, funciona y pierde los ajustes entre sesiones. Redirección de archivos, vía FileRedirectionFixup.dll. La aplicación está escribiendo la configuración junto a su ejecutable, dentro del paquete, donde las escrituras no persisten. La escritura parece tener éxito y se va en silencio a ninguna parte útil. Redirija esas rutas a una ubicación por usuario y los ajustes sobreviven.

La aplicación escribe en su propia carpeta de instalación y luego falla en el siguiente arranque. La misma causa raíz que la anterior, manifestándose de forma más violenta porque el archivo que escribió es uno que necesita. La misma solución. En Process Monitor esto se lee como un resultado de acceso denegado bajo la carpeta del paquete.

Algo falla solo para usuarios estándar y funciona para administradores. Derechos de acceso al registry, normalmente, atendidos por RegLegacyFixups.dll. La aplicación abre una clave de ámbito de máquina y pide más acceso del que necesita, típicamente control total cuando solo lee. Un administrador se sale con la suya y un usuario estándar no. El ajuste reescribe el acceso solicitado en algo que el contenedor sí concede, usando conversiones como Full2RW y RW2R. También puede fingir el borrado de claves que la aplicación insiste en eliminar, y ocultar claves que no deberían verse dentro del contenedor.

Un plug-in, complemento o ejecutable auxiliar no carga. Carga dinámica de bibliotecas, vía DynamicLibraryFixup.dll. La aplicación está cargando algo desde una ruta que el contenedor resuelve de otra manera, o está buscando una dependencia que espera encontrar instalada a nivel de máquina. Su configuración fija forcePackageDllUse y lista cada biblioteca por name junto al filepath relativo al paquete del que debería venir. Este es el ajuste que con más frecuencia revela una dependencia sin empaquetar, que es un problema mayor que una ruta.

Nada evidente, y ningún patrón claro. Trace primero, con TraceFixup.dll. No adivine. El ajuste de trazado registra lo que la aplicación está pidiendo realmente, lo que convierte un juego de adivinanzas en una lista corta. Cada hora dedicada a trazar ahorra varias aplicando ajustes a ciegas y preguntándose cuál ayudó.

Cómo es realmente la configuración

Todo ello vive en un único archivo en la raíz del paquete, y la forma es la misma sea cual sea el ajuste que aplique:

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

Tres cosas merece la pena interiorizar. El id debe coincidir con el atributo Id del elemento Application en el manifiesto, o no pasa nada y no obtiene ningún error útil. El executable bajo processes es normalmente el nombre de archivo sin ruta ni extensión, y se trata como un patrón, así que un valor descuidado atrapa más procesos de los que pretendía. Y applications, processes y fixups son todos arrays, que es como un paquete acaba cargando una pila de ajustes que nadie sabe explicar después.

Trace antes de adivinar

Dos herramientas hacen casi todo el trabajo de diagnóstico, y responden preguntas distintas.

Process Monitor le dice qué ocurrió en la frontera del sistema operativo. Filtre por su ejecutable, excluya los resultados correctos y luego lea la lista de abajo arriba, porque los eventos más recientes están ahí. Busca dos frases: acceso denegado, y ruta o nombre no encontrado. La primera suele apuntar a la redirección o a los derechos de acceso al registry. La segunda apunta al directorio de trabajo.

El ajuste de trazado cuenta la misma historia desde dentro del proceso, y está diseñado para sacar a la luz específicamente los fallos de compatibilidad. Añada la DLL al paquete y un fragmento a config.json:

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

Por defecto el trazado filtra los fallos que considera esperados, que suele ser lo que quiere, porque las aplicaciones intentan de forma rutinaria borrar archivos que nunca estuvieron ahí e ignoran el resultado. El coste es que un fallo genuino puede esconderse dentro del ruido que elimina. Empiece con el valor por defecto, y amplíe a allFailures para el área que sospecha solo una vez que la vista por defecto no haya explicado el comportamiento.

La salida va a un depurador conectado. Si no está depurando, ejecute DebugView de Sysinternals y léala ahí. Ese es todo el flujo de trabajo, y es mucho más rápido que aplicar un ajuste y esperar.

La regla que más tiempo ahorra

Trabaje en este orden:

  1. Reproduzca el fallo con una cuenta de usuario estándar, no con una de administrador. La mitad de los informes del tipo «MSIX lo rompió» son suposiciones de permisos que siempre estuvieron ahí y que antes quedaban enmascaradas.
  2. Trace antes de arreglar. Averigüe qué está pidiendo la aplicación.
  3. Arregle el directorio de trabajo antes de recurrir a cualquier redirección.
  4. Aplique un ajuste cada vez y vuelva a probar. Apilar tres a la vez significa que nunca sabrá cuál hacía falta, y que cargará con los tres para siempre.

Ese último punto importa más de lo que parece. La configuración de ajustes es algo que hereda la siguiente persona. Un paquete que carga tres ajustes donde hacía falta uno es un paquete que nadie se atreverá a tocar dentro de dos años.

Hay una quinta regla que aparece después de unas docenas de paquetes: escriba el porqué, junto al paquete, en una forma que sobreviva a quien lo decidió. Una línea por ajuste, nombrando el síntoma que curó, es suficiente. Sin ella el siguiente revisor tiene que reproducir el fallo original antes de poder quitar nada con seguridad, que es la razón por la que tan pocos ajustes se llegan a quitar.

Cuándo PSF es la respuesta equivocada

PSF es un shim de compatibilidad, y los shims se acumulan. Recurra a otra cosa cuando:

  • La aplicación necesita un driver o un servicio a nivel de sistema. Eso no es un problema de contenedor y ningún ajuste lo resolverá. Probablemente no debería ser MSIX.
  • La aplicación necesita escribir en algún sitio realmente de ámbito de máquina y otras aplicaciones necesitan leerlo. La redirección hace esa escritura invisible para todos los demás, lo que parece un arreglo y no lo es.
  • La aplicación solo falla cuando hay una segunda aplicación en ejecución. La comunicación a través de archivos compartidos, claves de registry compartidas u objetos con nombre no sobrevive limpiamente a la contenerización, y ningún ajuste aislado lo aborda.
  • Va por su cuarto ajuste. A esas alturas la respuesta honesta es que esta aplicación no es hoy un buen candidato a MSIX. MSI o un paquete de PowerShell App Deployment Toolkit la entregará con menos ceremonia, y podrá revisarlo más adelante.

Saber cuándo parar es la diferencia entre una práctica de empaquetado y un montón creciente de shims sin documentar. También afecta a la entrega: un paquete que carga ajustes se comporta de forma distinta bajo App Attach que uno limpio, que es el tema de qué significa PSF para App Attach.

Hacer esto de forma repetida

Diagnosticar una aplicación así es satisfactorio. Hacerlo para cuatrocientas es un problema de plantilla, que es la razón por la que el mapeo tiende a vivir en la cabeza de una sola persona y marcharse cuando ella se va.

A escala de estate el mapeo es además la unidad de trabajo equivocada. Lo que necesita es un veredicto por aplicación: va tal cual, va con ajustes, o todavía no puede moverse. Llegar rápido ahí convierte una conversión de heredado a MSIX de un proyecto abierto en un calendario, y es el marco detrás de nuestra ruta de aplicaciones heredadas.

Dónde encaja EtherApps Forge

EtherApps Forge prepara los ajustes de PSF como parte del empaquetado en lugar de como un proyecto de remediación aparte después, así que la decisión queda registrada con el paquete en vez de recordada. El enfoque más amplio está en nuestra ruta de empaquetado y despliegue MSIX, y la propia preparación de ajustes llegó en EtherApps Forge 1.0.6.

El efecto práctico está en el reparto de veredictos y no en ningún paquete concreto. Las aplicaciones que antes se habrían aparcado porque se portaban mal dentro del contenedor pasan en su lugar a la categoría de «va con ajustes», con el motivo adjunto, para que la siguiente persona que abra el paquete pueda ver qué se decidió y por qué.

EtherApps Forge es una aplicación de escritorio de Windows con una prueba gratuita de 7 días, así que puede probar el bucle de diagnóstico contra una aplicación que ya sabe que es incómoda.

Explore el empaquetado y despliegue MSIX

Empiece por el directorio de trabajo, trace antes de adivinar, y añada un ajuste cada vez.