The module of package reading is tested.

This commit is contained in:
Bruce
2025-10-18 13:58:35 +08:00
parent d6d8fc5b67
commit 53203e0401
20 changed files with 872 additions and 242 deletions

View File

@@ -766,7 +766,7 @@ HLIST_PVOID GetCapabilitiesList (_In_ HPKGREAD hReader)
}
} break;
}
size_t len = sizeof (LIST_PVOID) * sizeof (LPWSTR) * caps.size ();
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
@@ -811,7 +811,7 @@ HLIST_PVOID GetDeviceCapabilitiesList (_In_ HPKGREAD hReader)
}
} break;
}
size_t len = sizeof (LIST_PVOID) * sizeof (LPWSTR) * caps.size ();
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
@@ -831,3 +831,32 @@ void DestroyWStringList (_In_ HLIST_PVOID hList)
}
free (hList);
}
// Prerequisite
BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet)
{
auto ptr = ToPtrPackage (hReader);
if (!ptr) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto pre = reader.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
*pVerRet = VersionClassToStruct (ver);
return !ver.empty ();
} break;
case PackageType::bundle: {
auto br = ptr->bundle_reader ();
CComPtr <IAppxPackageReader> ar;
HRESULT hr = br.random_application_package (&ar);
if (FAILED (hr)) return false;
auto reader = appxreader (ar.p);
auto pre = reader.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
*pVerRet = VersionClassToStruct (ver);
return !ver.empty ();
} break;
}
return FALSE;
}

View File

@@ -12,35 +12,48 @@
#define PKGREAD_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
#ifdef PKGREAD_EXPORTS
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
#else
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
#endif
#ifdef PKGREAD_EXPORTS
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
#else
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
#endif
#else
#define _DEFAULT_INIT_VALUE_(_init_value_)
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
#endif
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
#include <iostream>
#endif
#ifndef _TYPE_STRUCT_VERSION_
#define _TYPE_STRUCT_VERSION_
typedef struct _VERSION
typedef struct _VERSION
{
UINT16 major _DEFAULT_INIT_VALUE_ (0),
minor _DEFAULT_INIT_VALUE_ (0),
build _DEFAULT_INIT_VALUE_ (0),
revision _DEFAULT_INIT_VALUE_ (0);
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
_VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0):
major (major), minor (minor), build (build), revision (revision) {}
friend std::ostream &operator << (std::ostream &o, const _VERSION &v)
{
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
_VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0):
major (major), minor (minor), build (build), revision (revision) {}
#endif
UINT16 major _DEFAULT_INIT_VALUE_ (0),
minor _DEFAULT_INIT_VALUE_ (0),
build _DEFAULT_INIT_VALUE_ (0),
revision _DEFAULT_INIT_VALUE_ (0);
} VERSION;
return o << v.major << "." << v.minor << "." << v.build << "." << v.revision;
}
friend std::wostream &operator << (std::wostream &o, const _VERSION &v)
{
return o << v.major << L"." << v.minor << L"." << v.build << L"." << v.revision;
}
#endif
} VERSION;
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _TYPE_STRUCT_LIST_PVOID_
@@ -106,6 +119,11 @@ extern "C"
// 获取身份信息能获取文本值的项。支持 PKG_IDENTITY_* 前缀的宏 NAME, PUBLISHER, PACKAGEFAMILYNAME, PACKAGEFULLNAME, RESOURCEID。
// 当与 PKG_IDENTITY_BUNDLE_GETAPPXINFO 通过位或结合时,则获取 AppxBundle 中某一个应用包。
PKGREAD_API LPWSTR GetPackageIdentityStringValue (_In_ HPKGREAD hReader, _In_ DWORD dwName);
#define GetPackageIdentityName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_NAME)
#define GetPackageIdentityPublisher(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PUBLISHER)
#define GetPackageIdentityPackageFamilyName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFAMILYNAME)
#define GetPackageIdentityPackageFullName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFULLNAME)
#define GetPackageIdentityResourceId(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_RESOURCEID)
// 获取身份信息。当 bGetSubPkgVer 为真,且打开的包为 AppxBundle 包,返回 AppxBundle 包中的某个应用包的版本号。
PKGREAD_API BOOL GetPackageIdentityVersion (_In_ HPKGREAD hReader, _Out_ VERSION *pVersion, _In_ BOOL bGetSubPkgVer _DEFAULT_INIT_VALUE_FORFUNC_ (0));
// 对于 AppxBundle 包,当传入的值有 PKG_IDENTITY_BUNDLE_GETAPPXINFO则返回一个按位值如 0b0011则意味着支持 x86 和 x64
@@ -123,14 +141,21 @@ extern "C"
// 传入参数参考https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getstringvalue
// 可以使用宏 PKG_PROPERTIES_* 前缀的 DISPLAYNAME, DESCRIPTION, LOGO, PUBLISHER
PKGREAD_API LPWSTR GetPackagePropertiesStringValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
#define GetPackagePropertiesDisplayName(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DISPLAYNAME)
#define GetPackagePropertiesDescription(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DESCRIPTION)
#define GetPackagePropertiesLogo(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_LOGO)
#define GetPackagePropertiesPublisher(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_PUBLISHER)
// 传入参数参考https://learn.microsoft.com/zh-cn/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getboolvalue
// 可以使用宏 PKG_PROPERTIES_* 前缀的 FRAMEWORD, IS_RESOURCE (Windows 8.1 支持)
PKGREAD_API HRESULT GetPackagePropertiesBoolValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet);
#define GetPackagePropertiesIsFramework(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_FRAMEWORD, _Outptr_pRetValue_)
#define GetPackagePropertiesIsResourcePackage(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_IS_RESOURCE, _Outptr_pRetValue_)
// Applications
// 注意:由于读取 Application 在官方 API 中是枚举类型,只能枚举一次。
// 所以请预先安排好需要的信息,并在枚举时进行缓存。
// 添加和删除的请参考这些https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestapplication-getstringvalue
// DLL 本身支持Id, DisplayName, BackgroundColor, ForegroundText, ShortName, Square44x44Logo
// 注一定会保留项AppUserModelID。这是必须项。
PKGREAD_API BOOL AddPackageApplicationItemGetName (_In_ LPCWSTR lpName);
// 移除不需要的信息项名。
PKGREAD_API BOOL RemovePackageApplicationItemGetName (_In_ LPCWSTR lpName);
@@ -220,65 +245,12 @@ extern "C"
#define DestroyCapabilitiesList DestroyWStringList
#define DestroyDeviceCapabilitiesList DestroyWStringList
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
#include <cstdlib>
#include <string>
#include <functional>
class package_info
{
private:
HPKGREAD hReader = nullptr;
std::wstring filepath = L"";
struct deconstr
{
std::function <void ()> endtask = nullptr;
deconstr (std::function <void ()> pf): endtask (pf) {}
~deconstr () { if (endtask) endtask (); }
};
public:
class identity
{
private:
HPKGREAD &hReader;
public:
identity (HPKGREAD hReader): hReader (hReader) {}
std::wstring string_value (DWORD dwName) const
{
LPWSTR lpstr = nullptr;
deconstr rel ([&lpstr] () {
if (lpstr) free (lpstr);
lpstr = nullptr;
});
lpstr = GetPackageIdentityStringValue (hReader, dwName);
return lpstr;
}
VERSION version (bool read_subpkg_ver = false) const
{
VERSION ver;
GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver);
return ver;
}
DWORD architecture () const
{
DWORD dw = 0;
GetPackageIdentityArchitecture (hReader, &dw);
return dw;
}
};
package_info (): hReader (CreatePackageReader ()) {}
~package_info () { DestroyPackageReader (hReader); hReader = nullptr; }
std::wstring file () const { return filepath; }
bool file (const std::wstring &path)
{
return LoadPackageFromFile (hReader, (filepath = path).c_str ());
}
WORD package_type () const { return GetPackageType (hReader); }
bool valid () const { return hReader && IsPackageValid (hReader); }
WORD package_role () const { return GetPackageRole (hReader); }
identity get_identity () const { return identity (hReader); }
};
#endif
// Prerequisite
#define PKG_PREREQUISITE_OS_MIN_VERSION L"OSMinVersion"
#define PKG_PREREQUISITE_OS_MAX_VERSION_TESTED L"OSMaxVersionTested"
PKGREAD_API BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet);
#define GetPackagePrerequisiteOsMinVersion(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MIN_VERSION, _Outptr_pVerRet_)
#define GetPackagePrerequisiteOsMaxVersionTested(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MAX_VERSION_TESTED, _Outptr_pVerRet_)
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
@@ -290,4 +262,332 @@ extern "C"
}
#endif
#endif
#if defined (__cplusplus) && !defined (PKGREAD_EXPORTS)
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <functional>
#include <cstring>
class package_reader
{
private:
HPKGREAD hReader = nullptr;
std::wstring filepath = L"";
struct deconstr
{
std::function <void ()> endtask = nullptr;
deconstr (std::function <void ()> pf): endtask (pf) {}
~deconstr () { if (endtask) endtask (); }
};
public:
class base_subitems
{
protected:
HPKGREAD &hReader;
public:
base_subitems (HPKGREAD &hReader): hReader (hReader) {}
};
class identity: public base_subitems
{
using base = base_subitems;
public:
using base::base;
std::wstring string_value (DWORD dwName) const
{
LPWSTR lpstr = nullptr;
deconstr rel ([&lpstr] () {
if (lpstr) free (lpstr);
lpstr = nullptr;
});
lpstr = GetPackageIdentityStringValue (hReader, dwName);
return lpstr ? lpstr : L"";
}
std::wstring name () const { return string_value (PKG_IDENTITY_NAME); }
std::wstring publisher () const { return string_value (PKG_IDENTITY_PUBLISHER); }
std::wstring package_family_name () const { return string_value (PKG_IDENTITY_PACKAGEFAMILYNAME); }
std::wstring package_full_name () const { return string_value (PKG_IDENTITY_PACKAGEFULLNAME); }
std::wstring resource_id () const { return string_value (PKG_IDENTITY_RESOURCEID); }
VERSION version (bool read_subpkg_ver = false) const { VERSION ver; GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver); return ver; }
DWORD architecture () const { DWORD dw = 0; GetPackageIdentityArchitecture (hReader, &dw); return dw; }
};
class properties: public base_subitems
{
using base = base_subitems;
public:
using base::base;
std::wstring string_value (const std::wstring &swName) const
{
LPWSTR lpstr = nullptr;
deconstr rel ([&lpstr] () {
if (lpstr) free (lpstr);
lpstr = nullptr;
});
lpstr = GetPackagePropertiesStringValue (hReader, swName.c_str ());
return lpstr ? lpstr : L"";
}
bool bool_value (const std::wstring &swName, bool bRetWhenFailed = false) const
{
BOOL ret = FALSE;
HRESULT hr = GetPackagePropertiesBoolValue (hReader, swName.c_str (), &ret);
if (FAILED (hr)) return bRetWhenFailed;
else return ret != FALSE;
}
std::wstring display_name () const { return string_value (PKG_PROPERTIES_DISPLAYNAME); }
std::wstring publisher_display_name () const { return string_value (PKG_PROPERTIES_PUBLISHER); }
std::wstring description () const { return string_value (PKG_PROPERTIES_DESCRIPTION); }
std::wstring logo () const { return string_value (PKG_PROPERTIES_LOGO); }
bool framework () const { return bool_value (PKG_PROPERTIES_FRAMEWORD); }
bool resource_package () const { return bool_value (PKG_PROPERTIES_IS_RESOURCE); }
};
class application: public std::map <std::wstring, std::wstring>
{
using base = std::map <std::wstring, std::wstring>;
public:
using base::base;
std::wstring user_model_id () const { return this->find (L"AppUserModelID")->second; }
friend bool operator == (const application &a1, const application &a2) { return !_wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
friend bool operator != (const application &a1, const application &a2) { return _wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
explicit operator bool () const { return this->user_model_id ().empty (); }
std::wstring &operator [] (const std::wstring &key)
{
auto it = this->find (key);
if (it == this->end ())
{
it = this->insert (std::make_pair (key, L"")).first;
}
return it->second;
}
typename base::iterator find_case_insensitive (const std::wstring &key)
{
for (auto it = this->begin (); it != this->end (); ++it)
{
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
return it;
}
return this->end ();
}
typename base::const_iterator find_case_insensitive (const std::wstring &key) const
{
for (auto it = this->begin (); it != this->end (); ++ it)
{
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
return it;
}
return this->end ();
}
};
class applications
{
private:
HPKGREAD &hReader;
HAPPENUMERATOR hList = nullptr;
public:
applications (HPKGREAD &hReader): hReader (hReader)
{
hList = GetPackageApplications (hReader);
}
~applications ()
{
if (hList) DestroyPackageApplications (hList);
hList = nullptr;
}
size_t get (std::vector <application> &apps)
{
apps.clear ();
if (!hList) return 0;
HLIST_PVOID hMapList = ApplicationsToMap (hList);
deconstr endt ([&hMapList] {
if (hMapList) DestroyApplicationsMap (hMapList);
hMapList = nullptr;
});
if (!hMapList) return 0;
for (size_t i = 0; i < hMapList->dwSize; i ++)
{
HLIST_PVOID &hKeyValues = ((HLIST_PVOID *)hMapList->alpVoid) [i];
application app;
for (size_t j = 0; j < hKeyValues->dwSize; j ++)
{
HPAIR_PVOID &hPair = ((HPAIR_PVOID *)hKeyValues->alpVoid) [j];
LPWSTR lpKey = (LPWSTR)hPair->lpKey;
LPWSTR lpValue = (LPWSTR)hPair->lpValue;
if (!lpKey || !*lpKey) continue;
app [lpKey] = lpValue ? lpValue : L"";
}
apps.push_back (app);
}
return apps.size ();
}
};
class capabilities: public base_subitems
{
using base = base_subitems;
public:
using base::base;
size_t capabilities_name (std::vector <std::wstring> &output) const
{
output.clear ();
HLIST_PVOID hList = GetCapabilitiesList (hReader);
deconstr endt ([&hList] () {
if (hList) DestroyCapabilitiesList (hList);
hList = nullptr;
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
if (!lpstr) continue;
output.push_back (lpstr);
}
return output.size ();
}
size_t device_capabilities (std::vector <std::wstring> &output) const
{
output.clear ();
HLIST_PVOID hList = GetDeviceCapabilitiesList (hReader);
deconstr endt ([&hList] () {
if (hList) DestroyDeviceCapabilitiesList (hList);
hList = nullptr;
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
if (!lpstr) continue;
output.push_back (lpstr);
}
return output.size ();
}
};
struct dependency
{
std::wstring name, publisher;
VERSION vermin;
dependency (const std::wstring &name = L"", const std::wstring &pub = L"", const VERSION &ver = VERSION ()):
name (name), publisher (pub), vermin (ver) {}
};
class dependencies: public base_subitems
{
using base = base_subitems;
public:
using base::base;
size_t get (std::vector <dependency> &output) const
{
auto hList = GetDependencesInfoList (hReader);
deconstr rel ([&hList] () {
DestroyDependencesInfoList (hList);
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
DEPENDENCY_INFO &depinf = ((DEPENDENCY_INFO *)hList->aDepInfo) [i];
if (!depinf.lpName || !*depinf.lpName) continue;
output.push_back (dependency (depinf.lpName, depinf.lpPublisher ? depinf.lpPublisher : L"", depinf.verMin));
}
return output.size ();
}
};
class resources: public base_subitems
{
using base = base_subitems;
public:
using base::base;
size_t languages (std::vector <std::wstring> &langs) const
{
langs.clear ();
auto hList = GetResourcesLanguages (hReader);
deconstr rel ([&hList] () {
if (hList) DestroyResourcesLanguagesList (hList);
hList = nullptr;
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
LPWSTR lpstr = ((LPWSTR *)hList->alpVoid) [i];
if (lpstr && *lpstr) langs.push_back (std::wstring (lpstr));
}
return langs.size ();
}
size_t languages (std::vector <LCID> &langs) const
{
langs.clear ();
auto hList = GetResourcesLanguagesToLcid (hReader);
deconstr rel ([&hList] () {
if (hList) DestroyResourcesLanguagesLcidList (hList);
hList = nullptr;
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
if (hList->aLcid [i]) langs.push_back (hList->aLcid [i]);
}
return langs.size ();
}
size_t scales (std::vector <UINT32> &output) const
{
output.clear ();
auto hList = GetResourcesScales (hReader);
deconstr rel ([&hList] () {
if (hList) DestroyResourcesScalesList (hList);
});
if (!hList) return 0;
for (size_t i = 0; i < hList->dwSize; i ++)
{
UINT32 s = hList->aUI32 [i];
if (s) output.push_back (s);
}
return output.size ();
}
DWORD dx_feature_level () const { return GetResourcesDxFeatureLevels (hReader); }
// 向数组添加的是以 PKG_RESOURCES_DXFEATURE_* 前缀的常量
size_t dx_feature_level (std::vector <DWORD> &ret)
{
DWORD dx = dx_feature_level ();
if (dx & PKG_RESOURCES_DXFEATURE_LEVEL9) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL9);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL10) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL10);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL11) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL11);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL12) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL12);
return ret.size ();
}
};
class prerequisites: public base_subitems
{
using base = base_subitems;
public:
using base::base;
VERSION get_version (const std::wstring &name) const
{
VERSION ver;
GetPackagePrerequisite (hReader, name.c_str (), &ver);
return ver;
}
VERSION os_min_version () const { return get_version (PKG_PREREQUISITE_OS_MIN_VERSION); }
VERSION os_max_version_tested () const { return get_version (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
};
package_reader (): hReader (CreatePackageReader ()) {}
package_reader (const std::wstring &fpath): hReader (CreatePackageReader ())
{
file (fpath);
}
~package_reader () { DestroyPackageReader (hReader); hReader = nullptr; }
std::wstring file () const { return filepath; }
bool file (const std::wstring &path)
{
return LoadPackageFromFile (hReader, (filepath = path).c_str ());
}
// PKGTYPE_* 前缀常量
WORD package_type () const { return GetPackageType (hReader); }
bool valid () const { return hReader && IsPackageValid (hReader); }
// PKGROLE_* 前缀常量
WORD package_role () const { return GetPackageRole (hReader); }
identity get_identity () { return identity (hReader); }
properties get_properties () { return properties (hReader); }
applications get_applications () { return applications (hReader); }
capabilities get_capabilities () { return capabilities (hReader); }
dependencies get_dependencies () { return dependencies (hReader); }
resources get_resources () { return resources (hReader); }
prerequisites get_prerequisites () { return prerequisites (hReader); }
};
#endif
#endif

View File

@@ -512,7 +512,6 @@ namespace appx_info
appx_preq (IAppxManifestReader *ptr = nullptr): com_info (nullptr) { set (ptr); }
version os_min_version () const { return get_version (L"OSMinVersion"); }
version os_max_version_tested () const { return get_version (L"OSMaxVersionTested"); }
private:
version get_version (const std::wstring &name) const
{
UINT64 u64 = 0;
@@ -551,8 +550,10 @@ namespace appx_info
if (lpstr) CoTaskMemFree (lpstr);
lpstr = nullptr;
});
if (SUCCEEDED (p->GetStringValue (it.c_str (), &lpstr))) app [it] = lpstr;
else app [it] = nullptr;
if (std::wnstring (it) == std::wnstring (L"AppUserModelID")) continue;
if (SUCCEEDED (p->GetStringValue (it.c_str (), &lpstr)) && lpstr)
app [it] = lpstr;
else app [it] = std::wstring ();
}
return app;
});

View File

@@ -102,6 +102,7 @@ static CriticalSection g_appcs;
bool PushApplicationAttributeItem (const std::wstring &lpstr)
{
CreateScopedLock (g_appcs);
if (std::wnstring (L"AppUserModelID") == lpstr) return false;
size_t len1 = appitems.size ();
push_unique <std::wstring> (appitems, lpstr, [] (const std::wstring &v1, const std::wstring &v2) -> bool {
return std::wnstring (v1) == std::wnstring (v2);
@@ -111,6 +112,7 @@ bool PushApplicationAttributeItem (const std::wstring &lpstr)
bool RemoveApplicationAttributeItem (const std::wstring &lpstr)
{
CreateScopedLock (g_appcs);
if (std::wnstring (L"AppUserModelID") == lpstr) return false;
auto it = std::find_if (appitems.begin (), appitems.end (), [&] (const std::wstring &v) {
return std::wnstring (v) == std::wnstring (lpstr);
});