Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La identidad del paquete es un identificador único en el espacio y el tiempo. Al igual que tu ADN te identifica de forma única, la identidad del paquete identifica de forma única a un paquete.
Un paquete tiene un conjunto asociado de bits (archivos, etc.). No hay dos paquetes con la misma identidad y los cambios en los bits asociados a un paquete requieren una identidad diferente.
¿Qué es la identidad del paquete?
Una identidad de paquete es una construcción lógica que identifica de forma única un paquete. La identidad tiene cinco partes:
- Nombre: Este es un nombre elegido por el desarrollador de aplicaciones. Microsoft Store garantiza la exclusividad de todos los nombres de aplicaciones para todos los desarrolladores dentro de la Tienda, pero no se asegura que los nombres sean únicos dentro del ecosistema general.
- Versión: Número de versión del paquete. El desarrollador de aplicaciones puede elegir números de versión arbitrarios, pero debe asegurarse de que los números de versión aumenten con las actualizaciones.
- Arquitectura: arquitectura del procesador al que va dirigido el paquete. La misma aplicación se puede compilar para diferentes arquitecturas de procesador, con cada compilación residiendo en su propio paquete.
-
ResourceId: Cadena elegida por el desarrollador de aplicaciones para identificar de forma única los paquetes de recursos, por ejemplo diferentes idiomas o escalas de presentación diferentes. Los paquetes de recursos suelen ser independientes de la arquitectura. En el caso de los conjuntos de productos, ResourceId es siempre
~. - Editor: nombre del firmante del desarrollador de aplicaciones identificado por su certificado de firma. Esto es teóricamente único para cada desarrollador de aplicaciones, ya que las entidades de certificación de reputación usan nombres e identidades únicos del mundo real para rellenar el campo de nombre del firmante del certificado.
Esta construcción a veces se conoce como la tupla de 5 partes .
Nota:
Paquetes sin firmar (1) todavía requieren un Editor, (2) el Editor debe contener el marcador Unsigned (OID.2.25.311729368913984317654407730594956997722=1), (3) el marcador Unsigned debe ser el último campo de la cadena Editor, y (4) no hay certificado ni firma para un paquete sin firmar.
Límites de campos de identidad del paquete
| Campo | Tipo de dato | Límites | Comentarios |
|---|---|---|---|
| Nombre | Cadena de paquete | Min: 3 Máximo: 50 |
Valores permitidos por Validate API (consulte Package String) |
| Versión | DotQuad | Min: 0.0.0.0 Max: 65535.65535.65535.65535 |
El formato de cadena usa la notación de puntos de base 10, "Major.Minor.Build.Revision" |
| Arquitectura | Enumeración | Mín.: N/A Máximo: N/A |
Los valores permitidos son "neutral", "x86", "x64", "arm64", "x86a64" |
| ResourceId | Cadena de paquete | Min: 0 Máximo: 30 |
Valores permitidos por Validate API (consulte Package String) |
| Publicador | Cuerda | Min: 1 Máximo: 8192 |
Valores permitidos por X.509 |
| ID de Publicador | Cuerda | Min: 13 Máximo: 13 |
Codificada en Base32, variante Crockford, es decir, [a-hjkmnp-tv-z0-9] |
¿Qué es una cadena de paquete?
Una cadena de paquete es una cadena que permite los siguientes caracteres:
- Caracteres de entrada permitidos (subconjunto ASCII)
- Letras mayúsculas (U+0041 a U+005A)
- Letras minúsculas (U+0061 a U+007A)
- Números (U+0030 a U+0039)
- Punto (U+002E)
- Guion (U+002D)
Se prohíbe usar los siguientes valores como cadenas de paquete:
| Condición | Valores prohibidos |
|---|---|
| No puede ser igual que | ".", "..", "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" |
| No puede comenzar por | "con.", "prn.", "aux.", "nul.", "com1.", "com2.", "com3.", "com4.", "com5.", "com6.", "com7.", "com8.", "com9.", "lpt1.", "lpt2.", "lpt3.", "lpt4.", "lpt5.", "lpt6.", "lpt7.", "lpt8.", "lpt9.", "xn--" |
| No puede finalizar con | "." |
| No puede contener | .xn-- |
Una cadena de paquete se debe comparar mediante las API de comparación de cadenas sin distinción entre mayúsculas y minúsculas ordinales (por ejemplo, _wcsicmp).
Los campos name y resourceid de la Identidad del Paquete son cadenas de paquete.
Objeto PackageId
Un PackageId es un objeto que contiene la tupla de 5 partes como campos individuales (Name, Version, Architecture, ResourceId, Publisher).
Nombre completo del paquete
Un nombre completo del paquete es una cadena opaca derivada de la identidad de un paquete (nombre, versión, arquitectura, resourceid, publicador)
<Name>_<Version>_<Architecture>_<ResourceId>_<PublisherId>
Por ejemplo, un nombre completo de paquete para la aplicación Fotos de Windows es "Microsoft.Windows.Photos_2020.20090.1002.0_x64__8wekyb3d8bbwe", donde "Microsoft.Windows.Photos" es el nombre, "2020.20090.1002.0" es el número de versión, "x64" es la arquitectura del procesador de destino, el identificador de recurso está vacío (sin contenido entre los dos últimos caracteres de subrayado) y "8wekyb3d8bbwe" es el identificador de publicador de Microsoft.
El Nombre Completo del Paquete identifica de manera única un paquete o conjunto MSIX . Es un error tener dos paquetes o agrupaciones con contenido diferente, pero con el mismo nombre completo del paquete.
Nota:
MSIX es el nuevo nombre para el término anterior APPX. Para obtener más información, consulte ¿Qué es MSIX?
Nombre de familia del paquete
El nombre de familia de paquete es una cadena opaca derivada de solo dos partes de una identidad del paquete: nombre y editor:
<Name>_<PublisherId>
Por ejemplo, el nombre de familia del paquete de la aplicación Fotos de Windows es "Microsoft.Windows.Photos_8wekyb3d8bbwe", donde "Microsoft.Windows.Photos" es el nombre y "8wekyb3d8bbwe" es el identificador de publicador de Microsoft.
El nombre de familia de paquete se conoce a menudo como "nombre completo del paquete menos la versión".
Nota:
Esto no es estrictamente cierto, ya que el nombre de familia del paquete también carece de arquitectura e identificador de recurso.
Nota:
Los datos y la seguridad suelen tener como ámbito una familia de paquetes. Por ejemplo, sería una mala experiencia si configuraste la aplicación bloc de notas instalada desde un paquete del Bloc de notas 1.0.0.0 para habilitar Wordwrap. A continuación, el Bloc de notas se actualizó posteriormente a la versión 1.0.0.1 y los datos de configuración no se llevaron a la versión más reciente del paquete.
Id. del publicador
Un nombre de familia de paquete es una cadena con el formato :
<name>_<publisherid>
donde id. de publicador tiene algunas propiedades muy específicas:
- Derivado de Publisher
- MinLength = MaxLength = 13 caracteres [tamaño fijo]
- Caracteres permitidos (como regex) = a-hj-km-np-tv-z0-9
- Base-32, variante Crockford, es decir, alfanumérico (A-Z0-9) excepto sin I (isla), L (ella), O (ola) o U (usted)
- Sin distinción entre mayúsculas y minúsculas ordinales para las comparaciones: ABCDEFABCDEFG == abcdefabcdefg
Por lo tanto, nunca verá % : \ / " ? u otros caracteres en un identificador de editor.
Consulte PackageFamilyNameFromId y PackageNameAndPublisherIdFromFamilyName para más información.
El identificador del publicador se conoce a menudo como PublisherId.
¿Por qué existe el identificador del publicador?
El identificador del editor existe porque el editor debe coincidir con el nombre o firmante X.509 del certificado, por lo tanto:
- Puede ser muy grande (longitud <= 8192 caracteres)
- Puede incluir caracteres que son difíciles o restringidos (barra diagonal inversa, etc.).
Estos problemas pueden hacer que algunas cadenas X.509 sean complicadas o imposibles de usar en el sistema de archivos, el registro, las direcciones URL y otros contextos.
¿Cómo se crea un PublisherId?
Use PackageNameAndPublisherIdFromFamilyName para extraer el objeto PublisherId de PackageFamilyName.
Usa PackageIdFromFullName para extraer el PublisherId de un PackageFullName.
Es poco frecuente que necesite crear a PublisherId partir de Publisher, pero se puede hacer con el uso de las API disponibles:
#include <appmodel.h>
HRESULT PublisherIdFromPublisher(
_In_ PCWSTR publisher,
_Out_writes_(PACKAGE_PUBLISHERID_MAX_LENGTH + 1) PWSTR publisherId)
{
PCWSTR name{ L"xyz" };
const size_t nameLength{ ARRAYSIZE(L"xyz") - 1 };
const size_t offsetToPublisherId{ nameLength + 1 }; // xyz_...publisherid...
PACKAGE_ID id{};
id.name = name;
id.publisher = publisher;
WCHAR familyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
UINT32 n{ ARRAYSIZE(familyName) };
RETURN_IF_WIN32_ERROR(PackageFamilyNameFromId(&id, &n, familyName));
RETURN_IF_FAILED(StringCchCopyW(publisherId, PACKAGE_PUBLISHERID_MAX_LENGTH + 1, familyName + offsetToPublisherId));
return S_OK;
}
A continuación se muestra una implementación clásica de Windows C de la misma operación:
#include <appmodel.h>
HRESULT PublisherIdFromPublisher(
_In_ PCWSTR publisher,
_Out_writes_(PACKAGE_PUBLISHERID_MAX_LENGTH + 1) PWSTR publisherId)
{
const WCHAR c_name[]{ L"xyz" };
const UINT32 c_nameLength{ ARRAYSIZE(c_name) - 1 };
PACKAGE_ID id{};
id.name = c_name;
id.publisher = publisher;
WCHAR familyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
UINT32 n{ ARRAYSIZE(familyName) };
RETURN_IF_WIN32_ERROR(PackageFamilyNameFromId(&id, &n, familyName));
RETURN_IF_FAILED(StringCchCopyW(publisherId, PACKAGE_PUBLISHERID_MAX_LENGTH + 1, familyName + c_nameLength + 1));
return S_OK;
}
Esto crea el PublisherId convirtiendo un identificador de paquete en un nombre de familia de paquetes con el formato xyz_<publisherid>resultante. Esta receta es estable y confiable.
Esto solo requiere compilar con appmodel.h desde el SDK y vincularlo con kernel32.lib (o kernelbase.lib, onecore.lib o api-ms-win-appmodel-runtime-l1.lib si usa APIets).
Comprensión de la arquitectura del procesador en la identidad del paquete
Un malentendido común es que significa que Architecture=x64 el paquete solo puede contener código x64. Esto no es cierto. Significa que el paquete funciona en sistemas que admiten código x64 y que las aplicaciones x64 pueden usar. Puedes crear un paquete que contenga solo archivos PDF, pero declararlo con <Identity Architecture=x64...> porque solo está diseñado para instalarse en sistemas compatibles con x64 (por ejemplo, los paquetes x64 solo se pueden instalar en sistemas x64 y (a partir de Windows 11) Arm64, ya que los sistemas Arm86, Arm y Windows 10 Arm64 no admiten x64).
Incluso se entiende menos, Architecture=neutralno significa que el paquete no contenga código ejecutable. Significa que el paquete funciona en todas las arquitecturas. Por ejemplo, podría crear un paquete que contenga una API de cifrado AES escrita en JavaScript, Python, C#, etc., pero el rendimiento no es aceptable en los sistemas Arm64. Por lo tanto, incluye un binario arm64 optimizado e implementa la API para controlarlo:
void Encrypt(...)
{
HANDLE h{};
if (GetCpu() == arm64)
{
h = LoadLibrary(GetCurrentPackagePath() + "\bin\encrypt-arm64.dll")
p = GetProcAddress(h, "Encrypt")
return (*p)(...)
}
else
{
// ...call other implementation...
}
}
O bien, puede crear un paquete neutro con varias variantes:
\
bin\
encrypt-x86.dll
encrypt-x64.dll
encrypt-arm.dll
encrypt-arm64.dll
A continuación, los desarrolladores pueden ejecutar el comando LoadLibrary("bin\encrypt-" + cpu + ".dll") para obtener el binario adecuado para su proceso en tiempo de ejecución.
Normalmente, los paquetes neutros no tienen contenido por arquitectura, pero pueden. Hay un límite en lo que puede hacer (por ejemplo, puede hacer un paquete del Bloc de notas que contenga notepad.exe compilado para x86 + x64 + arm + arm64, pero appxmanifest.xml solo puede declarar <Application Executable=...> que apunte a uno de ellos). Dado que hay agrupaciones que permiten instalar solo los bits necesarios, esto es algo muy poco común. No es ilegal, sólo avanzado y exótico.
Además, Architecture=x86 (o x64|arm|arm64) no significa que el paquete solo contenga código ejecutable para la arquitectura especificada. Es sólo el caso abrumadormente común.
Nota:
Al analizar "código" o "código ejecutable" en este contexto, nos referimos a archivos ejecutables portátiles (PE).
¿La identidad del paquete distingue mayúsculas de minúsculas?
En general, no, pero Publisher distingue mayúsculas de minúsculas.
Los campos restantes (Name, ResourceId, PublisherId, PackageFullName y PackageFamilyName) no lo son. Estos campos conservarán las mayúsculas o minúsculas, pero compararán la falta de distinción entre mayúsculas y minúsculas.
Identidad del paquete frente a identidad de aplicación
La identidad del paquete y la identidad de la aplicación están relacionadas, pero son conceptos distintos. Comprender la diferencia ayuda a evitar una idea errónea común: que una aplicación es su paquete.
- Un paquete es una unidad de distribución e implementación. Puede instalar, actualizar o quitar un paquete en su conjunto.
- Una aplicación es una construcción orientada al usuario: una colección de ventanas, procesos y otros recursos que forman un único programa, independientemente de cómo se implemente (proceso único, varios procesos o incluso varias aplicaciones que comparten un proceso).
Las aplicaciones se distribuyen a través de paquetes, pero no son lo mismo que los paquetes. Un único paquete puede declarar en cualquier lugar de cero a cien aplicaciones, y algunos tipos de paquete (como paquetes de marco y paquetes de recursos) no pueden declarar aplicaciones en absoluto.
ApplicationUserModelID (AUMID)
En el caso de las aplicaciones empaquetadas, la identidad de la aplicación se representa mediante ApplicationUserModelID (también conocido como AppUserModelId o AUMID). Esta cadena permite a Windows asociar windows, procesos y recursos a una aplicación determinada, independientemente de la arquitectura interna de la aplicación.
En otras palabras:
- La identidad del paquete (la tupla de 5 partes descrita anteriormente) identifica de forma única un paquete.
- La identidad de la aplicación (AUMID) identifica de forma única una aplicación dentro de ese paquete.
Windows usa AUMID para razonar sobre las aplicaciones en tiempo de ejecución, por ejemplo, para agrupar windows en la barra de tareas, las notificaciones de ruta y administrar el ciclo de vida de la aplicación. El AUMID se declara en el elemento Application del manifiesto del paquete y se deriva del nombre de familia del paquete y del identificador declarado de la aplicación.
Tip
Para una exploración más profunda de por qué las aplicaciones no son paquetes y cómo AUMID puentea los dos conceptos, consulte Aplicaciones no son paquetes en el blog Inside MSIX.