Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
L'identità del pacchetto è un identificatore univoco nello spazio e nel tempo. Proprio come il DNA identifica in modo univoco l'utente, l'identità del pacchetto identifica in modo univoco un pacchetto.
Un pacchetto ha un set associato di bit (file e così via). Nessun pacchetto ha la stessa identità e le modifiche apportate ai bit associati a un pacchetto richiedono un'identità diversa.
Che cos'è l'identità del pacchetto?
Un'identità del pacchetto è un costrutto logico che identifica in modo univoco un pacchetto. L'identità ha 5 parti:
- Nome: Si tratta di un nome scelto dallo sviluppatore di app. Il Microsoft Store garantisce l'univocità di tutti i nomi delle app tra tutti gli sviluppatori di app nello Store, ma non è garantito che i nomi siano univoci nell'ecosistema generale.
- Versione: Numero di versione del pacchetto. Lo sviluppatore dell'app può scegliere numeri di versione arbitrari, ma deve assicurarsi che i numeri di versione aumentino con gli aggiornamenti.
- Architettura: L'architettura del processore a cui è destinato il pacchetto. La stessa app può essere compilata per diverse architetture di processore, con ciascuna build che risiede nel proprio pacchetto.
-
ResourceId: Stringa scelta dallo sviluppatore dell'app per identificare in modo univoco i pacchetti di risorse, ad esempio lingue diverse o scale di visualizzazione diverse. I pacchetti di risorse sono in genere indipendenti dall'architettura. Per i bundle, il ResourceId è sempre
~. - Publisher: Nome soggetto dello sviluppatore dell'app identificato dal certificato di firma. Ciò è teoricamente univoco per ogni sviluppatore di app, perché le autorità di certificazione affidabili usano nomi e identità reali univoci per popolare il campo del nome soggetto del certificato.
Questo costrutto viene talvolta definito tupla a 5 parti .
Annotazioni
i pacchetti non firmati (1) richiedono comunque un Publisher, (2) il Publisher deve contenere l'indicatore non firmato (OID.2.25.311729368913984317654407730594956997722=1), (3) l'indicatore non firmato deve essere l'ultimo campo nella stringa Publisher e (4) non esiste alcun certificato o firma per un pacchetto non firmato.
Limiti dei campi di identità del pacchetto
| Campo | Tipo di dati | Limiti | Commenti |
|---|---|---|---|
| Nome | Pacchetto Stringa | Min: 3 Max: 50 |
Valori consentiti per l'API di validazione (vedere Package String) |
| Versione | DotQuad | Min: 0.0.0.0 Max: 65535.65535.65535.65535 |
Il formato stringa usa la notazione punteggiata base 10, "Major.Minor.Build.Revision" |
| Architettura | Enumerazione | Min: N/A Max: Non Disponibile |
I valori consentiti sono "neutral", "x86", "x64", "arm64", "x86a64" |
| ResourceId | Pacchetto Stringa | Min: 0 Massimo: 30 |
Valori consentiti per l'API di validazione (vedere Package String) |
| Editore | Stringa | Minimo: 1 Max: 8192 |
Valori consentiti per X.509 |
| ID del Pubblicatore | Stringa | Min: 13 Massimo: 13 |
con codifica Base32, variante Crockford, ad esempio [a-hjkmnp-tv-z0-9] |
Che cos'è una 'Package String'?
Una stringa di pacchetto è una stringa che consente i caratteri seguenti:
- Caratteri di input consentiti (sottogruppo ASCII)
- Lettere maiuscole (U+0041 thru U+005A)
- Lettere minuscole (U+0061 a U+007A)
- Numeri (U+0030 a U+0039)
- Punto (U+002E)
- Trattino (U+002D)
I valori seguenti non possono essere usati come stringhe di pacchetto:
| Condizione | Valori non consentiti |
|---|---|
| Non può essere uguale a | ".", "..", "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" |
| Impossibile iniziare con | "con.", "prn.", "aux.", "nul.", "com1.", "com2.", "com3.", "com4.", "com5.", "com6.", "com7.", "com8.", "com9.", "lpt1.", "lpt2.", "lpt3.", "lpt4.", "lpt5.", "lpt6.", "lpt7.", "lpt8.", "lpt9.", "xn--" |
| Impossibile terminare con | "." |
| Non può contenere | .xn-- |
È necessario confrontare una stringa di pacchetto usando api di confronto tra stringhe ordinali senza distinzione tra maiuscole e minuscole, ad esempio _wcsicmp.
I campi name e resourceid dell'identità del pacchetto sono stringhe del pacchetto.
Oggetto PackageId
Un PackageId è un oggetto contenente la tupla in 5 parti come singoli campi (Name, Version, Architecture, ResourceId, Publisher).
Nome completo del pacchetto
Il nome completo del pacchetto è una stringa opaca derivata da tutte le cinque parti dell'identità di un pacchetto (nome, versione, architettura, ID risorsa, editore)
<Name>_<Version>_<Architecture>_<ResourceId>_<PublisherId>
Ad esempio, un nome completo del pacchetto per l'app Foto di Windows è "Microsoft.Windows.Photos_2020.20090.1002.0_x64__8wekyb3d8bbwe", dove "Microsoft.Windows.Photos" è il nome, "2020.20090.1002.0" è il numero di versione, "x64" è l'architettura del processore di destinazione, l'ID risorsa è vuoto (nessun contenuto tra gli ultimi due caratteri di sottolineatura) e "8wekyb3d8bbwe" è l'ID editore per Microsoft.
Il nome completo del pacchetto identifica in modo univoco un pacchetto MSIX o un bundle. È un errore avere due pacchetti con contenuti diversi ma con lo stesso Nome Completo del Pacchetto.
Annotazioni
MSIX è il nuovo nome per il termine precedente APPX. Per altre informazioni, vedere Che cos'è MSIX?
Nome famiglia di pacchetti
Un
<Name>_<PublisherId>
Ad esempio, il nome della famiglia di pacchetti dell'app Foto di Windows è "Microsoft.Windows.Photos_8wekyb3d8bbwe", dove "Microsoft.Windows.Photos" è il nome e "8wekyb3d8bbwe" è l'ID editore per Microsoft.
Il nome della famiglia di pacchetti viene spesso definito "nome completo del pacchetto senza versione".
Annotazioni
Questo non è strettamente vero, poiché anche il nome della famiglia di pacchetti non dispone dell'architettura e dell'ID risorsa.
Annotazioni
I dati e la sicurezza sono generalmente circoscritti a una famiglia di pacchetti. Ad esempio, sarebbe un'esperienza scarsa se è stata configurata l'app Blocco note installata da un pacchetto blocco note versione 1.0.0.0 per abilitare Wordwrap. Il Blocco note è stato successivamente aggiornato alla versione 1.0.0.1 e i dati di configurazione non sono stati spostati nella versione più recente del pacchetto.
ID server di pubblicazione
Il nome della famiglia di pacchetti è una stringa con il formato seguente:
<name>_<publisherid>
dove l'ID del Publisher ha alcune proprietà molto specifiche:
- Derivato dal server di pubblicazione
- MinLength = MaxLength = 13 caratteri [a dimensione fissa]
- Caratteri consentiti (come regex) = a-hj-km-np-tv-z0-9
- Base-32, Crockford Variant, ovvero alfanumerico (A-Z0-9) tranne I (i), L (elle), O (o) o U (u)
- Senza distinzione tra maiuscole e minuscole per i confronti ordinali --- ABCDEFABCDEFG == abcdefabcdefg
Quindi non vedrai mai % : \ / " ? o altri caratteri in un Id di editore.
Per ulteriori dettagli, vedere PackageFamilyNameFromId e PackageNameAndPublisherIdFromFamilyName.
L'ID di pubblicazione è spesso chiamato PublisherId.
Perché esiste l'ID del publisher?
L'ID del pubblicatore esiste perché il pubblicatore deve corrispondere al nome/firmatario X.509 del certificato, pertanto:
- Può essere molto grande (lunghezza <= 8192 caratteri)
- Può includere caratteri imbarazzanti o limitati (barra rovesciata e così via)
Questi problemi possono rendere alcune stringhe X.509 scomode o impossibili da usare nel file system, nel Registro di sistema, negli URL e in altri contesti.
Come posso creare un PublisherId?
Usare PackageNameAndPublisherIdFromFamilyName per estrarre il PublisherId da un PackageFamilyName.
Usare PackageIdFromFullName per estrarre il PublisherId da un PackageFullName.
È raro che sia necessario creare una PublisherId da Publisher, ma è possibile farlo utilizzando le API disponibili.
#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;
}
Di seguito è riportata un'implementazione classica di Windows C della stessa operazione:
#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;
}
In questo modo viene creato il PublisherId convertendo un ID pacchetto in un Nome di Famiglia del Pacchetto con il formato risultante xyz_<publisherid>. Questa ricetta è stabile e affidabile.
Questo richiede solo la compilazione con appmodel.h dall'SDK e il collegamento con kernel32.lib (o kernelbase.lib, onecore.lib o api-ms-win-appmodel-runtime-l1.lib se si usano APIsets).
Comprendere l'architettura del processore nell'identità del pacchetto
Un malinteso comune è che significa che Architecture=x64 il pacchetto può contenere solo codice x64. Questo non è vero. Significa che il pacchetto funziona nei sistemi che supportano il codice x64 e può essere usato dalle app x64. È possibile creare un pacchetto contenente solo file PDF, ma dichiararlo con <Identity Architecture=x64...> perché è destinato solo a essere installato nei sistemi compatibili con x64 (ad esempio, i pacchetti x64 possono essere installati solo in sistemi x64 e (a partire da Windows 11) Arm64, perché i sistemi x86, Arm e Windows 10 Arm64 non supportano x64.
Ancora più frainteso, Architecture=neutral non significa che il pacchetto non contiene codice eseguibile. Significa che il pacchetto funziona su tutte le architetture. Ad esempio, è possibile creare un pacchetto contenente un'API di crittografia AES scritta in JavaScript, Python, C# e così via, ma le prestazioni non sono accettabili nei sistemi Arm64. Si include quindi un file binario Arm64 ottimizzato e si implementa l'API per gestirla:
void Encrypt(...)
{
HANDLE h{};
if (GetCpu() == arm64)
{
h = LoadLibrary(GetCurrentPackagePath() + "\bin\encrypt-arm64.dll")
p = GetProcAddress(h, "Encrypt")
return (*p)(...)
}
else
{
// ...call other implementation...
}
}
In alternativa, è possibile creare un pacchetto neutro con più varianti:
\
bin\
encrypt-x86.dll
encrypt-x64.dll
encrypt-arm.dll
encrypt-arm64.dll
Gli sviluppatori possono quindi utilizzare LoadLibrary("bin\encrypt-" + cpu + ".dll") per ottenere il file binario appropriato per il processo in fase di esecuzione.
In genere, i pacchetti neutri non hanno contenuto per architettura, ma potrebbero averne. Esistono limiti a ciò che si può fare (ad esempio, è possibile creare un pacchetto del Blocco note contenente notepad.exe compilato per x86 + x64 + arm + arm64, ma appxmanifest.xml può dichiarare solo <Application Executable=...> puntando a uno di essi). Dato che ci sono bundle che consentono di installare solo i bit necessari, questa è una cosa molto rara da fare. Non è illegale, solo avanzato ed esotico.
Inoltre, Architecture=x86 (o x64|arm|arm64) non significa che il pacchetto contenga solo codice eseguibile per l'architettura specificata. È solo il caso comune.
Annotazioni
Quando si parla di "codice" o "codice eseguibile" in questo contesto, si fa riferimento a file eseguibili portabili (PE).
L'identità del pacchetto fa distinzione tra maiuscole e minuscole?
La maggior parte delle volte, no, ma Publisher fa distinzione tra maiuscole e minuscole.
I campi rimanenti (Name, ResourceId, PublisherId, PackageFullName e PackageFamilyName) non sono . Questi campi conserveranno la distinzione tra maiuscole e minuscole, ma verranno confrontati senza tener conto delle maiuscole e minuscole.
Identità del pacchetto e identità dell'applicazione
L'identità del pacchetto e l'identità dell'applicazione sono correlati ma concetti distinti. Comprendere la differenza aiuta a evitare un equivoco comune: ovvero che un'applicazione sia il suo pacchetto.
- Un pacchetto è un'unità di distribuzione e installazione. Installare, aggiornare o rimuovere un pacchetto nel suo complesso.
- Un'applicazione è un costrutto rivolto all'utente , ovvero una raccolta di finestre, processi e altre risorse che insieme formano un singolo programma, indipendentemente dalla modalità di implementazione (singolo processo, più processi o persino più applicazioni che condividono un processo).
Le applicazioni vengono distribuite tramite pacchetti, ma non corrispondono ai pacchetti. Un singolo pacchetto può dichiarare da zero a cento applicazioni, e alcuni tipi di pacchetto (ad esempio pacchetti framework e pacchetti di risorse) non possono dichiarare applicazioni.
ApplicationUserModelID (AUMID)
Per le applicazioni in pacchetto, l'identità dell'applicazione è rappresentata da ApplicationUserModelID (noto anche come AppUserModelId o AUMID). Questa stringa consente Windows di associare windows, processi e risorse a una determinata applicazione, indipendentemente dall'architettura interna dell'applicazione.
In parole semplici:
- L'identità del pacchetto (la tupla in 5 parti descritta in precedenza) identifica in modo univoco un pacchetto.
- L'identità dell'applicazione (AUMID) identifica in modo univoco un'applicazione all'interno di tale pacchetto.
Windows usa l'AUMID per ragionare sulle applicazioni in fase di esecuzione, ad esempio per raggruppare windows nella barra delle applicazioni, indirizzare le notifiche e gestire il ciclo di vita dell'app. L'AUMID viene dichiarato nell'elemento Application del manifesto del pacchetto ed è derivato dal nome della famiglia di pacchetti e dall'ID dichiarato dell'applicazione.
Tip
Per un'esplorazione più approfondita dei motivi per cui le applicazioni non sono pacchetti e il modo in cui AUMID collega i due concetti, vedere Le applicazioni non sono pacchetti nel blog Inside MSIX.