Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
tożsamość pakietu jest unikatowym identyfikatorem w przestrzeni i czasie. Tak jak twoje DNA unikatowo cię identyfikuje, tożsamość pakietu jednoznacznie identyfikuje pakiet.
Pakiet ma skojarzony zestaw bitów (plików itp.). Żadne dwa pakiety nie mają tej samej tożsamości, a wszelkie zmiany w bitach skojarzonych z pakietem wymagają innej tożsamości.
Co to jest tożsamość pakietu?
Tożsamość pakietu jest konstrukcją logiczną, jednoznacznie identyfikującą pakiet. Tożsamość ma 5 części:
- Nazwa: Jest to nazwa wybrana przez dewelopera aplikacji. Sklep Microsoft Store wymusza unikatowość wszystkich nazw aplikacji we wszystkich deweloperach aplikacji w Sklepie, ale nazwy nie są unikatowe w ogólnym ekosystemie.
- Wersja: numer wersji pakietu. Deweloper aplikacji może wybrać dowolne numery wersji, ale musi zapewnić zwiększenie liczby wersji wraz z aktualizacjami.
- Architektura: Architektura procesora objęta pakietem. Tę samą aplikację można skompilować dla różnych architektur procesora, a każda kompilacja będzie znajdować się we własnym pakiecie.
-
ResourceId: Ciąg wybrany przez dewelopera aplikacji w celu unikatowego identyfikowania pakietów zasobów, na przykład różnych języków lub różnych skalowania wyświetlania. Pakiety zasobów są zwykle neutralne pod względem architektury. W przypadku pakietów ResourceId jest zawsze
~. - Publisher: Nazwa podmiotu dewelopera aplikacji, jako zidentyfikowana przez ich certyfikat podpisywania. Jest to teoretycznie unikatowe dla każdego dewelopera aplikacji, ponieważ wiarygodne urzędy certyfikacji używają unikatowych nazw i tożsamości rzeczywistych do wypełnienia pola nazwy podmiotu certyfikatu.
Ta konstrukcja czasami jest nazywana 5-elementową krotką.
Uwaga / Notatka
Niepodpisane pakiety (1) nadal wymagają Publisher, (2) Publisher musi zawierać znacznik Niepodpisane (OID.2.25.311729368913984317654407730594956997722=1), (3) znacznik Niepodpisane musi być ostatnim polem w ciągu Publisher, a (4) nie ma certyfikatu ani podpisywania dla Niepodpisanego pakietu.
Limity pól tożsamości pakietu
| (No changes needed) | Typ danych | Limity | Komentarze |
|---|---|---|---|
| Nazwa | Ciąg pakietu | Min: 3 Maksymalna: 50 |
Dozwolone wartości dla API do weryfikacji (zobacz zawartość pakietu) |
| wersja | DotQuad | Min. 0.0.0.0 Maks. 65535.65535.65535.65535 |
Formularz ciągu używa notacji kropkowanej base-10, "Major.Minor.Build".Revision" |
| Architektura | Wyliczenie | Min: brak danych Maks.: Nie dotyczy |
Dozwolone wartości to "neutral", "x86", "x64", "arm", "arm64", "x86a64" |
| Identyfikator zasobu | Ciąg pakietu | Min: 0 Maksymalna: 30 |
Dozwolone wartości dla API do weryfikacji (zobacz zawartość pakietu) |
| Wydawca | Sznurek | Min: 1 Maks.: 8192 |
Dozwolone wartości na X.509 |
| Identyfikator wydawcy | Sznurek | Min: 13 Maksymalna: 13 |
w kodowaniu Base32, wariant Crockford, czyli [a-hjkmnp-tv-z0-9] |
Co to jest ciąg pakietu?
Ciąg pakietowy to ciąg, który zezwala na następujące znaki:
- Dozwolone znaki wejściowe (podzestaw ASCII)
- Wielkie litery (U+0041 do U+005A)
- Małe litery (U+0061 do U+007A)
- Liczby (U+0030 thru U+0039)
- Kropka (U+002E)
- Myślnik (U+002D)
Następujące wartości nie mogą być używane jako ciągi pakietów:
| Warunek | Niedozwolone wartości |
|---|---|
| Nie można równać | ".", "..", "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" |
| Nie można rozpocząć od | "con.", "prn.", "aux.", "nul.", "com1.", "com2.", "com3.", "com4.", "com5.", "com6.", "com7.", "com8.", "com9.", "lpt1.", "lpt2.", "lpt3.", "lpt4.", "lpt5.", "lpt6.", "lpt7.", "lpt8.", "lpt9.", "xn--" |
| Nie można zakończyć z | "." |
| Nie może zawierać | .xn-- |
Ciąg pakietu musi być porównywany z użyciem interfejsów programowania aplikacji do porównania ciągów w sposób porządkowy i bez rozróżniania wielkości liter (np. _wcsicmp).
Pola name i resourceid tożsamości pakietu są ciągami pakietów.
Obiekt PackageId
PackageId jest obiektem zawierającym 5-częściową krotkę podzieloną na pojedyncze pola (Name, Version, Architecture, ResourceId, Publisher).
Pełna nazwa pakietu
Pełna nazwa pakietu jest nieprzezroczystym ciągiem pochodzącym ze wszystkich 5 części tożsamości pakietu (nazwa, wersja, architektura, identyfikator zasobu, wydawca)
<Name>_<Version>_<Architecture>_<ResourceId>_<PublisherId>
Na przykład pełna nazwa pakietu dla aplikacji Windows Photos to "Microsoft.Windows.Photos_2020.20090.1002.0_x64__8wekyb3d8bbwe", gdzie "Microsoft.Windows.Photos" jest nazwą, "2020.20090.1002.0" jest numerem wersji, "x64" jest architekturą procesora docelowego, identyfikator zasobu jest pusty (bez zawartości między dwoma ostatnimi podkreśleniami), a "8wekyb3d8bbwe" jest identyfikatorem wydawcy dla firmy Microsoft.
Pełna nazwa pakietu jednoznacznie identyfikuje pakiet MSIX lub wiązkę. Błędem jest posiadanie dwóch pakietów lub zestawów z inną zawartością, ale z tą samą nazwą pełnego pakietu.
Uwaga / Notatka
MSIX to nowa nazwa poprzedniego terminu APPX. Aby uzyskać więcej informacji, zobacz Co to jest MSIX?
Nazwa rodziny pakietów
Nazwa rodziny pakietów jest nieprzezroczystym ciągiem pochodzącym tylko z dwóch części tożsamości pakietu — nazwa i wydawca :
<Name>_<PublisherId>
Na przykład nazwa rodziny pakietów aplikacji Windows Photos to "Microsoft.Windows.Photos_8wekyb3d8bbwe", gdzie "Microsoft.Windows.Photos" to nazwa, a "8wekyb3d8bbwe" jest identyfikatorem wydawcy dla firmy Microsoft.
Nazwa rodziny pakietów jest często nazywana "pełną nazwą pakietu bez wersji".
Uwaga / Notatka
Nie jest to ściśle prawdziwe, ponieważ nazwa rodziny pakietów również nie zawiera architektury i identyfikatora zasobu.
Uwaga / Notatka
Dane i zabezpieczenia są zwykle ograniczone do rodziny pakietów. Na przykład, byłoby to słabe doświadczenie użytkownika, gdyby skonfigurowano aplikację Notatnik zainstalowaną z pakietu wersji 1.0.0.0 Notatnika, aby włączyć funkcję zawijania wierszy. Następnie Notatnik został zaktualizowany do wersji 1.0.0.1, a dane konfiguracji nie zostały przeniesione do nowszej wersji pakietu.
Identyfikator wydawcy
Nazwa rodziny pakietów to ciąg o formacie:
<name>_<publisherid>
gdzie identyfikator wydawcy ma pewne bardzo specyficzne właściwości:
- Pochodzi z programu Publisher
- MinLength = MaxLength = 13 znaków [stały rozmiar]
- Dozwolone znaki (jako wyrażenie regularne) = a-hj-km-np-tv-z0-9
- Base-32, wariant Crockforda, to jest alfanumeryczne (A-Z0-9) z wyjątkiem I (jak oko), L (jak el), O (jak o) lub U (jak ty)
- Porządkowość bez uwzględniania wielkości liter dla porównań --- ABCDEFABCDEFG == abcdefabcdefg
Więc nigdy nie zobaczysz % : \ / " ? lub inne znaki w identyfikatorze wydawcy.
Aby uzyskać więcej informacji, zobacz PackageFamilyNameFromId i PackageNameAndPublisherIdFromFamilyName.
Identyfikator wydawcy jest często określany jako PublisherId.
Dlaczego istnieje identyfikator wydawcy?
Identyfikator wydawcy istnieje, ponieważ musi odpowiadać nazwie lub podpisowi Twojego certyfikatu X.509, w ten sposób:
- Może to być bardzo duże (długość <= 8192 znaków)
- Może zawierać znaki, które są niezręczne lub ograniczone (ukośnik odwrotny itp.)
Te problemy mogą sprawić, że niektóre ciągi X.509 są niezręczne lub niemożliwe do użycia w systemie plików, rejestrze, adresach URL i innych kontekstach.
Jak utworzyć identyfikator PublisherId?
Użyj PackageNameAndPublisherIdFromFamilyName, aby wyodrębnić PublisherId z PackageFamilyName.
Użyj PackageIdFromFullName, aby wyodrębnić PublisherId z PackageFullName.
Rzadko trzeba utworzyć PublisherId na podstawie Publisher, ale można to zrobić, korzystając z dostępnych interfejsów API.
#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{ name + 1 }; // xyz_...publisherid...
PACKAGE_ID id{};
id.name = name;
id.publisher = publisher;
WCHAR familyName[PACKAGE_PUBLISHERID_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;
}
Poniżej przedstawiono klasyczną implementację systemu Windows C tej samej operacji:
#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_nameForPublisherToPublisherId) - 1 };
PACKAGE_ID id{};
id.name = c_name;
id.publisher = publisher;
WCHAR familyName[PACKAGE_PUBLISHERID_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;
}
Spowoduje to utworzenie identyfikatora wydawcy przez przekonwertowanie identyfikatora pakietu na nazwę rodziny pakietów z wynikowym formatem xyz_<publisherid>. Ten przepis jest stabilny i niezawodny.
Do tego wystarczy skompilować przy użyciu pliku appmodel.h z SDK i połączyć z biblioteką kernel32.lib (lub kernelbase.lib, onecore.lib, albo api-ms-win-appmodel-runtime-l1.lib, jeśli korzystasz z zestawów API).
Zrozumienie architektury procesora w kontekście tożsamości pakietu
Typowym nieporozumieniem jest to, że Architecture=x64 oznacza, że pakiet może zawierać tylko kod x64. To nieprawda. Oznacza to, że pakiet działa w systemach obsługujących kod x64 i może być używany przez aplikacje x64. Można utworzyć pakiet zawierający tylko pliki PDF, ale zadeklarować go za pomocą <Identity Architecture=x64...>, ponieważ jest przeznaczony tylko do zainstalowania w systemach zgodnych z architekturą x64 (np. pakiety x64 można zainstalować tylko w systemach x64 i (począwszy od systemu Windows 11) Arm64, ponieważ systemy x86, Arm i Windows 10 Arm64 nie obsługują architektury x64).
Jeszcze bardziej niezrozumiane, Architecture=neutral nie oznacza, że pakiet nie zawiera kodu wykonywalnego. Oznacza to, że pakiet działa we wszystkich architekturach. Można na przykład utworzyć pakiet zawierający interfejs API szyfrowania AES napisany w języku JavaScript, Python, C# itp., ale wydajność nie jest akceptowalna w systemach Arm64. Dlatego dołączysz zoptymalizowany plik binarny Arm64 i zaimplementujesz interfejs API, aby go obsłużyć:
void Encrypt(...)
{
HANDLE h{};
if (GetCpu() == arm64)
{
h = LoadLibrary(GetCurrentPackagePath() + "\bin\encrypt-arm64.dll")
p = GetProcAddress(h, "Encrypt")
return (*p)(...)
}
else
{
// ...call other implementation...
}
}
Możesz też utworzyć neutralny pakiet z wieloma wariantami:
\
bin\
encrypt-x86.dll
encrypt-x64.dll
encrypt-arm.dll
encrypt-arm64.dll
Deweloperzy mogą następnie LoadLibrary("bin\encrypt-" + cpu + ".dll"), aby uzyskać odpowiedni plik binarny dla swojego procesu w czasie wykonywania.
Zazwyczaj pakiety neutralne nie mają zawartości specyficznej dla architektury, ale mogą ją zawierać. Istnieją ograniczenia dotyczące tego, co można zrobić (np. można utworzyć pakiet Notatnik zawierający notepad.exe skompilowany dla x86 + x64 + arm + arm64, ale appxmanifest.xml może zadeklarować tylko <Application Executable=...> wskazując jeden z nich). Biorąc pod uwagę, że istnieją pakiety, które umożliwiają zainstalowanie tylko potrzebnych bitów, jest to bardzo rzadka rzecz do zrobienia. To nie jest nielegalne, po prostu zaawansowane i egzotyczne.
Ponadto Architecture=x86 (lub x64|arm|arm64) nie oznacza, że pakiet zawiera tylko kod wykonywalny dla określonej architektury. To po prostu w przeważającej mierze typowy przypadek.
Uwaga / Notatka
Podczas omawiania "kodu" lub "kodu wykonywalnego" w tym kontekście odnosimy się do przenośnych plików wykonywalnych (PE).
Czy rozróżnianie wielkości liter jest istotne dla tożsamości pakietu?
Głównie nie, ale Publisher rozróżnia wielkość liter.
Pozostałe pola (Name, ResourceId, PublisherId, PackageFullName i PackageFamilyName) nie są wypełnione. Te pola zachowają wielkość liter, ale będą porównywane bez uwzględniania wielkości liter.
Zobacz także
Windows developer