Update Shell

This commit is contained in:
Bruce
2025-11-26 07:44:51 +08:00
parent ae3771bfdb
commit a70b0547bd
45 changed files with 5781 additions and 253 deletions

Binary file not shown.

View File

@@ -96,6 +96,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;$(OutDir)pkgread.lib;$(OutDir)pkgmgr.lib;$(OutDir)certmgr.lib;$(OutDir)priformatcli.lib;$(OutDir)notice.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Manifest>
<AdditionalManifestFiles>app.manifest</AdditionalManifestFiles>
@@ -132,6 +133,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;$(OutDir)pkgread.lib;$(OutDir)pkgmgr.lib;$(OutDir)certmgr.lib;$(OutDir)priformatcli.lib;$(OutDir)notice.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Manifest>
<AdditionalManifestFiles>app.manifest</AdditionalManifestFiles>
@@ -167,6 +169,7 @@
<ClInclude Include="filepath.h" />
<ClInclude Include="ieshell.h" />
<ClInclude Include="initfile.h" />
<ClInclude Include="localeex.h" />
<ClInclude Include="module.h" />
<ClInclude Include="mpstr.h" />
<ClInclude Include="nstring.h" />
@@ -190,6 +193,7 @@
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="appinstaller.rc" />

View File

@@ -87,6 +87,9 @@
<ClInclude Include="..\priformatcli\priformatcli.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="localeex.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">

View File

@@ -12,6 +12,7 @@
#include "nstring.h"
#include "priformatcli.h"
#include "pkgread.h"
static std::string ws2utf8 (const std::wstring &ws)
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
@@ -47,6 +48,39 @@ struct pkginfo
VERSION version, realver;
DWORD architecture;
} identity;
// x86: 0
// x64: 9
// Arm: 5
// Neutral: 11
// Arm64: 12
std::set <WORD> get_architectures () const
{
std::set <WORD> ret;
switch (type)
{
case PKGTYPE_APPX: {
switch (identity.architecture)
{
case PKG_ARCHITECTURE_X86: ret.insert (0); break;
case PKG_ARCHITECTURE_X64: ret.insert (9); break;
case PKG_ARCHITECTURE_ARM: ret.insert (5); break;
case PKG_ARCHITECTURE_ARM64: ret.insert (12); break;
case PKG_ARCHITECTURE_NEUTRAL: ret.insert (11); break;
}
} break;
case PKGTYPE_BUNDLE: {
if (identity.architecture & PKG_ARCHITECTURE_X86) ret.insert (0);
if (identity.architecture & PKG_ARCHITECTURE_X64) ret.insert (9);
if (identity.architecture & PKG_ARCHITECTURE_ARM) ret.insert (5);
if (identity.architecture & PKG_ARCHITECTURE_ARM64) ret.insert (12);
// 由于架构历史发展原因:这样做是对的。
if (identity.architecture & (PKG_ARCHITECTURE_X86 | PKG_ARCHITECTURE_X64 | PKG_ARCHITECTURE_ARM))
{ ret.clear (); ret.insert (11); }
if (identity.architecture & PKG_ARCHITECTURE_NEUTRAL) { ret.clear (); ret.insert (11); }
}
}
return ret;
}
struct
{
std::wstring display_name;
@@ -91,6 +125,7 @@ struct pkginfo
struct
{
VERSION os_min_version, os_max_version_tested;
std::wstring os_min_version_description, os_max_version_tested_description;
} prerequisites;
static pkginfo parse (const std::wstring &filepath)
{
@@ -128,6 +163,8 @@ struct pkginfo
auto prer = pread.get_prerequisites ();
pkg.prerequisites.os_min_version = prer.os_min_version ();
pkg.prerequisites.os_max_version_tested = prer.os_max_version_tested ();
pkg.prerequisites.os_min_version_description = prer.os_min_version_description ();
pkg.prerequisites.os_max_version_tested_description = prer.os_max_version_tested_description ();
}
{
auto apps = pread.get_applications ();
@@ -299,10 +336,12 @@ struct pkginfo
Value obj (kObjectType);
obj.AddMember ("os_min_version", ver_to_json (prerequisites.os_min_version, alloc), alloc);
obj.AddMember ("os_max_version_tested", ver_to_json (prerequisites.os_max_version_tested, alloc), alloc);
obj.AddMember ("os_min_version_description", Value (ws2utf8 (prerequisites.os_min_version_description).c_str (), alloc), alloc);
obj.AddMember ("os_max_version_tested_description", Value (ws2utf8 (prerequisites.os_max_version_tested_description).c_str (), alloc), alloc);
doc.AddMember ("prerequisites", obj, alloc);
}
StringBuffer buffer;
Writer<StringBuffer> writer (buffer);
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;

View File

@@ -7,6 +7,7 @@
#include "rctools.h"
#include "filepath.h"
#include "raii.h"
#include "resource.h"
// 允许忽视命令行前缀。如当命令行前缀为“-”"/"时,且开启此项,则输入“-args”与"/args"和"args" 是等效的
#define CMDARG_IGNOREPREFIXS 0b001
@@ -24,12 +25,14 @@ struct cmdarg
std::wstring description; // 描述,用于生成帮助文本
DWORD flags; // 标志
};
#define CMDARG_PREFIXS_DEFAULT {L"-", L"/"}
#define CMDARG_PREFIXS_DEFAULT {L"/", L"-"}
#define CMDARG_POSTFIXS_DEFAULT {}
#define CMDARG_HELP {CMDARG_PREFIXS_DEFAULT, {L"?", L"help", L"h"}, CMDARG_PREFIXS_DEFAULT, L"help", GetRCStringSW (IDS_CMDPARAM_HELP), CMDARG_IGNOREPREFIXS}
std::vector <cmdarg> g_argslist = {
{CMDARG_PREFIXS_DEFAULT, {L"silent", L"quiet", L"passive"}, CMDARG_POSTFIXS_DEFAULT, L"silent", GetRCStringSW (0), CMDARG_IGNOREPREFIXS},
{CMDARG_PREFIXS_DEFAULT, {L"verysilent", L"veryquiet"}, CMDARG_POSTFIXS_DEFAULT, L"verysilent", GetRCStringSW (0), CMDARG_IGNOREPREFIXS},
{CMDARG_PREFIXS_DEFAULT, {L"multiple", L"filelist"}, {L"="}, L"multiple", GetRCStringSW (0), CMDARG_IGNOREPREFIXS | CMDARG_ENABLEPARAMS}
CMDARG_HELP,
{CMDARG_PREFIXS_DEFAULT, {L"silent", L"quiet", L"passive"}, CMDARG_POSTFIXS_DEFAULT, L"silent", GetRCStringSW (IDS_CMDPARAM_SILENT), CMDARG_IGNOREPREFIXS},
{CMDARG_PREFIXS_DEFAULT, {L"verysilent", L"veryquiet"}, CMDARG_POSTFIXS_DEFAULT, L"verysilent", GetRCStringSW (IDS_CMDPARAM_VERYSILENT), CMDARG_IGNOREPREFIXS},
{CMDARG_PREFIXS_DEFAULT, {L"multiple", L"filelist"}, {L"="}, L"multiple", GetRCStringSW (IDS_CMDPARAM_MULTIPLE), CMDARG_IGNOREPREFIXS | CMDARG_ENABLEPARAMS}
};
bool IsFile (const std::wstring &path)
{

248
appinstaller/localeex.h Normal file
View File

@@ -0,0 +1,248 @@
#pragma once
#include <WinNls.h>
#include <string>
#include "typestrans.h"
#undef GetLocaleInfo
std::string GetLocaleInfoA (LCID code, LCTYPE type)
{
char buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoA (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
std::wstring GetLocaleInfoW (LCID code, LCTYPE type)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoW (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
void GetLocaleInfo (LCID code, LCTYPE type, std::wstring &output)
{
output = GetLocaleInfoW (code, type);
}
void GetLocaleInfo (LCID code, LCTYPE type, std::string &output)
{
output = GetLocaleInfoA (code, type);
}
int GetLocaleInfoEx (std::wstring lpLocaleName, LCTYPE type, std::wstring &output)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
int res = GetLocaleInfoEx (lpLocaleName.c_str (), type, buf, LOCALE_NAME_MAX_LENGTH);
if (&output) output = std::wstring (buf);
return res;
}
#undef SetLocaleInfo
BOOL SetLocaleInfoA (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData.c_str ());
}
BOOL SetLocaleInfoW (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData.c_str ());
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData);
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData);
}
std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 89);
}
std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 89);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleRestrictedCodeFromLcidA (lcid);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleRestrictedCodeFromLcidW (lcid);
}
std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 90);
}
std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 90);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleElaboratedCodeFromLcidW (lcid);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleElaboratedCodeFromLcidA (lcid);
}
LCID LocaleCodeToLcidW (const std::wstring &localeCode)
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0};
int res = GetLocaleInfoEx (localeCode.c_str (), LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH);
LCID lcid = *((LCID *)buf);
return lcid;
}
catch (const std::exception &e) {}
return LocaleNameToLCID (localeCode.c_str (), 0);
#else
return LocaleNameToLCID (localeCode.c_str (), 0);
#endif
}
LCID LocaleCodeToLcidA (const std::string &localeCode)
{
std::wstring lcWide = StringToWString (std::string (localeCode));
return LocaleCodeToLcidW (lcWide.c_str ());
}
LCID LocaleCodeToLcid (const std::wstring &loccode)
{
return LocaleCodeToLcidW (loccode.c_str ());
}
LCID LocaleCodeToLcid (const std::string &loccode)
{
return LocaleCodeToLcidA (loccode.c_str ());
}
std::string GetLocaleRestrictedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 89);
}
std::string GetLocaleRestrictedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 89);
}
std::wstring GetLocaleRestrictedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCode (const std::wstring &lc) { return GetLocaleRestrictedCodeW (lc); }
std::string GetLocaleRestrictedCode (const std::string &lc) { return GetLocaleRestrictedCodeA (lc); }
std::string GetLocaleElaboratedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 90);
}
std::string GetLocaleElaboratedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 90);
}
std::wstring GetLocaleElaboratedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCode (const std::wstring &lc) { return GetLocaleElaboratedCodeW (lc); }
std::string GetLocaleElaboratedCode (const std::string &lc) { return GetLocaleElaboratedCodeA (lc); }
std::string LcidToLocaleCodeA (LCID lcid, char divide = '-')
{
return GetLocaleRestrictedCodeFromLcidA (lcid) + divide + GetLocaleElaboratedCodeFromLcidA (lcid);
}
std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-')
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
LCIDToLocaleName (lcid, buf, LOCALE_NAME_MAX_LENGTH, 0);
return buf;
}
catch (const std::exception &e) {}
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
#else
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
#endif
}
std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); }
std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); }
std::wstring GetUserDefaultLocaleName ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
catch (const std::exception &e) {}
return LcidToLocaleCodeW (GetUserDefaultLCID ());
#else
return LcidToLocaleCodeW (GetUserDefaultLCID ());
#endif
}
std::wstring GetSystemDefaultLocaleName ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
try
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
catch (const std::exception &e) {}
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
#else
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
#endif
}
std::wstring GetComputerLocaleCodeW ()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
{
try
{
{
LCID lcid = GetThreadLocale ();
std::wstring tmp = LcidToLocaleCodeW (lcid);
if (lcid && tmp.length () > 1) return tmp;
}
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
if (lstrlenW (buf)) return buf;
}
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
}
catch (const std::exception &e) {}
LCID lcid = GetThreadLocale ();
if (!lcid) lcid = GetUserDefaultLCID ();
if (!lcid) lcid = GetSystemDefaultLCID ();
return LcidToLocaleCodeW (lcid);
}
#else
{
LCID lcid = GetThreadLocale ();
if (!lcid) lcid = GetUserDefaultLCID ();
if (!lcid) lcid = GetSystemDefaultLCID ();
return LcidToLocaleCodeW (lcid);
}
#endif
}
bool LocaleNameCompare (const std::wstring &left, const std::wstring &right)
{
return std::wnstring::equals (left, right) || LocaleCodeToLcidW (left) == LocaleCodeToLcidW (right);
}

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,7 @@ std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (IDS_LAUNCHWHENREADY),
MAKENAMEIDMAP (IDS_SUCCESS_TITLE),
MAKENAMEIDMAP (IDS_SUCCESS_MTITLE),
MAKENAMEIDMAP (IDS_FAILED_TITLE),
MAKENAMEIDMAP (IDS_FAILED_MTITLE),
MAKENAMEIDMAP (IDS_FAILED_REASONNAME),
MAKENAMEIDMAP (IDS_SUCCESS_LAUNCH),
MAKENAMEIDMAP (IDS_COMMAND_CANCEL),
@@ -48,6 +48,35 @@ std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (IDS_DEFAULTWIDTH),
MAKENAMEIDMAP (IDS_DEFAULTHEIGHT),
MAKENAMEIDMAP (IDS_MINWIDTH),
MAKENAMEIDMAP (IDS_MINHIEHGT)
MAKENAMEIDMAP (IDS_MINHIEHGT),
MAKENAMEIDMAP (IDS_SPLASH_MLOAD),
MAKENAMEIDMAP (IDS_MOREINFO_IDNAME),
MAKENAMEIDMAP (IDS_MOREINFO_IDPUBLISHER),
MAKENAMEIDMAP (IDS_MOREINFO_IDVERSION),
MAKENAMEIDMAP (IDS_MOREINFO_IDFAMILY),
MAKENAMEIDMAP (IDS_MOREINFO_IDFULL),
MAKENAMEIDMAP (IDS_MOREINFO_IDARCH),
MAKENAMEIDMAP (IDS_MOREINFO_PROPFREAMWORK),
MAKENAMEIDMAP (IDS_MOREINFO_PROPRESPKG),
MAKENAMEIDMAP (IDS_MOREINFO_PROPYES),
MAKENAMEIDMAP (IDS_MOREINFO_PROPNO),
MAKENAMEIDMAP (IDS_MOREINFO_INFOSYS),
MAKENAMEIDMAP (IDS_MOREINFO_INFOSYS_VALUE),
MAKENAMEIDMAP (IDS_MOREINFO_INFOLANG),
MAKENAMEIDMAP (IDS_MOREINFO_ID),
MAKENAMEIDMAP (IDS_MOREINFO_PROP),
MAKENAMEIDMAP (IDS_MOREINFO_INFO),
MAKENAMEIDMAP (IDS_CMDPARAM_HELP),
MAKENAMEIDMAP (IDS_CMDTIP_PRETEXT),
MAKENAMEIDMAP (IDS_DEFAULTWIDTH),
MAKENAMEIDMAP (IDS_DEFAULTHEIGHT),
MAKENAMEIDMAP (IDS_MINWIDTH),
MAKENAMEIDMAP (IDS_MINHIEHGT),
MAKENAMEIDMAP (IDS_INSTALLING_MLOADCER),
MAKENAMEIDMAP (IDS_FAILED_MSUCCESS),
MAKENAMEIDMAP (IDS_FAILED_STITLE)
};
#ifdef MAKENAMEIDMAP
#undef MAKENAMEIDMAP
#endif

Binary file not shown.

View File

@@ -47,16 +47,14 @@ System::Drawing::Color GetDwmThemeColor ()
BOOL opaqueBlend = FALSE;
// 调用 DwmGetColorizationColor 获取 Aero 颜色
HRESULT hr = DwmGetColorizationColor (&color, &opaqueBlend);
if (SUCCEEDED (hr)) {
if (SUCCEEDED (hr))
{
BYTE r = (BYTE)((color & 0x00FF0000) >> 16);
BYTE g = (BYTE)((color & 0x0000FF00) >> 8);
BYTE b = (BYTE)(color & 0x000000FF);
return System::Drawing::Color::FromArgb (r, g, b);
}
else {
// 如果获取失败,返回默认颜色
return System::Drawing::Color::FromArgb (0, 120, 215);
}
else return System::Drawing::Color::FromArgb (0, 120, 215); // 如果获取失败,返回默认颜色
}
String ^ColorToHtml (System::Drawing::Color color)
{

View File

@@ -8,11 +8,13 @@
#include <cstdlib>
#include <cstdbool>
#include <cstring>
#include <cstdint>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <cstdint>
#endif
unsigned _wtou (const wchar_t *str)
{

View File

@@ -10,13 +10,13 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
CoInitializeEx (NULL, COINIT_MULTITHREADED);
RoInitialize (RO_INIT_MULTITHREADED);
// CoInitializeEx (NULL, COINIT_MULTITHREADED);
// RoInitialize (RO_INIT_MULTITHREADED);
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
CoUninitialize ();
RoUninitialize ();
// CoUninitialize ();
// RoUninitialize ();
break;
}
return TRUE;

View File

@@ -25,7 +25,31 @@ std::wstring GetFullPathName (const std::wstring &lpFileName)
if (result == 0) return L"";
return std::wstring (buffer.data (), result);
}
LPWSTR AllocWideString (const std::wstring &str)
{
size_t size = (str.length () + 1) * sizeof (WCHAR);
LPWSTR buf = (LPWSTR)CoTaskMemAlloc (size);
if (!buf) return nullptr;
ZeroMemory (buf, size);
wcscpy (buf, str.c_str ());
return buf;
}
// 测试用
LPWSTR AllocWideString (LPCWSTR str)
{
if (!str) return nullptr;
size_t size = (wcslen (str) + 1) * sizeof (WCHAR);
LPWSTR buf = (LPWSTR)CoTaskMemAlloc (size);
if (!buf) return nullptr;
ZeroMemory (buf, size);
wcscpy (buf, str);
return buf;
}
#define _wcsdup AllocWideString
#define free CoTaskMemFree
#define malloc CoTaskMemAlloc
#define realloc CoTaskMemRealloc
#define calloc(_cnt_, _size_) CoTaskMemAlloc (_cnt_ * _size_)
struct destruct
{
std::function <void ()> endtask = nullptr;
@@ -243,6 +267,7 @@ Windows::Data::Xml::Dom::XmlDocument ^SimpleToastNoticeXml2 (const std::wstring
{
case 1: templatename = L"ToastText01"; break; // 仅正文
case 3: templatename = L"ToastText02"; break; // 标题 + 正文
case 6:
case 5: templatename = L"ToastImageAndText01"; break; // 图 + 正文
case 7: templatename = L"ToastImageAndText02"; break; // 图 + 标题 + 正文
default: templatename = L"ToastText01"; break;
@@ -342,12 +367,12 @@ HRESULT CreateToastNoticeFromXml (const std::wstring &lpIdName, Windows::Data::X
else notifier = ToastMgr::CreateToastNotifier ();
auto &xmldoc = pIXml;
auto toast = ref new Toast (xmldoc);
toast->Activated += ref new Windows::Foundation::TypedEventHandler <
Windows::UI::Notifications::ToastNotification ^,
Platform::Object ^
> ([=] (Windows::UI::Notifications::ToastNotification ^sender, Platform::Object ^args) {
if (pfCallback) pfCallback (pCustom);
});
//toast->Activated += ref new Windows::Foundation::TypedEventHandler <
// Windows::UI::Notifications::ToastNotification ^,
// Platform::Object ^
//> ([=] (Windows::UI::Notifications::ToastNotification ^sender, Platform::Object ^args) {
// if (pfCallback) pfCallback (pCustom);
//});
notifier->Show (toast);
return hr = S_OK;
}
@@ -445,7 +470,7 @@ std::wstring IStreamToTempFile (IStream *p, const std::wstring &ext = L".tmp")
if (FAILED (hr)) throw Platform::Exception::CreateException (hr);
LARGE_INTEGER liZero = {};
stream->Seek (liZero, STREAM_SEEK_SET, nullptr);
HANDLE hFile = CreateFileW (outpath.c_str (), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr);
HANDLE hFile = CreateFileW (outpath.c_str (), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, nullptr);
const size_t bufsize = 4096;
BYTE buf [bufsize] = {0};
ULONG bytesRead = 0;
@@ -554,3 +579,71 @@ HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath
else pPersistFile = nullptr;
return hr;
}
void NoticeApiFreeString (LPWSTR lpstr)
{
if (!lpstr) return;
CoTaskMemFree (lpstr);
}
size_t Base64ToBytes (const std::wstring &base64OrDataUri, std::vector <BYTE> &retbytes)
{
retbytes.clear ();
std::wstring base64 = base64OrDataUri;
size_t commaPos = base64.find (L',');
if (commaPos != std::wstring::npos) base64 = base64.substr (commaPos + 1);
DWORD binLen = 0;
if (!CryptStringToBinaryW (base64.c_str (), static_cast <DWORD> (base64.length ()), CRYPT_STRING_BASE64, nullptr, &binLen, nullptr, nullptr))
return 0;
retbytes.resize (binLen);
if (!CryptStringToBinaryW (base64.c_str (), static_cast <DWORD> (base64.length ()), CRYPT_STRING_BASE64, retbytes.data (), &binLen, nullptr, nullptr))
{
retbytes.clear ();
return 0; // 解码失败
}
return binLen;
}
HRESULT BytesToIStream (const std::vector <BYTE> &data, IStream **ppStream)
{
if (!ppStream) return E_POINTER;
*ppStream = nullptr;
HGLOBAL hMem = GlobalAlloc (GMEM_MOVEABLE, data.size ());
if (!hMem) return E_OUTOFMEMORY;
void *pMem = GlobalLock (hMem);
if (!pMem)
{
GlobalFree (hMem);
return E_FAIL;
}
memcpy (pMem, data.data (), data.size ());
GlobalUnlock (hMem);
HRESULT hr = CreateStreamOnHGlobal (hMem, TRUE, ppStream);
if (FAILED (hr)) GlobalFree (hMem);
return hr;
}
HRESULT CreateToastNoticeWithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpText, LPCWSTR lpImgBase64, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg)
{
IStream *ist = nullptr;
destruct relt ([&ist] () {
if (ist) ist->Release ();
ist = nullptr;
});
std::vector <BYTE> bytes;
Base64ToBytes (lpImgBase64 ? lpImgBase64 : L"", bytes);
if (bytes.size ())
{ if (FAILED (BytesToIStream (bytes, &ist))) ist = nullptr; }
return CreateToastNoticeWithIStream (lpIdName, lpText, ist, pfCallback, pCustom, lpExceptMsg);
}
HRESULT CreateToastNotice2WithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImgBase64, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg)
{
IStream *ist = nullptr;
destruct relt ([&ist] () {
if (ist) ist->Release ();
ist = nullptr;
});
std::vector <BYTE> bytes;
Base64ToBytes (lpImgBase64 ? lpImgBase64 : L"", bytes);
if (bytes.size ())
{ if (FAILED (BytesToIStream (bytes, &ist))) ist = nullptr; }
return CreateToastNoticeWithIStream2 (lpIdName, lpTitle, lpText, ist, pfCallback, pCustom, lpExceptMsg);
}

View File

@@ -31,16 +31,16 @@ extern "C"
// 参考https://learn.microsoft.com/zh-cn/previous-versions/windows/apps/hh761494(v=win.10)
// 通过 Toast 通知名来获取 XML 模板。
// 不符合会返回一个默认模板(只会有一个 text 节点。根据需要的话可以自己添加)
// 注意:返回的指针要自己 free 释放
// 注意:返回的指针要自己 NoticeApiFreeString 释放
NOTICE_API LPWSTR GetToastNoticeXml (LPCWSTR lpTemplateName);
// 获取一个简单的 Toast 通知 XML 文档。第一个参数是必须的。第二个参数为图片 URIfile:///)。
// 第二个参数如果为 NULL 或去掉首尾空的长度为 0 的文本则不会使用带图片的模板。
// 注意:返回的指针要自己通过 free 释放
// 注意:返回的指针要自己通过 NoticeApiFreeString 释放
NOTICE_API LPWSTR GenerateSimpleToastNoticeXml (LPCWSTR lpText, LPCWSTR lpImagePath);
// 获取一个简单的 Toast 通知 XML 文档。第一个参数是必须的。第三个参数为图片 URIfile:///)。
// 第三个参数如果为 NULL 或去掉首尾空的长度为 0 的文本则不会使用带图片的模板。
// 第二个参数可以为 NULL 或空文本。当为空时不会使用相关模板
// 注意:返回的指针要自己通过 free 释放
// 注意:返回的指针要自己通过 NoticeApiFreeString 释放
NOTICE_API LPWSTR GenerateSimpleToastNoticeXml2 (LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImagePath);
// 创建并显示一个 Toast 通知
// 参数1 为非必须项,这意味着可以传入 NULL 或空文本。但是建议必须填。桌面应用
@@ -48,7 +48,7 @@ extern "C"
// 在 Windows 10 已经去除。
// pfCallback 为点击 Toast 通知本体后触发的回调函数。注意:仅运行期才能用,且不一定会调用成功
// pCustom 可以传入自定义内容并在回调中使用
// lpExceptMsg 返回异常信息。获取到的指针必须由 free 释放。
// lpExceptMsg 返回异常信息。获取到的指针必须由 NoticeApiFreeString 释放。
NOTICE_API HRESULT CreateToastNoticeFromXmlDocument (LPCWSTR lpIdName, LPCWSTR lpXmlString, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg);
// 创建一个简单的 Toast 通知。仅支持一段文本和一张图片(图片若不需要则设置为 NULL 或空文本)
// 一些参数作用与 CreateToastNoticeFromXmlDocument 中的同名参数作用一致。
@@ -71,6 +71,15 @@ extern "C"
// 创建快捷方式
// (不用安装程序原生的创建,因为需要 AppUserID 才能使用 Toast 通知,当然这个限制只有 Windows 8.x 有Windows 10 没有这个限制了)
NOTICE_API HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId);
// 由 notice.dll 获取到的动态字符串必须由此释放。
NOTICE_API void NoticeApiFreeString (LPWSTR lpstr);
// 创建一个简单的 Toast 通知。支持两段文本和一张图片(图片是 data uri 或者只是 Base64 编码后的字符串,如果不想设置则置 NULL
// 一些参数作用与 CreateToastNoticeFromXmlDocument 中的同名参数作用一致。
NOTICE_API HRESULT CreateToastNoticeWithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpText, LPCWSTR lpImgBase64, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg);
// 创建一个简单的 Toast 通知。支持两段文本和一张图片(图片是 data uri 或者只是 Base64 编码后的字符串,如果不想设置则置 NULL
// lpText 可以设置为 NULL 或空文本。此时函数的作用与 CreateToastNoticeWithIStream 一致。
// 一些参数作用与 CreateToastNoticeFromXmlDocument 中的同名参数作用一致。
NOTICE_API HRESULT CreateToastNotice2WithImgBase64 (LPCWSTR lpIdName, LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImgBase64, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -80,3 +89,117 @@ extern "C"
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
#include <string>
#include <functional>
namespace notice
{
// using LPWSTR = wchar_t *;
struct destruct
{
using funcend = std::function <void ()>;
funcend endtask = nullptr;
destruct (funcend endtask): endtask (endtask) {}
~destruct () { if (endtask) endtask (); }
destruct (destruct &) = delete;
};
struct autostr
{
LPWSTR lpstr = nullptr;
destruct reltask = [this] () {
if (lpstr) NoticeApiFreeString (lpstr);
lpstr = nullptr;
};
autostr (LPWSTR str = nullptr): lpstr (str) {}
operator LPWSTR () const { return lpstr; }
operator std::wstring () const { return lpstr ? lpstr : L""; }
std::wstring get_string () { return lpstr ? lpstr : L""; }
};
using qwstring = std::wstring &;
using qcwstring = const std::wstring &;
struct hresult
{
HRESULT hr = S_OK;
std::wstring message = L"";
operator HRESULT () const { return hr; }
operator std::wstring () const { return message; }
hresult (HRESULT hr = S_OK, qcwstring msg = L""): hr (hr), message (msg) {}
};
}
std::wstring GetToastNoticeXml (notice::qcwstring template_name) { return notice::autostr (GetToastNoticeXml (template_name.c_str ())).get_string (); }
std::wstring GenerateSimpleToastNoticeXml (notice::qcwstring text, notice::qcwstring imgurl = L"") { return notice::autostr (GenerateSimpleToastNoticeXml (text.c_str (), imgurl.c_str ())).get_string (); }
std::wstring GenerateSimpleToastNoticeXml (notice::qcwstring title, notice::qcwstring text, notice::qcwstring imgurl) { return notice::autostr (GenerateSimpleToastNoticeXml2 (title.c_str (), text.c_str (), imgurl.c_str ())).get_string (); }
std::wstring GenerateSimpleToastNoticeXml2 (notice::qcwstring title, notice::qcwstring text = L"", notice::qcwstring imgurl = L"") { return GenerateSimpleToastNoticeXml2 (title, text, imgurl); }
void ToastNoticeEventCallback (void *pCustom)
{
if (pCustom)
{
using cbfunc = std::function <void ()>;
auto func = reinterpret_cast <cbfunc *> (pCustom);
if (func) (*func)();
}
}
notice::hresult CreateToastNoticeFromXmlDocument (notice::qcwstring idname, notice::qcwstring xmlstring, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNoticeFromXmlDocument (idname.c_str (), xmlstring.c_str (), &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring text, notice::qcwstring imgpath, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNotice (idname.c_str (), text.c_str (), imgpath.c_str (), &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text, notice::qcwstring imgpath, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNotice2 (idname.c_str (), title.c_str (), text.c_str (), imgpath.c_str (), &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
notice::hresult CreateToastNotice2 (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text = L"", notice::qcwstring imgpath = L"", std::function <void ()> callback = nullptr) { return CreateToastNotice (idname, title, text, imgpath, callback); }
notice::hresult CreateToastNoticeWithIStream (notice::qcwstring idname, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNoticeWithIStream (idname.c_str (), text.c_str (), imgstream, &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
notice::hresult CreateToastNoticeWithIStream2 (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text = L"", IStream *imgstream = nullptr, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNoticeWithIStream2 (idname.c_str (), title.c_str (), text.c_str (), imgstream, &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
notice::hresult CreateToastNoticeWithIStream (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr) { return CreateToastNoticeWithIStream2 (idname, title, text, imgstream, callback); }
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring xmlstring, std::function <void ()> callback) { return CreateToastNoticeFromXmlDocument (idname, xmlstring, callback); }
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr) { return CreateToastNoticeWithIStream (idname, text, imgstream, callback); }
notice::hresult CreateToastNotice (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text, IStream *imgstream, std::function <void ()> callback = nullptr) { return CreateToastNoticeWithIStream2 (idname, title, text, imgstream, callback); }
HRESULT CreateShortcutWithAppIdW (notice::qcwstring shortcut_path, notice::qcwstring targetpath, notice::qcwstring appid) { return CreateShortcutWithAppIdW (shortcut_path.c_str (), targetpath.c_str (), appid.c_str ()); }
HRESULT CreateToastNoticeWithImgBase64 (notice::qcwstring idname, notice::qcwstring text, notice::qcwstring imgbase64, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNoticeWithImgBase64 (idname.c_str (), text.c_str (), imgbase64.c_str (), &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
HRESULT CreateToastNotice2WithImgBase64 (notice::qcwstring idname, notice::qcwstring title, notice::qcwstring text, notice::qcwstring imgbase64, std::function <void ()> callback = nullptr)
{
notice::autostr exp;
notice::hresult hr;
hr.hr = CreateToastNotice2WithImgBase64 (idname.c_str (), title.c_str (), text.c_str (), imgbase64.c_str (), &ToastNoticeEventCallback, &callback, &exp.lpstr);
hr.message = exp.get_string ();
return hr;
}
#endif

View File

@@ -61,7 +61,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>shlwapi.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -80,7 +80,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>shlwapi.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -32,8 +32,13 @@
#include <Shlwapi.h>
#include <algorithm>
#include <random>
#include <ppltasks.h>
#include <thread>
#include <vector>
#include <combaseapi.h>
#using <Windows.winmd>
using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Microsoft::WRL::Wrappers;
#include <wincrypt.h>

View File

@@ -10,13 +10,13 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
CoInitializeEx (NULL, COINIT_MULTITHREADED | COINIT_APARTMENTTHREADED);
RoInitialize (RO_INIT_MULTITHREADED);
// CoInitializeEx (NULL, COINIT_MULTITHREADED | COINIT_APARTMENTTHREADED);
// RoInitialize (RO_INIT_MULTITHREADED);
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
CoUninitialize ();
RoUninitialize ();
// CoUninitialize ();
// RoUninitialize ();
break;
}
return TRUE;

View File

@@ -20,7 +20,33 @@ std::wstring GetFullPathName (const std::wstring &lpFileName)
std::wstring g_swExceptionCode = L"";
std::wstring g_swExceptionDetail = L"";
bool g_enableIterDeps = false;
LPWSTR AllocWideString (const std::wstring &str)
{
size_t size = (str.length () + 1) * sizeof (WCHAR);
LPWSTR buf = (LPWSTR)CoTaskMemAlloc (size);
if (!buf) return nullptr;
ZeroMemory (buf, size);
wcscpy (buf, str.c_str ());
return buf;
}
// 测试用
LPWSTR AllocWideString (LPCWSTR str)
{
if (!str) return nullptr;
size_t size = (wcslen (str) + 1) * sizeof (WCHAR);
LPWSTR buf = (LPWSTR)CoTaskMemAlloc (size);
if (!buf) return nullptr;
ZeroMemory (buf, size);
wcscpy (buf, str);
return buf;
}
#define _wcsdup AllocWideString
#define free CoTaskMemFree
#define malloc CoTaskMemAlloc
#define realloc CoTaskMemRealloc
#define calloc(_cnt_, _size_) CoTaskMemAlloc (_cnt_ * _size_)
struct destruct
{
std::function <void ()> endtask = nullptr;
@@ -57,15 +83,15 @@ template <typename TAsyncOpCreator> HRESULT RunPackageManagerOperation (TAsyncOp
depopt->Progress = ref new onprogress ([pfCallback, pCustom] (progressopt operation, DeploymentProgress progress) {
if (pfCallback) pfCallback ((DWORD)progress.percentage, pCustom);
});
depopt->Completed = ref new onprogresscomp ([&hCompEvt] (progressopt, AsyncStatus) {
depopt->Completed = ref new onprogresscomp ([&hCompEvt] (progressopt, Windows::Foundation::AsyncStatus) {
SetEvent (hCompEvt);
});
WaitForSingleObject (hCompEvt, INFINITE);
switch (depopt->Status)
{
case AsyncStatus::Completed:
case Windows::Foundation::AsyncStatus::Completed:
return S_OK;
case AsyncStatus::Error:
case Windows::Foundation::AsyncStatus::Error:
{
auto depresult = depopt->GetResults ();
auto errorcode = depopt->ErrorCode;
@@ -77,11 +103,11 @@ template <typename TAsyncOpCreator> HRESULT RunPackageManagerOperation (TAsyncOp
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (HRESULT)errorcode.Value;
}
case AsyncStatus::Canceled:
case Windows::Foundation::AsyncStatus::Canceled:
g_swExceptionDetail = L"Installation Canceled";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_ABORT;
case AsyncStatus::Started:
case Windows::Foundation::AsyncStatus::Started:
g_swExceptionDetail = L"Installation is Running";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_PENDING;
@@ -185,7 +211,8 @@ void SidToAccountName (const std::wstring &sidString, std::wstring &stringSid)
if (LookupAccountSidW (nullptr, sid, namebuf.data (), &nameCharCount, domainNameBuf.data (), &domainNameCharCount, &sidType))
{
stringSid = domainNameBuf.data ();
stringSid += stringSid + L"\\" + namebuf.data ();
if (!stringSid.empty ()) stringSid += L"\\";
stringSid += namebuf.data ();
}
}
if (stringSid.length () == 0) stringSid = sidString;
@@ -218,7 +245,7 @@ struct pkg_info
std::wstring users = L"";
std::wstring sids = L"";
std::vector <pkg_info> dependencies;
static pkg_info parse (Windows::ApplicationModel::Package ^pkg, Windows::Management::Deployment::PackageManager ^mgr)
static pkg_info parse (Windows::ApplicationModel::Package ^pkg, Windows::Management::Deployment::PackageManager ^mgr, bool iterdeps = true)
{
pkg_info pi;
if (!pkg) throw ref new InvalidArgumentException ("No package found.");
@@ -259,23 +286,30 @@ struct pkg_info
std::wstring sid;
WAPParseSetStringValue (sid, it->UserSecurityId);
if (i) pi.sids += L';';
pi.users += sid;
pi.sids += sid;
}
i ++;
}
}
catch (...) {}
if (g_enableIterDeps && iterdeps)
{
try
{
auto deps = pkg->Dependencies;
for (auto it : deps)
if (deps && deps->Size)
{
auto deppkg = pkg_info::parse (it, mgr);
for (size_t i = 0; i < deps->Size; i ++)
{
auto it = deps->GetAt (i);
auto deppkg = pkg_info::parse (it, mgr, false);
deppkg.dependencies.clear ();
pi.dependencies.push_back (deppkg);
}
}
}
catch (...) {}
}
return pi;
#ifdef WAPParseSetStringValue
#undef WAPParseSetStringValue
@@ -319,6 +353,49 @@ struct pkg_info
}
};
[STAThread]
HRESULT ProcessFoundAppxPackages (Windows::Foundation::Collections::IIterable <Windows::ApplicationModel::Package ^> ^pkgarr, PackageManager ^pkgmgr, std::function <void (pkg_info &)> pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
if (pkgarr)
{
for each (auto pkg in pkgarr)
{
auto pkginfo = pkg_info::parse (pkg, pkgmgr);
if (pfCallback) pfCallback (pkginfo);
}
}
return S_OK;
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
HRESULT FindAppxPackageByCallback (std::function <void (pkg_info &)> pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
@@ -327,12 +404,7 @@ HRESULT FindAppxPackageByCallback (std::function <void (pkg_info &)> pfCallback,
{
auto pkgmgr = ref new PackageManager ();
auto pkgarr = pkgmgr->FindPackages ();
for (auto pkg : pkgarr)
{
auto pkginfo = pkg_info::parse (pkg, pkgmgr);
if (pfCallback) pfCallback (pkginfo);
}
return S_OK;
return ProcessFoundAppxPackages (pkgarr, pkgmgr, pfCallback, pErrorCode, pDetailMsg);
}
catch (AccessDeniedException ^e)
{
@@ -632,6 +704,7 @@ LPCWSTR GetPackageManagerLastErrorDetailMessage () { return g_swExceptionDetail.
HRESULT ActivateAppxApplication (LPCWSTR lpAppUserId, PDWORD pdwProcessId)
{
if (FAILED (CoInitializeEx (NULL, COINIT_APARTMENTTHREADED))) return E_INVALIDARG;
if (!lpAppUserId) return E_INVALIDARG;
std::wstring strAppUserModelId (L"");
if (lpAppUserId) strAppUserModelId += lpAppUserId;
@@ -649,9 +722,112 @@ HRESULT ActivateAppxApplication (LPCWSTR lpAppUserId, PDWORD pdwProcessId)
{
// This call ensures that the app is launched as the foreground window
hResult = CoAllowSetForegroundWindow (spAppActivationManager, NULL);
DWORD dwProgressId = 0;
// Launch the app
if (SUCCEEDED (hResult)) hResult = spAppActivationManager->ActivateApplication (strAppUserModelId.c_str (), NULL, AO_NONE, pdwProcessId);
if (SUCCEEDED (hResult))
hResult = spAppActivationManager->ActivateApplication (strAppUserModelId.c_str (), NULL, AO_NONE, &dwProgressId);
if (pdwProcessId) *pdwProcessId = dwProgressId;
}
}
return hResult;
}
[STAThread]
HRESULT FindAppxPackageByCallback (LPCWSTR lpPkgName, LPCWSTR lpPublisher, std::function <void (pkg_info &)> pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
auto pkgmgr = ref new PackageManager ();
std::wstring pkgname = lpPkgName ? lpPkgName : L"";
std::wstring pkgpublisher = lpPublisher ? lpPublisher : L"";
auto refname = ref new Platform::String (pkgname.c_str ()),
refpublisher = ref new Platform::String (pkgpublisher.c_str ());
auto pkgarr = pkgmgr->FindPackages (refname, refpublisher);
return ProcessFoundAppxPackages (pkgarr, pkgmgr, pfCallback, pErrorCode, pDetailMsg);
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
HRESULT FindAppxPackagesByIdentity (LPCWSTR lpPkgName, LPCWSTR lpPkgPublisher, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return FindAppxPackageByCallback (lpPkgName, lpPkgPublisher, [&pCustom, &pfCallback] (pkg_info &pi) {
std::vector <BYTE> bytes;
pi.to_c_struct (bytes);
if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
}, pErrorCode, pDetailMsg);
}
[STAThread]
HRESULT FindAppxPackageByCallback (LPCWSTR lpPkgFamilyName, std::function <void (pkg_info &)> pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
auto pkgmgr = ref new PackageManager ();
std::wstring familyname = L"";
familyname += lpPkgFamilyName ? lpPkgFamilyName : L"";
auto reffamily = ref new Platform::String (familyname.c_str ());
auto pkgarr = pkgmgr->FindPackages (reffamily);
return ProcessFoundAppxPackages (pkgarr, pkgmgr, pfCallback, pErrorCode, pDetailMsg);
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
HRESULT FindAppxPackagesByFamilyName (LPCWSTR lpPkgFamilyName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return FindAppxPackageByCallback (lpPkgFamilyName, [&pCustom, &pfCallback] (pkg_info &pi) {
std::vector <BYTE> bytes;
pi.to_c_struct (bytes);
if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
}, pErrorCode, pDetailMsg);
}
void PackageManagerFreeString (LPWSTR lpString) { if (lpString) free (lpString); }

View File

@@ -59,18 +59,23 @@ extern "C"
#define DEPOLYOPTION_INSTALL_ALL_RESOURCES 0x00000020
// 使用默认行为。
#define DEPOLYOPTION_NONE 0x00000000
// 发现拼写错了,只能将错就错(反正 IDE 不会给宏注释):
#define DEPLOYOPTION_FORCE_APP_SHUTDOWN DEPOLYOPTION_FORCE_APP_SHUTDOWN
#define DEPLOYOPTION_DEVELOPMENT_MODE DEPOLYOPTION_DEVELOPMENT_MODE
#define DEPLOYOPTION_INSTALL_ALL_RESOURCES DEPOLYOPTION_INSTALL_ALL_RESOURCES
#define DEPLOYOPTION_NONE DEPOLYOPTION_NONE
// 安装一个 Appx/AppxBundle/Msix/MsixBundle 包
// 注意:传入的文件路径为 DOS/NT 风格。如C:\Windows\...
// 该函数类似于 PowerShell 的 Add-AppxPackage
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPLOYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 安装一个 Appx/AppxBundle/Msix/MsixBundle 包
// 注意:传入的文件路径为 URI。
// 该函数类似于 PowerShell 的 Add-AppxPackage
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT AddAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT AddAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPLOYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
typedef struct _FIND_PACKAGE_ID
{
@@ -122,13 +127,13 @@ extern "C"
// 通过回调来获取所有包的信息。回调函数允许传自定义内容。返回的值可以判断是否成功。
// 该函数类似于 PowerShell 的 Get-AppxPackage
// 注意:回调函数中包的信息无法修改,也不能擅自释放。且随着函数的执行完毕自动释放。这就要求在回调中自行拷贝一份。
// 输出的错误信息别忘了用 free 释放
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 移除一个已经安装到电脑上的应用。注意:传入的是包完整名。
// 输出的错误信息别忘了用 free 释放
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT RemoveAppxPackage (LPCWSTR lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 清理指定用户的指定 包 。 用于清除删除用户用户配置文件后为用户安装的包。
// 输出的错误信息别忘了用 free 释放
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT CleanupAppxPackage (LPCWSTR lpPkgName, LPCWSTR lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 注册应用包
@@ -167,13 +172,13 @@ extern "C"
// 仅当更新包的版本高于已安装包的版本时,才能更新已安装的包。 如果不存在以前版本的包,则操作将失败。
// 注意:传入的文件路径为 DOS/NT 风格。如C:\Windows\...
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT UpdateAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 为当前用户汇报已安装的包或其依赖项包。
// 仅当更新包的版本高于已安装包的版本时,才能更新已安装的包。 如果不存在以前版本的包,则操作将失败。
// 注意:传入的文件路径为 URI。
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
// 输出的错误信息别忘了用 PackageManagerFreeString 释放
PKGMGR_API HRESULT UpdateAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 检索有关为任何用户安装的指定 包 的信息。
PKGMGR_API HRESULT FindAppxPackage (LPCWSTR lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
@@ -183,6 +188,12 @@ extern "C"
PKGMGR_API LPCWSTR GetPackageManagerLastErrorDetailMessage ();
// 启动 Metro UI 应用
PKGMGR_API HRESULT ActivateAppxApplication (LPCWSTR lpAppUserId, PDWORD pdwProcessId);
// 根据提供的包身份名和发布者检索
PKGMGR_API HRESULT FindAppxPackagesByIdentity (LPCWSTR lpPkgName, LPCWSTR lpPkgPublisher, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 根据提供的包系列名检索
PKGMGR_API HRESULT FindAppxPackagesByFamilyName (LPCWSTR lpPkgFamilyName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 释放由 pkgmgr.dll 返回的动态字符串。
PKGMGR_API void PackageManagerFreeString (LPWSTR lpString);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -192,3 +203,470 @@ extern "C"
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
#include <functional>
#include <vector>
#include <string>
#include <cstdlib>
void IAsyncProgressCallback (DWORD dwProgress, void *pCustom)
{
using cbfunc = std::function <void (DWORD)>;
if (auto func = reinterpret_cast <cbfunc *> (pCustom)) (*func)(dwProgress);
}
HRESULT AddAppxPackageFromPath (
const std::wstring &pkgpath,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = AddAppxPackageFromPath (pkgpath.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT AddAppxPackageFromURI (
const std::wstring &pkguri,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = AddAppxPackageFromURI (pkguri.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
struct find_pkginfo
{
bool isvalid = false;
struct
{
std::wstring
name,
publisher,
publisher_id,
full_name,
family_name,
resource_id;
UINT64 version = 0;
// x86: 0
// x64: 9
// Arm: 5
// Neutral: 11
// Arm64: 12
// Unknown: 65535(-1)
WORD architecture = -1;
} identity;
struct
{
std::wstring
display_name,
description,
publisher,
logo_uri;
bool is_framework = false,
resource_package = false;
} properties;
bool is_bundle = false;
bool is_development_mode = false;
std::wstring install_location;
std::vector <std::wstring>
users,
sids;
#define safestring(_pstr_) (_pstr_ ? _pstr_ : L"")
static find_pkginfo parse (LPCFIND_PACKAGE_INFO fpi)
{
if (!fpi) return find_pkginfo ();
find_pkginfo fpkg;
fpkg.identity.name += safestring (fpi->piIdentity.lpName);
fpkg.identity.publisher += safestring (fpi->piIdentity.lpPublisher);
fpkg.identity.publisher_id += safestring (fpi->piIdentity.lpPublisherId);
fpkg.identity.family_name += safestring (fpi->piIdentity.lpFamilyName);
fpkg.identity.full_name += safestring (fpi->piIdentity.lpFullName);
fpkg.identity.resource_id += safestring (fpi->piIdentity.lpResourceId);
fpkg.identity.version = fpi->piIdentity.qwVersion;
fpkg.identity.architecture = fpi->piIdentity.wProcessArchitecture;
fpkg.properties.display_name += safestring (fpi->piProperties.lpDisplayName);
fpkg.properties.description += safestring (fpi->piProperties.lpDescription);
fpkg.properties.publisher += safestring (fpi->piProperties.lpPublisher);
fpkg.properties.logo_uri += safestring (fpi->piProperties.lpLogoUri);
fpkg.properties.is_framework = fpi->piProperties.bIsFramework;
fpkg.properties.resource_package = fpi->piProperties.bIsResourcePackage;
fpkg.is_bundle = fpi->piProperties.bIsBundle;
fpkg.is_development_mode = fpi->piProperties.bIsDevelopmentMode;
fpkg.install_location += safestring (fpi->lpInstallLocation);
std::wstring users;
users += safestring (fpi->lpUsers);
std::wstring sids;
sids += safestring (fpi->lpSIDs);
std::wstring part = L"";
for (size_t i = 0; i < users.length (); i ++)
{
auto &wch = users [i];
if (wch == L';' || wch == L'0')
{
if (!part.empty ()) fpkg.users.push_back (part);
part = L"";
continue;
}
part += wch;
}
if (!part.empty ()) fpkg.users.push_back (part);
part = L"";
for (size_t i = 0; i < sids.length (); i ++)
{
auto &wch = sids [i];
if (wch == L';' || wch == L'0')
{
if (!part.empty ()) fpkg.sids.push_back (part);
part = L"";
continue;
}
part += wch;
}
if (!part.empty ()) fpkg.sids.push_back (part);
fpkg.isvalid = true;
return fpkg;
}
#ifdef safestring
#undef safestring
#endif
};
void IAsyncFindEnumCallback (LPCFIND_PACKAGE_INFO pNowItem, void *pCustom)
{
if (pNowItem)
{
try
{
auto fpkg = find_pkginfo::parse (pNowItem);
if (fpkg.isvalid)
{
using cbfunc = std::function <void (const find_pkginfo &)>;
auto func = reinterpret_cast <cbfunc *> (pCustom);
if (func) (*func)(fpkg);
}
}
catch (const std::exception &e)
{
OutputDebugStringA (e.what ());
}
}
}
HRESULT GetAppxPackages (
std::function <void (const find_pkginfo &)> callback,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = GetAppxPackages (&IAsyncFindEnumCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT GetAppxPackages (
std::vector <find_pkginfo> &out_pkgs,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
return GetAppxPackages ([&] (const find_pkginfo &fpi) {
out_pkgs.push_back (fpi);
}, errorcode, detailmsg);
}
HRESULT GetAppxPackages (
const std::wstring &package_family_name,
std::function <void (const find_pkginfo &)> callback,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = FindAppxPackagesByFamilyName (package_family_name.c_str (), &IAsyncFindEnumCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT GetAppxPackages (
const std::wstring &package_family_name,
std::vector <find_pkginfo> &out_pkgs,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
return GetAppxPackages (package_family_name , [&] (const find_pkginfo &fpi) {
out_pkgs.push_back (fpi);
}, errorcode, detailmsg);
}
HRESULT GetAppxPackages (
const std::wstring &package_id_name,
const std::wstring &package_id_publisher,
std::function <void (const find_pkginfo &)> callback,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = FindAppxPackagesByIdentity (package_id_name.c_str (), package_id_publisher.c_str (), &IAsyncFindEnumCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT GetAppxPackages (
const std::wstring &package_id_name,
const std::wstring &package_id_publisher,
std::vector <find_pkginfo> &out_pkgs,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
return GetAppxPackages (package_id_name, package_id_publisher, [&] (const find_pkginfo &fpi) {
out_pkgs.push_back (fpi);
}, errorcode, detailmsg);
}
HRESULT FindAppxPackage (
const std::wstring &package_fullname,
std::function <void (const find_pkginfo &)> callback,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = FindAppxPackage (package_fullname.c_str (), &IAsyncFindEnumCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT FindAppxPackage (
const std::wstring &package_fullname,
find_pkginfo &out_pkginf,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
return FindAppxPackage (package_fullname, [&] (const find_pkginfo &fpkg) {
out_pkginf = fpkg;
}, errorcode, detailmsg);
}
HRESULT RemoveAppxPackage (
const std::wstring &package_fullname,
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = RemoveAppxPackage (package_fullname.c_str (), &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT CleanupAppxPackage (
const std::wstring &package_name,
const std::wstring &user_sid,
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = CleanupAppxPackage (package_name.c_str (), user_sid.c_str (), &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT RegisterAppxPackageByPath (
const std::wstring &manifest_path,
const std::vector <std::wstring> &depurilist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * depurilist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = depurilist.size ();
for (size_t i = 0; i < depurilist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)depurilist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = RegisterAppxPackageByPath (manifest_path.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT RegisterAppxPackageByUri (
const std::wstring &manifest_uri,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = RegisterAppxPackageByUri (manifest_uri.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT RegisterAppxPackageByFullName (
const std::wstring &package_full_name,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = RegisterAppxPackageByFullName (package_full_name.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT StageAppxPackageFromURI (
const std::wstring &file_uri,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = StageAppxPackageFromURI (file_uri.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT StageAppxPackageFromPath (
const std::wstring &file_path,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = StageAppxPackageFromURI (file_path.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT StageAppxUserData (
const std::wstring &package_full_name,
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = StageAppxUserData (package_full_name.c_str (), &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT UpdateAppxPackageFromPath (
const std::wstring &file_path,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = UpdateAppxPackageFromPath (file_path.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT UpdateAppxPackageFromURI (
const std::wstring &file_uri,
const std::vector <std::wstring> &deplist = std::vector <std::wstring> (),
DWORD deployoption = DEPOLYOPTION_NONE, // 使用 DEPOLYOPTION_* 前缀
std::function <void (DWORD)> callback = nullptr,
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = deplist.size ();
for (size_t i = 0; i < deplist.size (); i ++) lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = UpdateAppxPackageFromURI (file_uri.c_str (), lpdeplist, deployoption, &IAsyncProgressCallback, &callback, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT SetAppxPackageStatus (
const std::wstring &package_full_name,
DWORD status, // PACKAGESTATUS_* 前缀常量
std::wstring &errorcode = std::wstring (),
std::wstring &detailmsg = std::wstring ()
) {
LPWSTR lperr = nullptr, lpmsg = nullptr;
HRESULT hr = SetAppxPackageStatus (package_full_name.c_str (), status, &lperr, &lpmsg);
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
return hr;
}
HRESULT ActivateAppxApplication (
const std::wstring &app_user_id,
PDWORD ret_processid = nullptr
) {
return ActivateAppxApplication (app_user_id.c_str (), ret_processid);
}
#endif

View File

@@ -15,9 +15,6 @@
// TODO: 在此处引用程序需要的其他头文件
#using <Windows.winmd>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Management::Deployment;
#include <string>
#include <vector>
#include <objbase.h>
@@ -31,3 +28,6 @@ using namespace Windows::Management::Deployment;
#include <shlobj.h>
#include <stdio.h>
#include <shobjidl.h>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Management::Deployment;

View File

@@ -10,10 +10,10 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
CoInitializeEx (NULL, COINIT_MULTITHREADED); break;
// CoInitializeEx (NULL, COINIT_MULTITHREADED); break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
CoUninitialize ();
// CoUninitialize ();
break;
}
return TRUE;

871
pkgread/filepath.h Normal file
View File

@@ -0,0 +1,871 @@
#pragma once
#include <Windows.h>
#include <string>
#include <algorithm>
#include <shlwapi.h>
#include <vector>
#include <iomanip>
#include <functional>
#include <sstream>
#include "strcmp.h"
#include "version.h"
#include "module.h"
typedef version S_VERSION;
template <typename T> constexpr T Max (T l, T r) { return l > r ? l : r; }
template <typename T> constexpr T Max (T l, T m, T r) { return Max (Max (l, r), m); }
template <typename T> constexpr T Max (T l, T ml, T mr, T r) { return Max (Max (l, ml), Max (mr, r)); }
template <typename CharT> std::basic_string <CharT> replace_substring
(
const std::basic_string <CharT> &str,
const std::basic_string <CharT> &from,
const std::basic_string <CharT> &to
)
{
if (from.empty ()) return str;
std::basic_string <CharT> result;
size_t pos = 0;
size_t start_pos;
while ((start_pos = str.find (from, pos)) != std::basic_string<CharT>::npos)
{
result.append (str, pos, start_pos - pos);
result.append (to);
pos = start_pos + from.length ();
}
result.append (str, pos, str.length () - pos);
return result;
}
std::string GetProgramRootDirectoryA (HMODULE hModule hModule_DefaultParam)
{
char path [MAX_PATH];
if (GetModuleFileNameA (hModule, path, MAX_PATH))
{
std::string dir (path);
size_t pos = dir.find_last_of ("\\/");
if (pos != std::string::npos)
{
dir = dir.substr (0, pos);
}
return dir;
}
return "";
}
std::wstring GetProgramRootDirectoryW (HMODULE hModule hModule_DefaultParam)
{
wchar_t path [MAX_PATH];
if (GetModuleFileNameW (hModule, path, MAX_PATH))
{
std::wstring dir (path);
size_t pos = dir.find_last_of (L"\\/");
if (pos != std::wstring::npos)
{
dir = dir.substr (0, pos);
}
return dir;
}
return L"";
}
std::string EnsureTrailingSlash (const std::string &path)
{
if (path.empty ()) return path; // 空路径直接返回
char lastChar = path.back ();
if (lastChar == '\\' || lastChar == '/')
return path; // 已有分隔符,直接返回
// 根据系统或原路径格式添加适当的分隔符
char separator = (path.find ('/') != std::string::npos) ? '/' : '\\';
return path + separator;
}
std::wstring EnsureTrailingSlash (const std::wstring &path)
{
if (path.empty ()) return path;
wchar_t lastChar = path.back ();
if (lastChar == L'\\' || lastChar == L'/')
return path;
wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\';
return path + separator;
}
bool IsFileExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
bool IsFileExists (const std::string &filePath) { return IsFileExistsA (filePath.c_str ()); }
bool IsFileExists (const std::wstring &filePath) { return IsFileExistsW (filePath.c_str ()); }
bool IsDirectoryExistsA (LPCSTR path)
{
DWORD attributes = GetFileAttributesA (path);
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsDirectoryExistsW (LPCWSTR path)
{
DWORD attributes = GetFileAttributesW (path);
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsDirectoryExists (const std::string &path) { return IsDirectoryExistsA (path.c_str ()); }
bool IsDirectoryExists (const std::wstring &path) { return IsDirectoryExistsW (path.c_str ()); }
bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); }
bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); }
bool IsPathExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
}
bool IsPathExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
}
bool IsPathExists (const std::string &path) { return IsPathExistsA (path.c_str ()); }
bool IsPathExists (const std::wstring &path) { return IsPathExistsW (path.c_str ()); }
bool IsPathExists (LPCSTR path) { return IsPathExistsA (path); }
bool IsPathExists (LPCWSTR path) { return IsPathExistsW (path); }
std::string NormalizePath (const std::string &path)
{
if (!path.empty () && path.back () == '\\')
return path.substr (0, path.size () - 1);
return path.c_str ();
}
std::wstring NormalizePath (const std::wstring &path)
{
if (!path.empty () && path.back () == L'\\')
return path.substr (0, path.size () - 1);
return path.c_str ();
}
std::vector <std::string> EnumSubdirectories (const std::string &directory, bool includeParentPath)
{
std::vector<std::string> subdirs;
std::string normPath = NormalizePath (directory);
std::string searchPath = normPath + "\\*";
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData);
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
do
{
// 过滤 "." 和 ".."
if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0)
continue;
// 判断是否为目录
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (includeParentPath)
subdirs.push_back (normPath + "\\" + findData.cFileName);
else
subdirs.push_back (findData.cFileName);
}
} while (FindNextFileA (hFind, &findData));
FindClose (hFind);
return subdirs;
}
std::vector <std::wstring> EnumSubdirectories (const std::wstring &directory, bool includeParentPath)
{
std::vector<std::wstring> subdirs;
std::wstring normPath = NormalizePath (directory);
std::wstring searchPath = normPath + L"\\*";
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
do
{
if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0)
continue;
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (includeParentPath)
subdirs.push_back (normPath + L"\\" + findData.cFileName);
else
subdirs.push_back (findData.cFileName);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
return subdirs;
}
std::string GetCurrentProgramPathA (HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameA (hModule, nullptr, 0)) + 1);
GetModuleFileNameA (hModule, buf.data (), buf.capacity ());
return buf.data ();
}
std::wstring GetCurrentProgramPathW (HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameW (hModule, nullptr, 0)) + 1);
GetModuleFileNameW (hModule, buf.data (), buf.capacity ());
return buf.data ();
}
std::string GetCurrentProgramNameA (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameA (GetCurrentProgramPathA (hModule).c_str ()); }
std::wstring GetCurrentProgramNameW (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameW (GetCurrentProgramPathW (hModule).c_str ()); }
S_VERSION GetExeFileVersion (LPCSTR lpszFilePath)
{
S_VERSION ver (0);
DWORD dummy;
DWORD size = GetFileVersionInfoSizeA (lpszFilePath, &dummy);
std::vector <BYTE> pVersionInfo (size);
if (!GetFileVersionInfoA (lpszFilePath, 0, size, pVersionInfo.data ()))
{
return ver;
}
VS_FIXEDFILEINFO* pFileInfo = nullptr;
UINT len = 0;
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
{
return ver;
}
if (len == 0 || pFileInfo == nullptr)
{
return ver;
}
ver = S_VERSION (
HIWORD (pFileInfo->dwFileVersionMS),
LOWORD (pFileInfo->dwFileVersionMS),
HIWORD (pFileInfo->dwFileVersionLS),
LOWORD (pFileInfo->dwFileVersionLS)
);
return ver;
}
S_VERSION GetExeFileVersion (LPCWSTR lpswFilePath)
{
S_VERSION ver (0);
DWORD dummy;
DWORD size = GetFileVersionInfoSizeW (lpswFilePath, &dummy);
std::vector <BYTE> pVersionInfo (size);
if (!GetFileVersionInfoW (lpswFilePath, 0, size, pVersionInfo.data ()))
{
return ver;
}
VS_FIXEDFILEINFO* pFileInfo = nullptr;
UINT len = 0;
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
{
return ver;
}
if (len == 0 || pFileInfo == nullptr)
{
return ver;
}
ver = S_VERSION (
HIWORD (pFileInfo->dwFileVersionMS),
LOWORD (pFileInfo->dwFileVersionMS),
HIWORD (pFileInfo->dwFileVersionLS),
LOWORD (pFileInfo->dwFileVersionLS)
);
return ver;
}
S_VERSION GetExeFileVersion (std::wstring objswFilePath)
{
return GetExeFileVersion (objswFilePath.c_str ());
}
S_VERSION GetExeFileVersion (std::string objszFilePath)
{
return GetExeFileVersion (objszFilePath.c_str ());
}
// 设置当前进程的环境变量RunPath和ProgramPath
void SetupInstanceEnvironment (HMODULE hModule hModule_DefaultParam)
{
// 设置RunPath为当前工作目录无结尾反斜杠
std::vector <WCHAR> currentDir (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
DWORD len = GetCurrentDirectoryW (currentDir.capacity (), currentDir.data ());
if (len > 0)
{
std::wstring runPath (currentDir.data ());
if (!runPath.empty () && (runPath.back () == L'\\' || runPath.back () == L'/'))
{
runPath.pop_back ();
}
SetEnvironmentVariableW (L"RunPath", runPath.c_str ());
}
// 设置ProgramPath为程序所在目录无结尾反斜杠
std::vector <WCHAR> modulePath (Max <size_t> (GetModuleFileNameW (hModule, nullptr, 0), MAX_PATH) + 1);
len = GetModuleFileNameW (hModule, modulePath.data (), MAX_PATH);
if (len > 0 && len < MAX_PATH)
{
wchar_t* lastSlash = wcsrchr (modulePath.data (), L'\\');
if (!lastSlash) lastSlash = wcsrchr (modulePath.data (), L'/');
if (lastSlash) *lastSlash = L'\0';
std::wstring programPath (modulePath.data ());
if (!programPath.empty () && (programPath.back () == L'\\' || programPath.back () == L'/'))
{
programPath.pop_back ();
}
SetEnvironmentVariableW (L"ProgramPath", programPath.c_str ());
}
}
// 处理宽字符串环境变量展开
std::wstring ProcessEnvVars (const std::wstring &input)
{
DWORD requiredSize = ExpandEnvironmentStringsW (input.c_str (), nullptr, 0);
if (requiredSize == 0) return input;
std::wstring buffer (requiredSize, L'\0');
if (!ExpandEnvironmentStringsW (input.c_str (), &buffer [0], requiredSize))
{
return input;
}
buffer.resize (requiredSize - 1); // 去除终止空字符
return buffer.c_str ();
}
std::wstring ProcessEnvVars (LPCWSTR input)
{
return ProcessEnvVars (std::wstring (input));
}
// 处理ANSI字符串环境变量展开
std::string ProcessEnvVars (const std::string &input)
{
DWORD requiredSize = ExpandEnvironmentStringsA (input.c_str (), nullptr, 0);
if (requiredSize == 0) return input;
std::string buffer (requiredSize, '\0');
if (!ExpandEnvironmentStringsA (input.c_str (), &buffer [0], requiredSize))
{
return input;
}
buffer.resize (requiredSize - 1); // 去除终止空字符
return buffer.c_str ();
}
std::string ProcessEnvVars (LPCSTR input)
{
return ProcessEnvVars (std::string (input));
}
std::string GetCurrentDirectoryA ()
{
std::vector <CHAR> buf (Max <size_t> (GetCurrentDirectoryA (0, nullptr), MAX_PATH) + 1);
GetCurrentDirectoryA (buf.size (), buf.data ());
return buf.data ();
}
std::wstring GetCurrentDirectoryW ()
{
std::vector <WCHAR> buf (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
GetCurrentDirectoryW (buf.size (), buf.data ());
return buf.data ();
}
std::wstring GetFileDirectoryW (const std::wstring &filePath)
{
std::vector <WCHAR> buf (filePath.capacity () + 1);
lstrcpyW (buf.data (), filePath.c_str ());
PathRemoveFileSpecW (buf.data ());
return buf.data ();
}
std::string GetFileDirectoryA (const std::string &filePath)
{
std::vector <CHAR> buf (filePath.capacity () + 1);
lstrcpyA (buf.data (), filePath.c_str ());
PathRemoveFileSpecA (buf.data ());
return buf.data ();
}
size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter,
std::vector <std::wstring> &outFiles, bool recursive = false)
{
std::wstring searchPath = directory;
if (!searchPath.empty () && searchPath.back () != L'\\')
{
searchPath += L'\\';
}
searchPath += filter;
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
outFiles.push_back (directory + L"\\" + findData.cFileName);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
}
if (recursive) {
std::wstring subDirSearchPath = directory + L"\\*";
hFind = FindFirstFileW (subDirSearchPath.c_str (), &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
wcscmp (findData.cFileName, L".") != 0 && wcscmp (findData.cFileName, L"..") != 0)
{
EnumerateFilesW (directory + L"\\" + findData.cFileName, filter, outFiles, true);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
}
}
return outFiles.size ();
}
// 检查是否为 Windows 设备名(大小写不敏感)
bool IsReservedName (const std::wstring &name)
{
static const wchar_t* reserved [] = {
L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", L"COM8", L"COM9",
L"LPT1", L"LPT2", L"LPT3", L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9"
};
std::wstring upperName = StringToUpper (name);
for (const auto& res : reserved)
{
if (upperName == res || (upperName.rfind (res, 0) == 0 && upperName.length () > wcslen (res) && upperName [wcslen (res)] == L'.'))
{
return true;
}
}
return false;
}
// Windows 文件命名规范检查 (Unicode)
bool IsValidWindowsNameW (LPCWSTR name)
{
if (!name || !*name) return false;
std::wstring wname (name);
if (wname.find_first_of (L"<>:\"/\\|?*") != std::wstring::npos) return false;
if (IsReservedName (wname)) return false;
if (wname.back () == L' ' || wname.back () == L'.') return false;
return true;
}
// Windows 文件命名规范检查 (ANSI)
bool IsValidWindowsNameA (LPCSTR name)
{
if (!name || !*name) return false;
std::string str (name);
if (str.find_first_of ("<>:\"/\\|?*") != std::string::npos) return false;
// 转换 ANSI 到宽字符
int len = MultiByteToWideChar (CP_ACP, 0, name, -1, NULL, 0);
if (len <= 0) return false;
std::wstring wname (len - 1, L'\0');
MultiByteToWideChar (CP_ACP, 0, name, -1, &wname [0], len);
if (IsReservedName (wname)) return false;
if (str.back () == ' ' || str.back () == '.') return false;
return true;
}
bool IsValidWindowsName (LPCSTR name) { return IsValidWindowsNameA (name); }
bool IsValidWindowsName (LPCWSTR name) { return IsValidWindowsNameW (name); }
bool IsValidWindowsName (const std::wstring &name) { return IsValidWindowsName (name.c_str ()); }
bool IsValidWindowsName (const std::string &name) { return IsValidWindowsName (name.c_str ()); }
std::wstring GetRootFolderNameFromFilePath (const std::wstring &lpFilePath)
{
std::vector <WCHAR> szPath (Max <size_t> (lpFilePath.length (), MAX_PATH) + 1);
if (!PathCanonicalizeW (szPath.data (), lpFilePath.c_str ())) return L"";
if (PathRemoveFileSpecW (szPath.data ()) == FALSE) return L"";
LPCWSTR pszFolder = PathFindFileNameW (szPath.data ());
if (*pszFolder != L'\0') return std::wstring (pszFolder);
WCHAR rootName [3] = {szPath [0], L':', L'\0'};
return std::wstring (rootName);
}
std::wstring GetSafeTimestampForFilename ()
{
::FILETIME ft;
GetSystemTimeAsFileTime (&ft);
SYSTEMTIME st;
FileTimeToSystemTime (&ft, &st);
std::wstringstream wss;
wss << std::setfill (L'0')
<< st.wYear
<< std::setw (2) << st.wMonth
<< std::setw (2) << st.wDay << L"_"
<< std::setw (2) << st.wHour
<< std::setw (2) << st.wMinute
<< std::setw (2) << st.wSecond
<< std::setw (3) << st.wMilliseconds;
return wss.str ();
}
size_t EnumFiles (
const std::wstring &lpDir,
const std::wstring &lpFilter,
std::vector <std::wstring> &aszOutput,
bool bOutputWithPath = false,
bool bSortByLetter = false,
bool bIncludeSubDir = false
) {
if (!bIncludeSubDir) aszOutput.clear ();
std::vector<std::wstring> filters;
size_t start = 0;
while (start < lpFilter.length ())
{
size_t pos = lpFilter.find (L'\\', start);
if (pos == std::wstring::npos) pos = lpFilter.length ();
filters.emplace_back (lpFilter.substr (start, pos - start));
start = pos + 1;
}
std::function <void (const std::wstring &, std::wstring)> enumDir;
enumDir = [&] (const std::wstring &physicalPath, std::wstring relativePath)
{
WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
if (hFind == INVALID_HANDLE_VALUE) return;
do {
if (wcscmp (ffd.cFileName, L".") == 0 ||
wcscmp (ffd.cFileName, L"..") == 0) continue;
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
const std::wstring newPhysical = physicalPath + L"\\" + ffd.cFileName;
std::wstring newRelative = relativePath;
if (isDir) {
if (bIncludeSubDir) {
newRelative += ffd.cFileName;
newRelative += L"\\";
enumDir (newPhysical, newRelative);
}
}
else
{
for (const auto &filter : filters)
{
if (PathMatchSpecW (ffd.cFileName, filter.c_str ()))
{
aszOutput.push_back
(
bOutputWithPath ? newPhysical : (relativePath + ffd.cFileName)
);
break;
}
}
}
} while (FindNextFileW (hFind, &ffd));
FindClose (hFind);
};
enumDir (lpDir, L"");
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
return aszOutput.size ();
}
std::wstring GetRelativePath (
const std::wstring &pszBaseDir,
const std::wstring &pszFullPath,
DWORD cchRelative
) {
std::vector <WCHAR> szBase (Max <size_t> (pszBaseDir.length (), pszFullPath.length (), MAX_PATH) + 1);
wcscpy_s (szBase.data (), MAX_PATH, pszBaseDir.c_str ());
if (szBase [wcslen (szBase.data ()) - 1] != L'\\')
{
wcscat_s (szBase.data (), MAX_PATH, L"\\");
}
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, szBase.size ()) + 1);
BOOL res = PathRelativePathToW (
buf.data (),
szBase.data (),
FILE_ATTRIBUTE_DIRECTORY,
pszFullPath.c_str (),
FILE_ATTRIBUTE_NORMAL
);
if (res) return buf.data ();
else return L"";
}
size_t EnumDirectory (
const std::wstring &lpDir,
std::vector<std::wstring> &aszOutput,
bool bOutputWithPath = false,
bool bSortByLetter = false,
bool bIncludeSubDir = false
) {
aszOutput.clear ();
std::function <void (const std::wstring &, const std::wstring &)> enumDir;
enumDir = [&] (const std::wstring &physicalPath, const std::wstring &relativePath) {
WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
if (hFind == INVALID_HANDLE_VALUE) return;
do
{
const std::wstring name = ffd.cFileName;
if (name == L"." || name == L"..") continue;
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
std::wstring newPhysical = physicalPath + L"\\" + name;
std::wstring newRelative = relativePath + name;
if (isDir)
{
if (bIncludeSubDir) enumDir (newPhysical, newRelative + L"\\");
if (bOutputWithPath) aszOutput.push_back (newPhysical);
else aszOutput.push_back (newRelative);
}
} while (FindNextFileW (hFind, &ffd));
FindClose (hFind);
};
enumDir (lpDir, L"");
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
return aszOutput.size ();
}
static DWORD CALLBACK ProgressRoutine (
LARGE_INTEGER TotalFileSize,
LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER /*StreamSize*/,
LARGE_INTEGER /*StreamBytesTransferred*/,
DWORD /*dwStreamNumber*/,
DWORD /*dwCallbackReason*/,
HANDLE /*hSourceFile*/,
HANDLE /*hDestinationFile*/,
LPVOID lpData
) {
auto *pCallback = reinterpret_cast <std::function <void (int)> *> (lpData);
if (pCallback && *pCallback)
{
int progress = static_cast <int> (
(TotalBytesTransferred.QuadPart * 100) / TotalFileSize.QuadPart
);
(*pCallback) (progress);
}
return PROGRESS_CONTINUE;
}
bool RenameFileW (
const std::wstring &lpSrcPath,
const std::wstring &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressW (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameFileA (
const std::string &lpSrcPath,
const std::string &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressA (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameFileW (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
{
struct BuildTask
{
LPWSTR src = nullptr, dest = nullptr;
~BuildTask ()
{
if (src != nullptr)
{
delete [] src;
src = nullptr;
}
if (dest != nullptr)
{
delete [] dest;
dest = nullptr;
}
}
};
BuildTask bt;
bt.src = new WCHAR [lpSrcDir.length () + lpSrcName.length () + 2];
bt.dest = new WCHAR [lpSrcDir.length () + lpDestName.length () + 2];
PathCombineW (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
PathCombineW (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
return RenameFileW (bt.src, bt.dest, fProgress);
}
bool RenameFileA (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
{
struct BuildTask
{
LPSTR src = nullptr, dest = nullptr;
~BuildTask ()
{
if (src != nullptr)
{
delete [] src;
src = nullptr;
}
if (dest != nullptr)
{
delete [] dest;
dest = nullptr;
}
}
};
BuildTask bt;
bt.src = new CHAR [lpSrcDir.length () + lpSrcName.length () + 2];
bt.dest = new CHAR [lpSrcDir.length () + lpDestName.length () + 2];
PathCombineA (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
PathCombineA (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
return RenameFileA (bt.src, bt.dest, fProgress);
}
bool RenameFile (const std::wstring &lpSrcPath, const std::wstring &lpDestPath, std::function <void (int)> fProgress = nullptr)
{
return RenameFileW (lpSrcPath, lpDestPath, fProgress);
}
bool RenameFile (const std::string &lpSrcPath, const std::string &lpDestPath, std::function <void (int)> fProgress = nullptr)
{
return RenameFileA (lpSrcPath, lpDestPath, fProgress);
}
bool RenameFile (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
{
return RenameFileW (lpSrcDir, lpSrcName, lpDestName, fProgress);
}
bool RenameFile (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
{
return RenameFileA (lpSrcDir, lpSrcName, lpDestName, fProgress);
}
bool RenameDirectoryW (
const std::wstring &lpSrcPath,
const std::wstring &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressW (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameDirectoryA (
const std::string &lpSrcPath,
const std::string &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressA (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameDirectoryW (
const std::wstring &lpParentDir,
const std::wstring &lpSrcName,
const std::wstring &lpDestName,
std::function <void (int)> fProgress = nullptr
) {
struct PathBuilder
{
LPWSTR src = nullptr;
LPWSTR dest = nullptr;
~PathBuilder ()
{
delete [] src;
delete [] dest;
}
} pb;
pb.src = new WCHAR [lpParentDir.length () + lpSrcName.length () + 2];
pb.dest = new WCHAR [lpParentDir.length () + lpDestName.length () + 2];
PathCombineW (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
PathCombineW (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
return RenameDirectoryW (pb.src, pb.dest, fProgress);
}
bool RenameDirectoryA (
const std::string &lpParentDir,
const std::string &lpSrcName,
const std::string &lpDestName,
std::function <void (int)> fProgress = nullptr
) {
struct PathBuilder
{
LPSTR src = nullptr;
LPSTR dest = nullptr;
~PathBuilder ()
{
delete [] src;
delete [] dest;
}
} pb;
pb.src = new CHAR [lpParentDir.length () + lpSrcName.length () + 2];
pb.dest = new CHAR [lpParentDir.length () + lpDestName.length () + 2];
PathCombineA (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
PathCombineA (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
return RenameDirectoryA (pb.src, pb.dest, fProgress);
}
bool RenameDirectory (
const std::wstring &src,
const std::wstring &dst,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryW (src, dst, fProgress);
}
bool RenameDirectory (
const std::string &src,
const std::string &dst,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryA (src, dst, fProgress);
}
bool RenameDirectory (
const std::wstring &parentDir,
const std::wstring &srcName,
const std::wstring &dstName,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryW (parentDir, srcName, dstName, fProgress);
}
bool RenameDirectory (
const std::string &parentDir,
const std::string &srcName,
const std::string &dstName,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryA (parentDir, srcName, dstName, fProgress);
}
std::wstring CombinePath (const std::wstring &left, const std::wstring &right)
{
std::vector <WCHAR> buf (left.capacity () + right.capacity () + 2);
PathCombineW (buf.data (), left.c_str (), right.c_str ());
return buf.data ();
}
#ifdef PathCommonPrefix
#undef PathCommonPrefix
#endif
std::wstring PathCommonPrefix (const std::wstring &file1, const std::wstring &file2)
{
std::vector <WCHAR> buf (Max <size_t> (file1.capacity (), file2.capacity (), MAX_PATH) + 2);
PathCommonPrefixW (file1.c_str (), file2.c_str (), buf.data ());
return buf.data ();
}
#undef GetFullPathName
std::wstring GetFullPathName (const std::wstring &lpFileName)
{
if (lpFileName.empty ()) return L"";
DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
if (length == 0) return L"";
std::vector <WCHAR> buffer (length + 1, L'\0');
DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
if (result == 0) return L"";
return std::wstring (buffer.data (), result);
}
bool PathEquals (const std::wstring &path1, const std::wstring &path2)
{
size_t maxlen = Max <size_t> (path1.capacity () + 1, path2.capacity () + 1, MAX_PATH);
std::vector <WCHAR> buf1 (maxlen), buf2 (maxlen);
PathCanonicalizeW (buf1.data (), path1.c_str ());
PathCanonicalizeW (buf2.data (), path2.c_str ());
return IsNormalizeStringEquals (buf1.data (), buf2.data ());
}

51
pkgread/module.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <Windows.h>
#ifdef __cplusplus
#ifndef GetCurrentModule_bRefDefault
// 在 C++ 中GetCurrentModule 将会启用默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
#define GetCurrentModule_bRefDefault = FALSE
#endif
#else
#define GetCurrentModule_bRefDefault
#endif
HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
{
HMODULE hModule = NULL;
if (GetModuleHandleExW (bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCWSTR)GetCurrentModule, &hModule))
{
return hModule;
}
return NULL;
}
HMODULE GetSelfModuleHandle ()
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery (GetSelfModuleHandle, &mbi, sizeof (mbi)) != 0)
? (HMODULE)mbi.AllocationBase : NULL);
}
#ifndef GetModuleHandleW_lpModuleNameDefault
#define GetModuleHandleW_lpModuleNameDefault NULL
#endif
#ifndef DEFAULT_HMODULE
#ifdef HMODULE_MODE_EXE
#define DEFAULT_HMODULE GetModuleHandleW (NULL)
#elif defined (HMODULE_MODE_DLL1)
#define DEFAULT_HMODULE GetCurrentModule ()
#elif defined (HMODULE_MODE_DLL2)
#define DEFAULT_HMODULE GetSelfModuleHandle ()
#else
#define DEFAULT_HMODULE GetModuleHandleW (GetModuleHandleW_lpModuleNameDefault)
#endif
#endif
#undef GetModuleHandleW_lpModuleNameDefault
#ifdef __cplusplus
#ifndef hModule_DefaultParam
// 在 C++ 中你可以使用此宏“hModule_DefaultParam”来用于给一些函数的形参定义默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)。
#define hModule_DefaultParam = DEFAULT_HMODULE
#endif
#else
#define hModule_DefaultParam
#endif

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SQLite" version="3.12.2" targetFramework="native" />
<package id="pugixml" version="1.15.0" targetFramework="native" />
</packages>

View File

@@ -1171,3 +1171,46 @@ LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWS
if (lpBase64Head) *lpBase64Head = retptr + head;
return retptr;
}
LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName)
{
auto ptr = ToPtrPackage (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto read = ptr->appx_reader ();
auto pre = read.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
auto str = GetPrerequistOSVersionDescription (ver);
return _wcsdup (str.c_str ());
} break;
case PackageType::bundle: {
auto br = ptr->bundle_reader ();
CComPtr <IAppxFile> iaf;
if (FAILED (br.random_application_package (&iaf))) return nullptr;
CComPtr <IStream> ist;
if (FAILED (iaf->GetStream (&ist))) return nullptr;
CComPtr <IAppxPackageReader> iar;
if (FAILED (GetAppxPackageReader (ist, &iar))) return nullptr;
appxreader read (iar.p);
auto pre = read.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
auto str = GetPrerequistOSVersionDescription (ver);
return _wcsdup (str.c_str ());
}
default:
break;
}
return nullptr;
}
LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName)
{
if (!lpCapabilityName) return nullptr;
std::wnstring capname = (lpCapabilityName ? lpCapabilityName : L"");
if (capname.empty ()) return nullptr;
std::wstring ret = GetCapabilityDisplayName (capname);
if (IsNormalizeStringEmpty (ret)) return nullptr;
else return _wcsdup (ret.c_str ());
}

View File

@@ -251,6 +251,7 @@ extern "C"
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_)
PKGREAD_API LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
// File Stream
// 从 Appx 包中获取 Appx 中的文件的文件流。
@@ -282,6 +283,9 @@ extern "C"
PKGREAD_API LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head);
// 获取 AppxBundle 包中的应用包文件流。最后通过 DestroyAppxFileStream 销毁。
PKGREAD_API HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader);
// 获取功能名的显示名,如 internetClient 对应“访问您的 Internet 连接”。返回的是适应于系统区域语言的文本。
// 注意:返回的字符串一定要通过 free 释放。
PKGREAD_API LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -320,6 +324,35 @@ const std::vector <std::wstring> g_filepathitems =
L"Wide310x150Logo",
L"Executable"
};
std::map <std::wstring, std::wstring> g_capnamemap;
std::wstring GetPackageCapabilityDisplayName (const std::wstring &capname)
{
try
{
if (g_capnamemap.find (capname) != g_capnamemap.end () && !g_capnamemap.at (capname).empty ()) return g_capnamemap.at (capname);
else
{
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
std::wstring ret = L"";
ret += lpstr ? lpstr : L"";
if (lpstr) free (lpstr);
lpstr = nullptr;
g_capnamemap [capname] = ret;
return ret;
}
}
catch (...)
{
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
std::wstring ret = L"";
ret += lpstr ? lpstr : L"";
if (lpstr) free (lpstr);
lpstr = nullptr;
g_capnamemap [capname] = ret;
return ret;
}
return L"";
}
class package_reader
{
private:
@@ -984,6 +1017,17 @@ class package_reader
}
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); }
std::wstring get_description (const std::wstring &name) const
{
LPWSTR lpstr = GetPackagePrerequistieSystemVersionName (hReader, name.c_str ());
deconstr relt ([&lpstr] () {
if (lpstr) free (lpstr);
lpstr = nullptr;
});
return lpstr ? lpstr : L"";
}
std::wstring os_min_version_description () const { return get_description (PKG_PREREQUISITE_OS_MIN_VERSION); }
std::wstring os_max_version_tested_description () const { return get_description (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
};
package_reader (): hReader (CreatePackageReader ()) {}
package_reader (const std::wstring &fpath): hReader (CreatePackageReader ())

Binary file not shown.

View File

@@ -86,13 +86,13 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;HMODULE_MODE_DLL1;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>urlmon.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>urlmon.lib;crypt32.lib;version.lib;xmllite.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -115,7 +115,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;HMODULE_MODE_DLL1;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
@@ -123,7 +123,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>urlmon.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>urlmon.lib;crypt32.lib;version.lib;xmllite.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -148,17 +148,22 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="dynarr.h" />
<ClInclude Include="filepath.h" />
<ClInclude Include="localeex.h" />
<ClInclude Include="module.h" />
<ClInclude Include="norstr.h" />
<ClInclude Include="pkgread.h" />
<ClInclude Include="raii.h" />
<ClInclude Include="rctools.h" />
<ClInclude Include="readobj.h" />
<ClInclude Include="resource1.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="strcmp.h" />
<ClInclude Include="stringres.h" />
<ClInclude Include="syncutil.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="themeinfo.h" />
<ClInclude Include="typestrans.h" />
<ClInclude Include="version.h" />
</ItemGroup>
<ItemGroup>
@@ -185,12 +190,19 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<ResourceCompile Include="pkgread.rc" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pkgread.rc" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\pugixml.1.15.0\build\native\pugixml.targets" Condition="Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\pugixml.1.15.0\build\native\pugixml.targets'))" />
</Target>
</Project>

View File

@@ -57,6 +57,21 @@
<ClInclude Include="themeinfo.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="module.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="rctools.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="filepath.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="typestrans.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="strcmp.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@@ -69,12 +84,12 @@
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pkgread.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

121
pkgread/rctools.h Normal file
View File

@@ -0,0 +1,121 @@
#pragma once
#include <Windows.h>
#include <WinBase.h>
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "typestrans.h"
#include "module.h"
// 返回的指针如果非空则一定需要用 free 释放
LPWSTR GetRCStringW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _wcsdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringW;
}
else return _wcsdup (buf.data ());
}
}
// 返回的指针如果非空则一定需要用 free 释放
LPSTR GetRCStringA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _strdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringA;
}
else return _strdup (buf.data ());
}
}
HICON LoadRCIcon (UINT resID, HMODULE hModule hModule_DefaultParam)
{
return (HICON)LoadImageW (hModule, MAKEINTRESOURCEW (resID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
}
HRSRC FindResourceByName (LPCWSTR resourceName, LPCWSTR resourceType, HMODULE hModule hModule_DefaultParam)
{
return FindResourceW (hModule, resourceName, resourceType);
}
#ifdef __cplusplus
#include <string>
std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSW;
}
else return buf.data ();
}
}
std::string GetRCStringSA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSA;
}
else return buf.data ();
}
}
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
String ^GetRCStringCli (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringCli:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return gcnew String (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringCli;
}
else return gcnew String (buf.data ());
}
}
#define GetRCIntValue(_UINT__resID_) toInt (GetRCStringCli (_UINT__resID_))
#define GetRCDoubleValue(_UINT__resID_) toDouble (GetRCStringCli (_UINT__resID_))
#define GetRCBoolValue(_UINT__resID_) toBool (GetRCStringCli (_UINT__resID_))
#define GetRCDateTimeValue(_UINT__resID_) toDateTime (GetRCStringCli (_UINT__resID_))
#define rcString(resID) GetRCStringCli (resID)
#define rcInt(resID) GetRCIntValue (resID)
#define rcDouble(resID) GetRCDoubleValue (resID)
#define rcBool(resID) GetRCBoolValue (resID)
#define rcDTime(resID) GetRCDateTimeValue (resID)
#define rcIcon(resID) LoadRCIcon (resID)
#endif

View File

@@ -9,27 +9,14 @@
#include <atlbase.h>
#include <functional>
#include <utility>
#include <xmllite.h>
#include "dynarr.h"
#include "version.h"
#include "stringres.h"
#include "norstr.h"
#include "raii.h"
#include "priformatcli.h"
bool IsFileExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
bool IsFileExists (std::string filePath) { return IsFileExistsA (filePath.c_str ()); }
bool IsFileExists (std::wstring filePath) { return IsFileExistsW (filePath.c_str ()); }
#include "filepath.h"
HRESULT GetBundleReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxBundleReader** bundleReader)
{
@@ -615,9 +602,53 @@ namespace appx_info
{
using Base = com_info <IAppxManifestDeviceCapabilitiesEnumerator>;
APPX_CAPABILITIES cflags;
std::vector <std::wnstring> cnames;
public:
using Base::Base;
appx_capabs (IAppxManifestDeviceCapabilitiesEnumerator *devicec, APPX_CAPABILITIES capa): cflags (capa), com_info (devicec) {}
appx_capabs (IAppxManifestDeviceCapabilitiesEnumerator *devicec, APPX_CAPABILITIES capa, IAppxManifestReader *&r): cflags (capa), com_info (devicec)
{
if (!r) return;
CComPtr <IStream> xmlstream;
if (FAILED (r->GetStream (&xmlstream))) return;
CComPtr <IXmlReader> xmlreader;
if (FAILED (CreateXmlReader (__uuidof (IXmlReader), (void **)&xmlreader, nullptr))) return;
xmlreader->SetInput (xmlstream.p);
XmlNodeType nodeType;
bool inPackage = false;
bool inCapabilities = false;
HRESULT hr = S_OK;
auto &reader = xmlreader;
while (SUCCEEDED (hr = xmlreader->Read (&nodeType)) && hr == S_OK)
{
if (nodeType == XmlNodeType_Element)
{
LPCWSTR localName = nullptr;
reader->GetLocalName (&localName, nullptr);
// <Package>
if (!inPackage && _wcsicmp (localName, L"Package") == 0) inPackage = true;
// <Capabilities>
else if (inPackage && !inCapabilities && _wcsicmp (localName, L"Capabilities") == 0) inCapabilities = true;
// <Capability>
else if (inCapabilities && _wcsicmp (localName, L"Capability") == 0)
{
if (SUCCEEDED (reader->MoveToAttributeByName (L"Name", nullptr)))
{
LPCWSTR value = nullptr;
reader->GetValue (&value, nullptr);
if (value && *value) cnames.push_back (value);
}
reader->MoveToElement ();
}
}
else if (nodeType == XmlNodeType_EndElement)
{
LPCWSTR localName = nullptr;
reader->GetLocalName (&localName, nullptr);
if (inCapabilities && _wcsicmp (localName, L"Capabilities") == 0) inCapabilities = false;
else if (inPackage && _wcsicmp (localName, L"Package") == 0) break;
}
}
}
appx_capabs () = default;
APPX_CAPABILITIES capabilities () const { return cflags; }
size_t device_capabilities (_Out_ std::vector <std::wstring> &output) const
@@ -634,7 +665,8 @@ namespace appx_info
size_t capabilities_names (_Out_ std::vector <std::wstring> &output) const
{
output.clear ();
CapabilitiesFlagsToNames (cflags, output);
if (cnames.empty ()) CapabilitiesFlagsToNames (cflags, output);
else for (auto &it : cnames) output.push_back (it);
return output.size ();
}
// 获取功能和设备功能的所有功能名
@@ -889,8 +921,9 @@ class appxreader: virtual public com_info_quote <IAppxPackageReader>
{
APPX_CAPABILITIES caps;
IAppxManifestDeviceCapabilitiesEnumerator *ip = nullptr;
get_device_capabilities (&ip);
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps);
CComPtr <IAppxManifestReader> im;
if (SUCCEEDED (manifest (&im))) im->GetDeviceCapabilities (&ip);
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps, im.p);
return appx_info::appx_capabs (ip);
}
HRESULT get_dependencies (_Outptr_ IAppxManifestPackageDependenciesEnumerator **output) const { return get_from_manifest <IAppxManifestPackageDependenciesEnumerator *> (&Manifest::GetPackageDependencies, output); }

Binary file not shown.

154
pkgread/strcmp.h Normal file
View File

@@ -0,0 +1,154 @@
#pragma once
#include <Shlwapi.h>
#include "norstr.h"
#ifdef __cplusplus
#define ptrnull(ptr) (!(ptr))
#else
#define ptrnull(ptr) ((ptr) == NULL)
#endif
#define ptrvalid(ptr) (!ptrnull (ptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL判断是否为非空字符串指针有效且长度大于 0。千万不能是野指针否则一定会崩溃
#define strvalid(strptr) (ptrvalid (strptr) && *(strptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL判断是否为空字符串指针为 NULL 或长度为 0。千万不能是野指针否则一定会崩溃
#define strnull(strptr) (ptrnull (strptr) || !*(strptr))
typedef std::wnstring strlabel, StringLabel;
std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); }
std::string StringTrim (const std::string &str) { return std::nstring::trim (str); }
#define StringToUpper l0km::toupper
#define StringToLower l0km::tolower
int LabelCompare (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::compare (l1, l2);
}
int LabelCompare (const std::string &l1, const std::string &l2)
{
return std::nstring::compare (l1, l2);
}
bool LabelEqual (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEqual (const std::string &l1, const std::string &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); }
bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); }
#define LabelNoEmpty(_str_) (!LabelEmpty (_str_))
int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
// 该函数帮助构成 "<str1>\0<str2>\0" 这种字符串,用于通用对话框中的文件框
LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize)
{
if (!dest || !endwith || bufsize == 0)
return dest;
if (dest [0] == L'\0' && bufsize > 1)
{
dest [1] = L'\0';
}
size_t pos = 0;
while (pos < bufsize - 1)
{
if (dest [pos] == L'\0' && dest [pos + 1] == L'\0')
{
if (dest [0]) pos ++;
break;
}
pos ++;
}
size_t i = 0;
while (pos < bufsize - 1 && endwith [i] != L'\0')
{
dest [pos ++] = endwith [i ++];
}
if (pos < bufsize)
{
dest [pos] = L'\0';
}
return dest;
}
// 取文本左边注意长度指的是文本字符数比如“ch”的长度为2
std::wstring GetStringLeft (const std::wstring &str, size_t length)
{
std::vector <WCHAR> buf (length + 1);
lstrcpynW (buf.data (), str.c_str (), length + 1);
return buf.data ();
}
// 取文本右边
std::wstring GetStringRight (const std::wstring &str, size_t length)
{
if (length >= str.length ()) return str;
return str.substr (str.length () - length, length).c_str ();
}

View File

@@ -1,10 +1,16 @@
#pragma once
#include <string>
#include <map>
#include <pugiconfig.hpp>
#include <pugixml.hpp>
#include "version.h"
#include "dynarr.h"
#include "norstr.h"
#include "syncutil.h"
#include "resource1.h"
#include "localeex.h"
#include "rctools.h"
#include "filepath.h"
static const std::pair <UINT64, LPCWSTR> captable [] = {
{APPX_CAPABILITY_INTERNET_CLIENT, L"internetClient"},
{APPX_CAPABILITY_INTERNET_CLIENT_SERVER, L"internetClientServer"},
@@ -124,3 +130,201 @@ bool RemoveApplicationAttributeItem (const std::wstring &lpstr)
}
return false;
}
#define MAKENAMEIDMAP(_Res_Name_) {#_Res_Name_, _Res_Name_}
std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (accessoryManager),
MAKENAMEIDMAP (activity),
MAKENAMEIDMAP (allJoyn),
MAKENAMEIDMAP (allowElevation),
MAKENAMEIDMAP (appDiagnostics),
MAKENAMEIDMAP (applicationData),
MAKENAMEIDMAP (applicationPackage),
MAKENAMEIDMAP (appLicensing),
MAKENAMEIDMAP (appointments),
MAKENAMEIDMAP (appointmentsSystem),
MAKENAMEIDMAP (appointmentSystem),
MAKENAMEIDMAP (authenticationManagerAuthentication),
MAKENAMEIDMAP (blockedChatMessages),
MAKENAMEIDMAP (bluetooth),
MAKENAMEIDMAP (bluetooth_genericAttributeProfile),
MAKENAMEIDMAP (bluetooth_rfcomm),
MAKENAMEIDMAP (broadFileSystemAccess),
MAKENAMEIDMAP (callHistory),
MAKENAMEIDMAP (callHistorySystem),
MAKENAMEIDMAP (cellularDeviceControl),
MAKENAMEIDMAP (cellularDeviceIdentity),
MAKENAMEIDMAP (cellularMessaging),
MAKENAMEIDMAP (chat),
MAKENAMEIDMAP (chatSystem),
MAKENAMEIDMAP (codeGeneration),
MAKENAMEIDMAP (confirmAppClose),
MAKENAMEIDMAP (contacts),
MAKENAMEIDMAP (contactsSystem),
MAKENAMEIDMAP (contactSystem),
MAKENAMEIDMAP (cortanaSpeechAccessory),
MAKENAMEIDMAP (customInstallActions),
MAKENAMEIDMAP (deviceManagementDmAccount),
MAKENAMEIDMAP (deviceManagementEmailAccount),
MAKENAMEIDMAP (deviceManagementFoundation),
MAKENAMEIDMAP (deviceManagementWapSecurityPolicies),
MAKENAMEIDMAP (deviceMangementFoundation),
MAKENAMEIDMAP (deviceUnlock),
MAKENAMEIDMAP (documentsLibrary),
MAKENAMEIDMAP (dualSimTiles),
MAKENAMEIDMAP (email),
MAKENAMEIDMAP (emailSystem),
MAKENAMEIDMAP (enterpriseAuthentication),
MAKENAMEIDMAP (enterpriseDataPolicy),
MAKENAMEIDMAP (enterpriseDeviceLockdown),
MAKENAMEIDMAP (extendedExecutionBackgroundAudio),
MAKENAMEIDMAP (extendedExecutionCritical),
MAKENAMEIDMAP (extendedExecutionUnconstrained),
MAKENAMEIDMAP (externalDependenciesVirtualCapability),
MAKENAMEIDMAP (firstSignInSettings),
MAKENAMEIDMAP (gameList),
MAKENAMEIDMAP (humaninterfacedevice),
MAKENAMEIDMAP (hyperLinkLearnMore),
MAKENAMEIDMAP (inputForegroundObservation),
MAKENAMEIDMAP (inputInjection),
MAKENAMEIDMAP (inputInjection_Brokered),
MAKENAMEIDMAP (inputObservation),
MAKENAMEIDMAP (inputSuppression),
MAKENAMEIDMAP (internetClient),
MAKENAMEIDMAP (internetClientServer),
MAKENAMEIDMAP (interopServices),
MAKENAMEIDMAP (localSystemServices),
MAKENAMEIDMAP (location),
MAKENAMEIDMAP (locationHistory),
MAKENAMEIDMAP (locationSystem),
MAKENAMEIDMAP (lockScreenCreatives),
MAKENAMEIDMAP (lowLevelDevices),
MAKENAMEIDMAP (microphone),
MAKENAMEIDMAP (modifiableApp),
MAKENAMEIDMAP (musicLibrary),
MAKENAMEIDMAP (networkConnectionManagerProvisioning),
MAKENAMEIDMAP (networkDataPlanProvisioning),
MAKENAMEIDMAP (networkingVpnProvider),
MAKENAMEIDMAP (objects3d),
MAKENAMEIDMAP (oemDeployment),
MAKENAMEIDMAP (oemPublicDirectory),
MAKENAMEIDMAP (optical),
MAKENAMEIDMAP (packagedServices),
MAKENAMEIDMAP (packageManagement),
MAKENAMEIDMAP (packagePolicySystem),
MAKENAMEIDMAP (packageQuery),
MAKENAMEIDMAP (packageWriteRedirectionCompatibilityShim),
MAKENAMEIDMAP (phoneCall),
MAKENAMEIDMAP (phoneCallHistory),
MAKENAMEIDMAP (phoneCallHistoryPublic),
MAKENAMEIDMAP (phoneCallHistorySystem),
MAKENAMEIDMAP (picturesLibrary),
MAKENAMEIDMAP (pointOfService),
MAKENAMEIDMAP (previewStore),
MAKENAMEIDMAP (previewUiComposition),
MAKENAMEIDMAP (privateNetworkClientServer),
MAKENAMEIDMAP (proximity),
MAKENAMEIDMAP (recordedCallsFolder),
MAKENAMEIDMAP (remotePassportAuthentication),
MAKENAMEIDMAP (removableStorage),
MAKENAMEIDMAP (runFullTrust),
MAKENAMEIDMAP (screenDuplication),
MAKENAMEIDMAP (sharedUserCertificates),
MAKENAMEIDMAP (smsSend),
MAKENAMEIDMAP (spatialPerception),
MAKENAMEIDMAP (systemManagement),
MAKENAMEIDMAP (teamEditionExperience),
MAKENAMEIDMAP (uiAccess),
MAKENAMEIDMAP (unvirtualizedResources),
MAKENAMEIDMAP (usb),
MAKENAMEIDMAP (userAccountInformation),
MAKENAMEIDMAP (userDataAccountSetup),
MAKENAMEIDMAP (userDataAccountsProvider),
MAKENAMEIDMAP (userDataSystem),
MAKENAMEIDMAP (userPrincipalName),
MAKENAMEIDMAP (userSigninSupport),
MAKENAMEIDMAP (videosLibrary),
MAKENAMEIDMAP (visualElementsSystem),
MAKENAMEIDMAP (visualVoiceMail),
MAKENAMEIDMAP (voipCall),
MAKENAMEIDMAP (walletSystem),
MAKENAMEIDMAP (webcam),
MAKENAMEIDMAP (wiFiControl),
MAKENAMEIDMAP (xboxAccessoryManagement)
};
#ifdef MAKENAMEIDMAP
#undef MAKENAMEIDMAP
#endif
std::string GetSuitableLanguageValue (const std::map <std::nstring, std::string> &map, const std::nstring &localename)
{
for (auto &it : map) if (it.first == localename) return it.second;
for (auto &it : map) if (LocaleNameCompare (pugi::as_wide (it.first), pugi::as_wide (localename))) return it.second;
for (auto &it : map) if (IsNormalizeStringEquals (GetLocaleRestrictedCodeA (it.first), GetLocaleRestrictedCodeA (localename))) return it.second;
for (auto &it : map) if (LocaleNameCompare (pugi::as_wide (GetLocaleRestrictedCodeA (it.first)), pugi::as_wide (GetLocaleRestrictedCodeA (localename)))) return it.second;
return "";
}
std::string GetSuitableLanguageValue (const std::map <std::nstring, std::string> &map)
{
if (map.empty ()) return "";
std::string ret = GetSuitableLanguageValue (map, pugi::as_utf8 (GetComputerLocaleCodeW ()));
if (ret.empty ()) ret = GetSuitableLanguageValue (map, "en-US");
if (ret.empty ()) ret = map.begin ()->second;
return ret;
}
struct xmldoc
{
pugi::xml_document doc;
bool isvalid = false;
void destroy ()
{
if (isvalid) doc.reset ();
isvalid = false;
}
bool create (const std::wstring &filepath)
{
destroy ();
auto res = doc.load_file (filepath.c_str ());
return isvalid = res;
}
xmldoc (const std::wstring &filepath) { create (filepath); }
~xmldoc () { destroy (); }
std::string get (const std::string &id) const
{
auto root = doc.first_child ();
auto nodes = root.children ();
for (auto &it : nodes)
{
if (IsNormalizeStringEquals (std::string (it.attribute ("id").as_string ()), id))
{
auto strings = it.children ();
std::map <std::nstring, std::string> lang_value;
for (auto &sub : strings)
{
std::nstring lang = sub.attribute ("name").as_string ();
if (!lang.empty ()) lang_value [lang] = sub.text ().get ();
}
return GetSuitableLanguageValue (lang_value);
}
}
return "";
}
std::wstring get (const std::wstring &id) const { return pugi::as_wide (get (pugi::as_utf8 (id))); }
std::wstring operator [] (const std::wstring &id) const { return get (id); }
std::wstring operator [] (const std::wstring &id) { return get (id); }
std::string operator [] (const std::string &id) const { return get (id); }
std::string operator [] (const std::string &id) { return get (id); }
} cap_localeres (CombinePath (GetProgramRootDirectoryW (), L"locale\\capabilities.xml"));
std::wstring GetCapabilityDisplayName (const std::wstring &capname)
{
std::nstring searchname = pugi::as_utf8 (capname);
std::wstring ret = cap_localeres [capname];
if (IsNormalizeStringEmpty (ret))
{
for (auto &it : g_nameToId)
{
if (it.first == searchname) return GetRCStringSW (it.second);
}
}
else return ret;
return L"";
}

265
pkgread/typestrans.h Normal file
View File

@@ -0,0 +1,265 @@
#pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <Windows.h>
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstdbool>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#endif
unsigned _wtou (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%u", &value);
}
return value;
}
unsigned long _wtoul (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%lu", &value);
}
return value;
}
unsigned long long _wtou64 (const wchar_t *str)
{
unsigned long long value = 0;
if (str)
{
swscanf (str, L"%llu", &value);
}
return value;
}
double _wtod (const wchar_t *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (swscanf (str, L"%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
unsigned atou (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%u", &value);
}
return value;
}
unsigned long atoul (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%lu", &value);
}
return value;
}
unsigned long long atou64 (const char *str)
{
unsigned long long value = 0;
if (str)
{
sscanf (str, "%llu", &value);
}
return value;
}
double atod (const char *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (sscanf (str, "%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
int8_t atoi8 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int8_t)value;
}
int16_t atoi16 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int16_t)value;
}
int32_t atoi32 (const char *str)
{
int32_t value = 0;
if (str) sscanf (str, "%d", &value);
return value;
}
uint8_t atoui8 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint8_t)value;
}
uint16_t atoui16 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint16_t)value;
}
uint32_t atoui32 (const char *str)
{
uint32_t value = 0;
if (str) sscanf (str, "%u", &value);
return value;
}
int8_t _wtoi8 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int8_t)value;
}
int16_t _wtoi16 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int16_t)value;
}
int32_t _wtoi32 (const wchar_t *str)
{
int32_t value = 0;
if (str) swscanf (str, L"%d", &value);
return value;
}
uint8_t _wtoui8 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint8_t)value;
}
uint16_t _wtoui16 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint16_t)value;
}
uint32_t _wtoui32 (const wchar_t *str)
{
uint32_t value = 0;
if (str) swscanf (str, L"%u", &value);
return value;
}
int64_t atoi64 (const char *str)
{
int64_t value = 0;
if (str) sscanf (str, "%lld", &value);
return value;
}
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
EXTERN_C bool StringToBoolA (const char *str)
{
char buf [32] = {0};
strcpy (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !strcmp (buf, "true") ||
!strcmp (buf, "yes") ||
!strcmp (buf, "ok") ||
!strcmp (buf, "sure") ||
!strcmp (buf, "okay") ||
!strcmp (buf, "zhen") ||
!strcmp (buf, "");
}
EXTERN_C bool StringToBoolW (const WCHAR *str)
{
WCHAR buf [32] = {0};
lstrcpyW (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !lstrcmpW (buf, L"true") ||
!lstrcmpW (buf, L"yes") ||
!lstrcmpW (buf, L"ok") ||
!lstrcmpW (buf, L"sure") ||
!lstrcmpW (buf, L"okay") ||
!lstrcmpW (buf, L"zhen") ||
!lstrcmpW (buf, L"");
}
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
#ifdef __cplusplus
int StringToInt (LPCSTR str) { return StringToIntA (str); }
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
long StringToLong (LPCSTR str) { return StringToLongA (str); }
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
bool objToBool (Object ^result)
{
if (!result) return false;
try
{
String ^strValue = safe_cast <String ^> (result);
return (strValue->ToLower () == "on");
}
catch (InvalidCastException ^)
{
try
{
return Convert::ToBoolean (result);
}
catch (InvalidCastException ^)
{
return false;
}
}
return false;
}
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
#endif

View File

@@ -24,6 +24,7 @@ body * {
margin: 0px;
padding: 0px;
border: 0px;
background-color: #f3f3f3;
}
.pagecontainer.full {
@@ -74,6 +75,17 @@ body * {
color: white;
}
.page.splash .content.splash .status-text {
width: 100%;
padding: 0 20px;
box-sizing: border-box;
margin-top: 10px;
overflow-y: hidden;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.page.splash .content.splash progress {
border-style: none;
background-color: transparent;
@@ -257,9 +269,53 @@ progress.win-ring:indeterminate::-ms-fill {
box-sizing: border-box;
transition: width 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), height 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), top 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), left 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), right 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), bottom 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), margin 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), padding 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
list-style-position: outside;
color: rgb(113, 113, 113);
/*test*/
border: 1px solid black;
padding: 5px;
/*border: 1px solid black;
padding: 5px;*/
}
.page .content p,
.page .content span,
.page .content h1,
.page .content label,
.page .content select,
.page .content .functions ul li,
.page .content .reason {
font-weight: normal;
}
.page .content .pkgtitle.multiple {
font-weight: bold;
-ms-overflow-x: hidden;
-ms-overflow-y: hidden;
-ms-text-overflow: ellipsis;
white-space: nowrap;
max-height: 1.3em;
max-width: 100%;
}
.page .content .pkgtitle.multiple span {
font-weight: bold;
-ms-overflow-x: hidden;
-ms-overflow-y: hidden;
-ms-text-overflow: ellipsis;
max-height: 1.3em;
white-space: nowrap;
max-width: 100%;
}
.pkgtitle span[data-overflow]::after {
content: "...";
}
.page>.content h1 {
font-size: 25pt;
margin-bottom: 8px;
}
.page>.content .pkgapplabel {
color: rgb(0, 120, 215);
}
.page>.progress {
@@ -273,6 +329,14 @@ progress.win-ring:indeterminate::-ms-fill {
box-sizing: border-box;
}
.content #moreinfo-flyout-content p>span:nth-child(1) {
-ms-user-select: none;
}
.content #moreinfo-flyout-content>span:nth-child(2) {
color: darkgray;
}
.progress * {
width: 100%;
}
@@ -364,7 +428,7 @@ progress.win-ring:indeterminate::-ms-fill {
}
.page.select>.controls.select>.command button:nth-of-type(2) {
display: none;
/*display: none;*/
}
.page.select>.content.select,
@@ -451,3 +515,31 @@ progress.win-ring:indeterminate::-ms-fill {
.page.installing.multiple>.content .currentfile br {
display: none;
}
@keyframes scale-visible {
from {
transform: translateX(50px) scale(0.8);
opacity: 0;
}
to {
transform: translateX(0) scale(1);
opacity: 1;
}
}
.page.installsuccess.multiple>.content.installsuccess * {
display: none;
}
.page.installsuccess.multiple>.content.installsuccess>.currentfile {
display: block;
}
.page.installsuccess.multiple>.content.installsuccess>.currentfile h1.title {
display: block;
}
.page.installsuccess>.controls.installsuccess>.command button:nth-of-type(2),
.page.installfailed>.controls.installsuccess>.command button:nth-of-type(2) {
display: none;
}

View File

@@ -0,0 +1,376 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动画效果测试</title>
<script type="text/javascript" src="js/module.js"></script>
<script type="text/javascript" src="js/polyfill-ie.js"></script>
<link rel="stylesheet" href="libs/winjs/2.0/css/ui-light.css">
<script type="text/javascript" src="libs/winjs/2.0/js/base.js"></script>
<script type="text/javascript" src="libs/winjs/2.0/js/ui.js"></script>
<script type="text/javascript" src="js/animation.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
padding: 20px;
overflow-x: auto;
overflow-y: auto;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 20px;
background: linear-gradient(135deg, #0067b8, #004e8c);
color: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
.description {
font-size: 1.1rem;
max-width: 800px;
margin: 0 auto;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.control-group {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
}
.control-group h3 {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
color: #0067b8;
}
.demo-area {
display: flex;
flex-direction: column;
align-items: center;
margin: 15px 0;
flex-grow: 1;
}
.demo-element {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #0067b8, #00a4ef);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
position: relative;
transition: all 0.3s;
}
.demo-element::after {
content: "动画元素";
font-size: 0.9rem;
text-align: center;
padding: 5px;
}
.animation-buttons {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
width: 100%;
}
button {
background-color: #0067b8;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s;
font-size: 14px;
width: 100%;
}
button:hover {
background-color: #004e8c;
}
.animation-status {
background: #f8f8f8;
padding: 10px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
min-height: 60px;
white-space: pre-wrap;
margin-top: 10px;
width: 100%;
}
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: #666;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.controls {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>动画效果测试</h1>
<p class="description">此页面展示animation.js中定义的所有动画效果。点击每个动画类别下的按钮来测试对应的动画。</p>
</header>
<div class="controls">
<div class="control-group">
<h3>弹出动画 (Flyout)</h3>
<div class="demo-area">
<div class="demo-element" id="flyoutElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Flyout.toTop', 'flyoutElement')">向顶端</button>
<button onclick="runAnimation('Flyout.toBottom', 'flyoutElement')">向底端</button>
<button onclick="runAnimation('Flyout.toLeft', 'flyoutElement')">向左</button>
<button onclick="runAnimation('Flyout.toRight', 'flyoutElement')">向右</button>
<button onclick="runAnimation('Flyout.fromBottom', 'flyoutElement')">从底端</button>
<button onclick="runAnimation('Flyout.fromTop', 'flyoutElement')">从顶端</button>
<button onclick="runAnimation('Flyout.fromLeft', 'flyoutElement')">从左侧</button>
<button onclick="runAnimation('Flyout.fromRight', 'flyoutElement')">从右侧</button>
</div>
<div class="animation-status" id="flyoutStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>渐变动画 (Opacity)</h3>
<div class="demo-area">
<div class="demo-element" id="opacityElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Opacity.visible', 'opacityElement')">显示</button>
<button onclick="runAnimation('Opacity.hidden', 'opacityElement')">消失</button>
</div>
<div class="animation-status" id="opacityStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>缩放动画 (Scale)</h3>
<div class="demo-area">
<div class="demo-element" id="scaleElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Scale.up', 'scaleElement')">放大</button>
<button onclick="runAnimation('Scale.down', 'scaleElement')">缩小</button>
</div>
<div class="animation-status" id="scaleStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>默认动画 (Default)</h3>
<div class="demo-area">
<div class="demo-element" id="defaultElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Default.remove', 'defaultElement')">从右返回</button>
<button onclick="runAnimation('Default.removertl', 'defaultElement')">从左返回</button>
<button onclick="runAnimation('Default.apply', 'defaultElement')">向右移动</button>
<button onclick="runAnimation('Default.applyrtl', 'defaultElement')">向左移动</button>
</div>
<div class="animation-status" id="defaultStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>边缘动画 (Edge)</h3>
<div class="demo-area">
<div class="demo-element" id="edgeElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Edge.show', 'edgeElement')">从顶部显示</button>
<button onclick="runAnimation('Edge.hide', 'edgeElement')">向顶部隐藏</button>
</div>
<div class="animation-status" id="edgeStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>面板动画 (Panel)</h3>
<div class="demo-area">
<div class="demo-element" id="panelElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Panel.show', 'panelElement')">从右侧显示</button>
<button onclick="runAnimation('Panel.showrtl', 'panelElement')">从左侧显示</button>
<button onclick="runAnimation('Panel.hide', 'panelElement')">向右侧隐藏</button>
<button onclick="runAnimation('Panel.hidertl', 'panelElement')">向左侧隐藏</button>
</div>
<div class="animation-status" id="panelStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>弹出动画 (Popup)</h3>
<div class="demo-area">
<div class="demo-element" id="popupElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Popup.show', 'popupElement')">弹出显示</button>
</div>
<div class="animation-status" id="popupStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>拖放动画 (Drag)</h3>
<div class="demo-area">
<div class="demo-element" id="dragElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Drag.sourceEnd', 'dragElement')">从右复位</button>
<button onclick="runAnimation('Drag.sourceEndRtl', 'dragElement')">从左复位</button>
</div>
<div class="animation-status" id="dragStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>内容动画 (Content)</h3>
<div class="demo-area">
<div class="demo-element" id="contentElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Content.enter', 'contentElement')">从右进入</button>
<button onclick="runAnimation('Content.enterrtl', 'contentElement')">从左进入</button>
</div>
<div class="animation-status" id="contentStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>页面动画 (Page)</h3>
<div class="demo-area">
<div class="demo-element" id="pageElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Page.enter', 'pageElement')">从右进入</button>
<button onclick="runAnimation('Page.enterrtl', 'pageElement')">从左进入</button>
</div>
<div class="animation-status" id="pageStatus">等待动画执行...</div>
</div>
</div>
<div class="control-group">
<h3>其他动画</h3>
<div class="demo-area">
<div class="demo-element" id="otherElement"></div>
<div class="animation-buttons">
<button onclick="runAnimation('Exit', 'otherElement')">退出</button>
<button onclick="runAnimation('UpdateBadge', 'otherElement')">更新徽章</button>
</div>
<div class="animation-status" id="otherStatus">等待动画执行...</div>
</div>
</div>
</div>
<footer>
<p>动画效果测试页面 - 使用 WinJS 动画库</p>
</footer>
</div>
<script>
// 确保Windows对象存在
if (typeof Windows === 'undefined') {
console.error('Windows对象未定义请确保已正确引入WinJS库');
} else if (!Windows.UI || !Windows.UI.Animation) {
console.error('Windows.UI.Animation未定义请确保animation.js已正确加载');
}
// 动画映射表
const animationMap = {
'Flyout.toTop': Windows.UI.Animation.Keyframes.Flyout.toTop,
'Flyout.toBottom': Windows.UI.Animation.Keyframes.Flyout.toBottom,
'Flyout.toLeft': Windows.UI.Animation.Keyframes.Flyout.toLeft,
'Flyout.toRight': Windows.UI.Animation.Keyframes.Flyout.toRight,
'Flyout.fromBottom': Windows.UI.Animation.Keyframes.Flyout.fromBottom,
'Flyout.fromTop': Windows.UI.Animation.Keyframes.Flyout.fromTop,
'Flyout.fromLeft': Windows.UI.Animation.Keyframes.Flyout.fromLeft,
'Flyout.fromRight': Windows.UI.Animation.Keyframes.Flyout.fromRight,
'Opacity.visible': Windows.UI.Animation.Keyframes.Opacity.visible,
'Opacity.hidden': Windows.UI.Animation.Keyframes.Opacity.hidden,
'Scale.up': Windows.UI.Animation.Keyframes.Scale.up,
'Scale.down': Windows.UI.Animation.Keyframes.Scale.down,
'Default.remove': Windows.UI.Animation.Keyframes.Default.remove,
'Default.removertl': Windows.UI.Animation.Keyframes.Default.removertl,
'Default.apply': Windows.UI.Animation.Keyframes.Default.apply,
'Default.applyrtl': Windows.UI.Animation.Keyframes.Default.applyrtl,
'Edge.show': Windows.UI.Animation.Keyframes.Edge.show,
'Edge.hide': Windows.UI.Animation.Keyframes.Edge.hide,
'Panel.show': Windows.UI.Animation.Keyframes.Panel.show,
'Panel.showrtl': Windows.UI.Animation.Keyframes.Panel.showrtl,
'Panel.hide': Windows.UI.Animation.Keyframes.Panel.hide,
'Panel.hidertl': Windows.UI.Animation.Keyframes.Panel.hidertl,
'Popup.show': Windows.UI.Animation.Keyframes.Popup.show,
'Drag.sourceEnd': Windows.UI.Animation.Keyframes.Drag.sourceEnd,
'Drag.sourceEndRtl': Windows.UI.Animation.Keyframes.Drag.sourceEndRtl,
'Content.enter': Windows.UI.Animation.Keyframes.Content.enter,
'Content.enterrtl': Windows.UI.Animation.Keyframes.Content.enterrtl,
'Page.enter': Windows.UI.Animation.Keyframes.Page.enter,
'Page.enterrtl': Windows.UI.Animation.Keyframes.Page.enterrtl,
'Exit': Windows.UI.Animation.Keyframes.Exit,
'UpdateBadge': Windows.UI.Animation.Keyframes.UpdateBadge
};
// 运行动画的函数
function runAnimation(animationKey, elementId) {
const targetElement = document.getElementById(elementId);
const statusElement = document.getElementById(elementId.replace('Element', 'Status'));
if (!animationMap[animationKey]) {
statusElement.textContent = `错误:未找到动画键 "${animationKey}"`;
return;
}
// 获取动画关键帧
const keyFrame = animationMap[animationKey];
// 更新状态
statusElement.textContent = `正在执行动画: ${animationKey}\n关键帧: ${keyFrame}\n开始时间: ${new Date().toLocaleTimeString()}`;
// 执行动画
Windows.UI.Animation.RunAsync(targetElement, keyFrame, 1000)
.then(function() {
statusElement.textContent += `\n动画完成时间: ${new Date().toLocaleTimeString()}`;
})
.catch(function(error) {
statusElement.textContent = `动画执行出错: ${error.message}`;
});
}
// 页面加载完成后显示提示
window.addEventListener('DOMContentLoaded', function() {
const statusElements = document.querySelectorAll('.animation-status');
statusElements.forEach(element => {
element.textContent = '页面已加载完成,点击按钮测试动画效果';
});
});
</script>
</body>
</html>

View File

@@ -20,6 +20,7 @@
<link rel="stylesheet" href="fonts/fonts.css">
<link rel="stylesheet" href="css/pages.css">
<script type="text/javascript" src="js/event.js"></script>
<script type="text/javascript" src="js/tileback.js"></script>
<script type="text/javascript" src="js/pages.js"></script>
<script type="text/javascript" src="js/load.js"></script>
<script type="text/javascript" src="js/init.js"></script>
@@ -27,11 +28,12 @@
<body>
<div id="page-container" class="pagecontainer full">
<div class="page splash">
<div class="page preinstall">
<!-- Splash Screen -->
<img class="splash" src="images/splash.default.png" alt="Splash Screen" width="620" height="300">
<div class="content splash">
<progress class="win-ring"></progress>
<p class="status-text"></p>
</div>
<script>
(function() {
@@ -54,44 +56,160 @@
<span data-res-byname="IDS_PLEASEWAIT">Please wait...</span>
</div>
<!-- Main Page -->
<div class="content select preinstall installing installsuccess installfailed">
<div class="content select preinstall installing installsuccess installfailed main">
<div style="width: 100%; box-sizing: border-box;" class="currentfile multiple">
<h1 class="win-type-x-large" data-res-byname="IDS_PREINSTALL_MTTITLE"></h1>
<label for="select-package" class="win-label" data-res-byname="IDS_PREINSTALL_MSELECT">在这里请选择一个包查看信息。</label><br />
<select id="select-package"></select><br />
<h1 class="win-type-x-large title multiple" data-res-byname="IDS_PREINSTALL_MTTITLE"></h1>
<label for="select-package" class="win-label" data-res-byname="IDS_PREINSTALL_MSELECT"></label><br />
<select id="select-package" style="width: 100%;"></select><br />
</div>
<div class="storelogo">
<div class="storelogo" style="margin-left: 24px;">
<div class="filter">
<img src="images/splash.default.png" alt="App Store Logo">
</div>
</div>
<h1 class="win-type-x-large pkgtitle" data-res-byname="IDS_PREINSTALL_TITLE"></h1>
<h1 class="win-type-x-large pkgtitle title single" data-res-byname="IDS_PREINSTALL_TITLE"></h1>
<script>
(function() {
"use strict";
var monitor = Windows.UI.Event.Monitor;
var htitle = document.body.querySelector(".page .content h1.pkgtitle");
if (!htitle) return;
function getHeight(ele) {
if (typeof ele === "string") ele = document.getElementById(ele);
try {
return ele.offsetHeight;
} catch (e) {
try {
return ele.clientHeight;
} catch (e) {
return ele.getBoundingClientRect().height;
}
}
return 0;
}
function onChildChangeEventHandler(e) {
var span = htitle.querySelector("span");
if (!span) return;
if (!span.hasAttribute("data-original")) span.setAttribute("data-original", span.textContent);
else span.textContent = span.getAttribute("data-original");
if (!span.hasAttribute("data-showlength")) span.setAttribute("data-showlength", (span.textContent || "").length);
else span.setAttribute("data-showlength", (span.textContent || "").length);
var totalheight = getHeight(htitle);
var limitheight = (parseFloat(("" + (getComputedStyle(htitle, null).lineHeight || 25 / 72 * 96)).replace("px", "")) + 1) * 2;
while (totalheight > limitheight && span.textContent.length) {
totalheight = getHeight(htitle);
if (totalheight > limitheight) {
span.textContent = (span.textContent || "").slice(0, -1);
span.setAttribute("data-showlength", span.textContent.length);
// console.log(totalheight, limitheight, span.textContent.length, span.getAttribute("data-showlength"), span.getAttribute("data-original").length)
}
}
if (!(totalheight > limitheight && span.textContent.length)) {
var isfulllen =
span.getAttribute("data-original").length <=
parseInt(span.getAttribute("data-showlength"), 10);
if (isfulllen) {
span.removeAttribute("data-overflow");
} else {
span.setAttribute("data-overflow", true);
}
}
}
monitor.observe(htitle, monitor.EventType.child, onChildChangeEventHandler);
function getWidth(ele) {
if (typeof ele === "string") ele = document.getElementById(ele);
try {
return ele.getBoundingClientRect().width;
} catch (e) {
try {
return ele.offsetWidth;
} catch (e) {
return ele.clientWidth;
}
}
return 0;
}
var lastWidth = getWidth(htitle);
function onSizeChangeEventHandler(e) {
if (lastWidth === getWidth(htitle)) return;
lastWidth = getWidth(htitle);
onChildChangeEventHandler(e);
}
var deb_sizechange = debounce(onSizeChangeEventHandler, 500);
monitor.observe(htitle, monitor.EventType.resize, deb_sizechange);
var lastAttr = htitle.getAttribute("data-titlefmt") || "";
function onAttributeChangeEventHandler(e) {
if (lastAttr === htitle.getAttribute("data-titlefmt")) return;
lastAttr = htitle.getAttribute("data-titlefmt");
htitle.innerHTML = Bridge.String.formatInnerHtml(lastAttr, htitle.getAttribute("data-pkgname") || "");
}
monitor.observe(htitle, monitor.EventType.attribute, onAttributeChangeEventHandler);
})();
</script>
<p class="pkgtitle multiple" data-res-byname="IDS_PREINSTALL_MPKGNAME"></p>
<p data-res-byname="IDS_MSAPP"></p>
<p class="pkgapplabel" data-res-byname="IDS_MSAPP"></p>
<p class="pkgpublisher" data-res-byname="IDS_PUBLISHER"></p>
<p class="pkgversion" data-res-byname="IDS_VERSION"></p><br />
<p class="pkgfunctions-label" data-res-byname="IDS_FUNCTIONNAME"></p>
<div class="functions">
<ul>
<li>使用全部的系统资源</li>
</ul>
</div>
<a class="moreinfo" data-res-byname="IDS_MOREINFO"></a>
<a class="moreinfo" data-res-byname="IDS_MOREINFO" tabindex="0"></a>
<div data-win-control="WinJS.UI.Flyout" id="moreinfo-flyout" style="max-width: 80%; max-height: 80%;">
<div id="moreinfo-flyout-content" style="-ms-user-select: element; user-select: text; padding: 0 0 25px 0; box-sizing: border-box;;">
<div style="width: 100%;">
<p><span colspan="2" style="font-weight: bold;" data-res-byname="IDS_MOREINFO_ID"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDNAME"></span>: <span class="id name"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDPUBLISHER"></span>: <span class="id publisher"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDVERSION"></span>: <span class="id version"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDARCH"></span>: <span class="id arch"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDFAMILY"></span>: <span class="id family"></span></p>
<p><span data-res-byname="IDS_MOREINFO_IDFULL"></span>: <span class="id full"></span></p>
</div>
<div style="width: 100%; display: none;">
<p><span colspan="2" style="font-weight:bold;" data-res-byname="IDS_MOREINFO_PROP"></span></p>
<p><span data-res-byname="IDS_MOREINFO_PROPFREAMWORK"></span>: <span class="prop framework"></span></p>
<p><span data-res-byname="IDS_MOREINFO_PROPRESPKG"></span>: <span class="prop respkg"></span></p>
</div>
<div style="width: 100%;">
<p><span colspan="2" style="font-weight:bold;" data-res-byname="IDS_MOREINFO_INFO"></span></p>
<p><span data-res-byname="IDS_MOREINFO_INFOSYS"></span>: <span class="info sys"></span></p>
<p><span data-res-byname="IDS_MOREINFO_INFOLANG"></span>: </p>
<ul class="info langs"></ul>
</div>
</div>
</div>
<script>
(function() {
"use strict";
var monitor = Windows.UI.Event.Monitor;
var page = document.querySelector(".page");
var content = page.querySelector(".content.preinstall");
var content = page.querySelector(".content.main");
var functions = page.querySelector(".functions");
var funculist = functions.querySelector("ul");
var moreinfo = page.querySelector(".moreinfo");
function sizeChangeEvent(e) {
// var height = parseFloat((getComputedStyle(content, null).height || ("" + content.getBoundingClientRect().height)).replace("px", ""));
var height = content.getBoundingClientRect().height;
var iscomputedheight = false;
if (height < ("" + content.getBoundingClientRect().height)) iscomputedheight = true;
if (height <= 0) height = height || content.offsetHeight || content.clientHeight;
var top = functions.getBoundingClientRect().top;
var newheight = parseInt((height - top - 10));
var newheight = 0;
if (iscomputedheight) {
newheight = height - top;
} else {
newheight = parseInt((height - top - (moreinfo.offsetHeight || moreinfo.getBoundingClientRect().height || 10)));
}
var listheight = (funculist.scrollHeight || funculist.offsetHeight || funculist.clientHeight || funculist.getBoundingClientRect().height || 10) + 20;
console.log(newheight, listheight);
// console.log(newheight, listheight);
if (newheight > listheight) newheight = listheight;
functions.style.height = newheight + "px";
}
@@ -102,12 +220,87 @@
setTimeout(sizeChangeEvent, 0);
})();
</script>
<script>
(function() {
"use strict";
var eutils = Windows.UI.Event.Util;
var select = document.getElementById("select-package");
eutils.addEvent(select, "change", function() {
var strutils = Bridge.External.String;
var page = document.querySelector(".page");
var pkgtitle = page.querySelector(".pkgtitle.multiple");
var pkgpublisher = page.querySelector(".pkgpublisher");
var pkgversion = page.querySelector(".pkgversion");
var funculist = page.querySelector(".functions ul");
var storelogo = page.querySelector(".storelogo");
var slimg = storelogo.querySelector("img");
var slfilter = storelogo.querySelector(".filter");
var pi = Bridge.Package.pkginfo(this.value);
var reason = page.querySelector(".reason textarea");
if (pi && pi.valid) {
var res = Bridge.Resources;
pkgtitle.textContent = strutils.format(res.byname("IDS_PREINSTALL_MPKGNAME"), pi.properties.display_name);
slimg.src = pi.properties.logo_base64;
pkgpublisher.textContent = strutils.format(res.byname("IDS_PUBLISHER"), pi.properties.publisher_display_name);
pkgversion.textContent = strutils.format(res.byname("IDS_VERSION"), stringifyVersion(pi.identity.version));
funculist.innerHTML = "";
storelogo.setAttribute("data-logoimg", pi.properties.logo);
for (var j = 0; j < pi.capabilities.capabilities_name.length; j++) {
var li = document.createElement("li");
var capname = pi.capabilities.capabilities_name[j];
li.setAttribute("data-capability", capname);
li.textContent = Bridge.Package.capabilityDisplayName(capname);
if (Bridge.NString.empty(li.textContent)) li.textContent = capname;
funculist.appendChild(li);
}
for (var j = 0; j < pi.capabilities.device_capabilities.length; j++) {
var capname = pi.capabilities.device_capabilities[j];
var cdname = Bridge.Package.capabilityDisplayName(capname);
if (!Bridge.NString.empty(cdname)) {
var li = document.createElement("li");
li.setAttribute("data-capability", capname);
li.textContent = Bridge.Package.capabilityDisplayName(capname);
funculist.appendChild(li);
}
}
try {
var bc = pi.applications[0].BackgroundColor || Bridge.UI.themeColor;
storelogo.style.backgroundColor = bc;
slfilter.style.background = Color.genTileBackFilter(bc);
} catch (e) {
var bc = Bridge.UI.themeColor;
storelogo.style.backgroundColor = bc;
slfilter.style.background = Color.genTileBackFilter(bc);
}
setFlyoutDisplayInfo(pi);
var hres = Bridge.Package.installResult(this.value);
if (hres) {
reason.textContent = hres.message;
} else {
reason.textContent = Bridge.Resources.byname("IDS_FAILED_MSUCCESS");
}
}
});
})();
</script>
<script>
(function() {
"Use strict";
var page = document.querySelector(".page");
var content = page.querySelector(".content.preinstall");
var moreinfo = page.querySelector(".moreinfo");
Windows.UI.Event.Util.addEvent(moreinfo, "click", function() {
var flyout = document.getElementById("moreinfo-flyout").winControl;
flyout.show(this);
});
})();
</script>
</div>
<div class="progress installing">
<div>
<span class="ring-loading">&#57543;</span>&nbsp;<span class="status" data-res-byname="IDS_INSTALLING_SLOADING"></span>
</div>
<progress min="0" max="100" value="50" class="win-progress-bar"></progress>
<progress min="0" max="100" class="win-progress-bar"></progress>
</div>
<div class="reason installfailed">
<p data-res-byname="IDS_FAILED_REASONNAME"></p>
@@ -119,11 +312,10 @@
<label for="preinst-enablelaunch" data-res-byname="IDS_LAUNCHWHENREADY"></label>
</div>
<div class="command">
<button data-res-byname="IDS_PREINSTALL_TINSTALL"></button>
<button data-res-byname="IDS_PREINSTALL_CANCEL"></button>
<button data-res-byname="IDS_PREINSTALL_TINSTALL" onclick="Bridge.Frame.callEvent ('OnPress_Button1')"></button>
<button data-res-byname="IDS_PREINSTALL_CANCEL" onclick="Bridge.Frame.callEvent ('OnPress_Button2')"></button>
</div>
</div>
<div data-win-control="WinJS.UI.Flyout" id="moreinfo-flyout"></div>
</div>
</div>
</body>

View File

@@ -152,13 +152,6 @@
}
return swResult;
}
module.exports = {
Windows: {
UI: {
Animation: {
Keyframes: AnimationKeyFrames,
Animation: generateAnimeString,
/**
* 异步设置动画,返回一个 Promise 对象,动画结束后会执行
* @param {HTMLElement} element 元素节点
@@ -172,7 +165,7 @@
* @param {string} [swPlayState] 播放状态,默认 ""
* @returns {Promise}
*/
RunAsync: function(element, swKeyFrames, uMillisecond, swTimingFunc, uDelayMs, swIteration, swDirection, swFillMode, swPlayState) {
function RunAsync(element, swKeyFrames, uMillisecond, swTimingFunc, uDelayMs, swIteration, swDirection, swFillMode, swPlayState) {
return new WinJS.Promise(function(complete) {
element.style.animation = generateAnimeString(swKeyFrames, uMillisecond, swTimingFunc, uDelayMs, swIteration, swDirection, swFillMode, swPlayState);
element.addEventListener("animationend", function() {
@@ -181,6 +174,92 @@
});
});
}
module.exports = {
Windows: {
UI: {
Animation: {
Keyframes: AnimationKeyFrames,
Animation: generateAnimeString,
animation: generateAnimeString,
RunAsync: RunAsync,
runAsync: RunAsync
}
}
}
};
if (!String.prototype.repeat) {
String.prototype.repeat = function(count) {
'use strict';
if (this == null) { throw new TypeError('can\'t convert ' + this + ' to object'); }
var str = '' + this;
count = +count;
if (count != count) { count = 0 }
if (count < 0) { throw new RangeError('repeat count must be non-negative'); }
if (count == Infinity) { throw new RangeError('repeat count must be less than infinity'); }
count = Math.floor(count);
if (str.length == 0 || count == 0) { return '' }
if (str.length * count >= 1 << 28) { throw new RangeError('repeat count must not overflow maximum string size'); }
var rpt = '';
for (var i = 0; i < count; i++) { rpt += str }
return rpt
}
}
var timers = {};
function DisplayLoadingAmineChar(containerId, shouldAnimate) {
var container = null;
if (containerId instanceof HTMLElement) {
if (typeof containerId.id === "string" && containerId.id.length > 0) {
container = containerId;
containerId = container.id;
} else {
containerId.id = "elementid-" + Math.floor(Math.random() * 1000000);
container = containerId;
containerId = container.id;
}
} else document.getElementById(containerId);
var textNode = container.firstChild;
if (!textNode || textNode.nodeType !== 3) {
textNode = document.createTextNode("");
container.innerHTML = "";
container.appendChild(textNode);
}
var chars = ''.repeat(10);
var index = 0;
var charGroupSize = 120;
function showNextChar() {
if (index < chars.length) {
textNode.nodeValue = chars.charAt(index);
index++;
if (index % charGroupSize === 0) {
clearInterval(timers[containerId]);
setTimeout(startAnimation, 200);
}
} else {
index = 0;
textNode.nodeValue = chars.charAt(index);
}
}
function startAnimation() {
if (timers[containerId]) {
clearInterval(timers[containerId]);
}
if (shouldAnimate) {
timers[containerId] = setInterval(showNextChar, 30);
} else {
clearInterval(timers[containerId]);
textNode.nodeValue = chars.charAt(chars.length - 1);
}
}
startAnimation();
}
module.exports = {
Windows: {
UI: {
Animation: {
loading: DisplayLoadingAmineChar
}
}
}

View File

@@ -10,7 +10,10 @@
External: ext,
Frame: {
isIe10: function() { return ext.IEFrame.Version === 10; },
isIe11: function() { return ext.IEFrame.Version === 11; }
isIe11: function() { return ext.IEFrame.Version === 11; },
callEvent: function(funcName, e) {
ext.Window.CallEvent(funcName, e);
}
},
UI: {
Splash: {
@@ -19,11 +22,12 @@
fadeOut: function() { ext.System.UI.FadeOutSplash(); }
}
},
String: {
String: ext.String,
/* {
trim: function(str) { return ext.String.Trim(str); },
tolower: function(str) { return ext.String.ToLower(str); },
toupper: function(str) { return ext.String.ToUpper(str); },
},
}, */
NString: {
equals: function(str1, str2) { return ext.String.NString.NEquals(str1, str2); },
compare: function(str1, str2) { return ext.String.NString.Compare(str1, str2); },
@@ -35,6 +39,26 @@
byid: function(resid) { return ext.System.Resources.GetById(resid); },
nameToId: function(resname) { return ext.System.Resources.ToId(resname); },
idToName: function(resid) { return ext.System.Resources.ToName(resid); },
},
Package: {
filepaths: function() {
return JSON.parse(ext.Package.GetPackagesToJson() || "[]");
},
pkginfo: function(filepath) {
return JSON.parse(ext.Package.GetPackageInfoToJson(filepath) || "{}");
},
capabilityDisplayName: function(capability) {
return ext.Package.GetCapabilityDisplayName(capability);
},
installResult: function(filepath) {
return ext.Package.GetPackageInstallResult(filepath);
},
},
Locale: {
toLcid: function(localeName) { return ext.System.Locale.ToLcid(localeName); },
toLocaleName: function(lcid) { return ext.System.Locale.ToLocaleName(lcid); },
localeInfo: function(lcid, lcType) { return ext.System.Locale.LocaleInfo(lcid, lcType); },
localeInfoEx: function(localeName, lcType) { return ext.System.Locale.LocaleInfoEx(localeName, lcType); }
}
};
Object.defineProperty(global.Bridge.Frame, "scale", {
@@ -56,6 +80,15 @@
Object.defineProperty(global.Bridge.UI, "dpi", {
get: function() { return ext.System.UI.DPI; }
});
Object.defineProperty(global.Bridge.UI, "themeColor", {
get: function() { return ext.System.UI.ThemeColor; }
});
Object.defineProperty(global.Bridge.UI, "contrast", {
get: function() { return ext.System.UI.HighContrast; }
});
Object.defineProperty(global.Bridge.UI, "darkmode", {
get: function() { return ext.System.UI.DarkMode; }
});
Object.defineProperty(global.Bridge.UI.Splash, "backcolor", {
get: function() { return ext.System.UI.SplashBackgroundColor; },
});

View File

@@ -24,6 +24,7 @@
Object.defineProperty(this, "color", {
get: function() { return parent; }
});
this.stringify = function() { return "rgb(" + parent.red + "," + parent.green + "," + parent.blue + ")"; };
}
function RGBA(parent) {
@@ -34,6 +35,7 @@
});
this.toString = function() { return "rgba(" + parent.red + "," + parent.green + "," + parent.blue + "," + (parent.alpha / 255).toFixed(2) + ")"; };
this.valueOf = function() { return parent.valueOf(); };
this.stringify = function() { return "rgba(" + parent.red + "," + parent.green + "," + parent.blue + "," + (parent.alpha / 255).toFixed(2) + ")"; };
}
function HSL(parent) {
@@ -196,6 +198,7 @@
});
this.toString = function() { return "hsl(" + this.hue + "," + (this.saturation * 100).toFixed(2) + "%," + (this.lightness * 100).toFixed(2) + "%)"; };
this.valueOf = function() { return parent.valueOf(); };
this.stringify = function() { return "hsl(" + this.hue + "," + (this.saturation * 100).toFixed(2) + "%," + (this.lightness * 100).toFixed(2) + "%)"; };
}
function HSLA(parent) {
@@ -206,6 +209,7 @@
});
this.toString = function() { return "hsla(" + this.hue + "," + (this.saturation * 100).toFixed(2) + "%," + (this.lightness * 100).toFixed(2) + "%," + (parent.alpha / 255).toFixed(2) + ")"; };
this.valueOf = function() { return parent.valueOf(); };
this.stringify = function() { return "hsla(" + this.hue + "," + (this.saturation * 100).toFixed(2) + "%," + (this.lightness * 100).toFixed(2) + "%," + (parent.alpha / 255).toFixed(2) + ")"; };
}
function HWB(parent) {
@@ -381,6 +385,13 @@
}
};
this.valueOf = function() { return parent.valueOf(); };
this.stringify = function() {
if (parent.alpha == 255) {
return "hwb(" + this.hue + "," + (this.white * 100).toFixed(2) + "%," + (this.black * 100).toFixed(2) + "%)";
} else {
return "hwb(" + this.hue + "," + (this.white * 100).toFixed(2) + "%," + (this.black * 100).toFixed(2) + "% / " + (parent.alpha / 255).toFixed(2) + ")";
}
};
}
/**
*
@@ -390,26 +401,28 @@
* @param {number} alpha 透明度通道值 0-255
*/
function Color(red, green, blue, alpha) {
red = red & 0xFF;
green = green & 0xFF;
blue = blue & 0xFF;
alpha = (typeof alpha === "undefined") ? 255 : (alpha & 0xFF);
this.rgbData = (red << 16) | (green << 8) | blue;
this.alpha = alpha;
this._red = red & 0xFF;
this._green = green & 0xFF;
this._blue = blue & 0xFF;
this._alpha = (typeof alpha === "undefined") ? 255 : (alpha & 0xFF);
Object.defineProperty(this, "rgbData", {
get: function() { return this._rgbData; },
set: function(value) { this._rgbData = value & 0xFFFFFF; }
});
// 红色通道
Object.defineProperty(this, "red", {
get: function() { return (this.rgbData >>> 16) & 0xFF; },
set: function(value) { this.rgbData = ((value & 0xFF) << 16) | (this.rgbData & 0x00FFFF); }
get: function() { return this._red; },
set: function(value) { this._red = value & 0xFF; }
});
// 绿色通道
Object.defineProperty(this, "green", {
get: function() { return (this.rgbData >>> 8) & 0xFF; },
set: function(value) { this.rgbData = (this.rgbData & 0xFF00FF) | ((value & 0xFF) << 8); }
get: function() { return this._green; },
set: function(value) { this._green = value & 0xFF; }
});
// 蓝色通道
Object.defineProperty(this, "blue", {
get: function() { return this.rgbData & 0xFF; },
set: function(value) { this.rgbData = (this.rgbData & 0xFFFF00) | (value & 0xFF); }
get: function() { return this._blue; },
set: function(value) { this._blue = value & 0xFF; }
});
// Alpha 通道单独存储
Object.defineProperty(this, "alpha", {
@@ -458,6 +471,16 @@
this.HSL = new HSL(this);
this.HSLA = new HSLA(this);
this.HWB = new HWB(this);
this.stringify = function() { return this.hex; };
}
/**
* 解析颜色字符串
* @param {string} str 颜色字符串
* @returns {Color} 解析得到的颜色对象
*/
Color.parse = function(str) {
var json = JSON.parse(window.external.IEFrame.ParseHtmlColor(str));
return new Color(json.r, json.g, json.b, json.a);
}
module.exports = { Color: Color };
})(this);

View File

@@ -171,13 +171,35 @@
}
return {
/**
* 监听元素变化,并触发回调函数。
* @param {Element} el 目标元素
* @param {string} type 事件类型,如 "resize", "position", "attribute", "child"
* @param {function} callback 回调函数,参数为事件对象
*/
observe: observe,
/**
* 取消监听元素变化。
* @param {Element} el 目标元素
* @param {string} type 事件类型,如 "resize", "position", "attribute", "child"
* @param {function} [callback] 回调函数,如果指定,则只移除指定的回调函数,否则移除所有回调函数。
*/
detach: detach,
/**
* 清除所有监听。
*/
clearAll: clearAll,
/**
* 事件类型枚举。
*/
EventType: {
/** 元素尺寸变化 */
resize: "resize",
/** 元素位置变化 */
position: "position",
/** 元素属性变化 */
attribute: "attribute",
/** 子元素变化 */
child: "child"
}
};

View File

@@ -25,12 +25,20 @@
var splashBackColor = "";
var timer = {
title: null,
text: null,
logo: null,
progress: null,
controls: null,
};
function setPage(swPageLabel, bIsMulti) {
var page = getPage();
swPageLabel = ("" + (swPageLabel || ""));
for (var i = 0; i < supportPageList.length; i++) {
if (Bridge.NString.equals(swPageLabel, supportPageList[i])) {
page.classList.add(supportPageList[i]);
if (!page.classList.contains(supportPageList[i])) page.classList.add(supportPageList[i]);
} else {
if (page.classList.contains(supportPageList[i])) page.classList.remove(supportPageList[i]);
}
@@ -49,6 +57,125 @@
break;
}
}
(function() {
if (Bridge.NString.equals(swPageLabel, "loading")) {
var content = page.querySelector(".content.loading");
if (content) content.style.visibility = "hidden";
setTimeout(function(node) {
if (node) {
node.style.visibility = "visible";
var animation = Windows.UI.Animation;
animation.runAsync(node, animation.Keyframes.Flyout.toLeft, 500);
}
}, 0, content);
var loading = content.querySelector(".ring-loading");
Windows.UI.Animation.loading(loading, true);
} else {
var content = page.querySelector(".content.loading");
if (content) {
var loading = content.querySelector(".ring-loading");
Windows.UI.Animation.loading(loading, false);
}
}
})();
(function() {
function push_nonull(arr, item) {
if (item) arr.push(item);
}
var timerkeys = Object.keys(timer);
for (var i = 0; i < timerkeys.length; i++) {
if (timer[timerkeys[i]]) {
clearTimeout(timer[timerkeys[i]]);
timer[timerkeys[i]] = null;
}
}
var content = page.querySelector(".content." + Bridge.String.trim(swPageLabel));
var controls = page.querySelector(".controls." + Bridge.String.trim(swPageLabel));
var progress = page.querySelector(".progress");
var reason = page.querySelector(".reason");
var titlepart = [];
var textpart = [];
var storelogo = null;
if (content) {
if (bIsMulti) push_nonull(titlepart, content.querySelector(".currentfile"));
push_nonull(titlepart, content.querySelector(".pkgtitle"));
if (bIsMulti) push_nonull(titlepart, content.querySelector(".pkgtitle.multiple"));
push_nonull(titlepart, content.querySelector(".pkgapplabel"));
push_nonull(titlepart, content.querySelector(".pkgpublisher"));
push_nonull(titlepart, content.querySelector(".pkgversion"));
push_nonull(textpart, content.querySelector(".pkgfunctions-label"));
push_nonull(textpart, content.querySelector(".functions"));
push_nonull(textpart, content.querySelector(".moreinfo"));
storelogo = content.querySelector(".storelogo");
}
var refresh = function(nodes) {
for (var i = 0; i < nodes.titlepart.length; i++) nodes.titlepart[i].style.visibility = "hidden";
for (var i = 0; i < nodes.textpart.length; i++) nodes.textpart[i].style.visibility = "hidden";
if (nodes.storelogo) nodes.storelogo.style.visibility = "hidden";
if (nodes.progress) nodes.progress.style.visibility = "hidden";
if (nodes.controls) nodes.controls.style.visibility = "hidden";
if (nodes.reason) nodes.reason.style.visibility = "hidden";
var animation = Windows.UI.Animation;
timer.title = setTimeout(function(titlenodes) {
if (titlenodes) {
for (var i = 0; i < titlenodes.length; i++) {
animation.runAsync(titlenodes[i], animation.Keyframes.Flyout.toLeft, 500);
}
for (var i = 0; i < titlenodes.length; i++) titlenodes[i].style.visibility = "visible";
}
}, 0, nodes.titlepart);
timer.text = setTimeout(function(textnodes) {
if (textnodes) {
for (var i = 0; i < textnodes.length; i++) {
animation.runAsync(textnodes[i], animation.Keyframes.Flyout.toLeft, 500);
}
for (var i = 0; i < textnodes.length; i++) textnodes[i].style.visibility = "visible";
}
}, 50, nodes.textpart);
timer.logo = setTimeout(function(logonode) {
if (logonode) {
animation.runAsync(logonode, "scale-visible", 500);
logonode.style.visibility = "visible";
}
}, 100, nodes.storelogo);
timer.progress = setTimeout(function(progressnode) {
if (progressnode) {
animation.runAsync(progressnode, animation.Keyframes.Flyout.toLeft, 500);
progressnode.style.visibility = "visible";
}
}, 100, nodes.progress);
timer.controls = setTimeout(function(controlnodes) {
if (controlnodes) {
animation.runAsync(controlnodes, animation.Keyframes.Flyout.toTop, 500);
controlnodes.style.visibility = "visible";
}
}, 100, nodes.controls);
timer.reason = setTimeout(function(reasonnode) {
if (reasonnode) {
animation.runAsync(reasonnode, animation.Keyframes.Flyout.toLeft, 500);
reasonnode.style.visibility = "visible";
}
}, 100, nodes.reason);
};
refresh({
titlepart: titlepart,
textpart: textpart,
storelogo: storelogo,
progress: progress,
controls: controls,
reason: reason,
});
})();
(function() {
var page = document.querySelector(".page");
var progress = page.querySelector(".progress");
var ringLoading = progress.querySelector(".ring-loading");
if (Bridge.NString.equals(swPageLabel, "installing")) {
Windows.UI.Animation.loading(ringLoading, true);
} else {
Windows.UI.Animation.loading(ringLoading, false);
}
})();
}
function getPageLabel() {
@@ -97,15 +224,48 @@
});
Object.defineProperty(ret, "content", {
get: function() {
try {
var content = page.querySelector(".content.splash");
return content;
} catch (e) { return null; }
},
});
Object.defineProperty(ret, "statusText", {
get: function() {
var statustext = page.querySelector(".content.splash .status-text");
return statustext.textContent;
},
set: function(value) {
var statustext = page.querySelector(".content.splash .status-text");
if (!statustext) return;
statustext.textContent = value;
}
});
ret["getImageUrl"] = function() { return ret.imagesrc; };
ret["setImageUrl"] = function(value) { ret.imagesrc = value; };
ret["getBackground"] = function() { return ret.background; };
ret["setBackground"] = function(value) { ret.background = value; };
ret["setStatusText"] = function(value) { ret.statusText = value; };
ret["getStatusText"] = function() { return ret.statusText; };
ret["getContent"] = function() { return ret.content; };
return ret;
}
function getPreinstallPage() {
return document.querySelector(".page.preinstall");
}
module.exports = {
Page: {}
Page: {
set: setPage,
get: function() {
if (isMultiPage()) {
return [getPageLabel(), "multiple"];
} else {
return getPageLabel();
}
}
}
};
Object.defineProperty(Page, "current", {
get: function() { return getPageLabel(); },
@@ -118,4 +278,364 @@
Object.defineProperty(Page, "splash", {
get: function() { return getSplashPage(); }
});
module.exports = {
setPage: setPage,
getPage: getPage,
getPageIsMulti: isMultiPage,
setPageMultiple: setPageMultiple,
getSplashPage: getSplashPage,
getSplashPageImageUrl: function() { return getSplashPage().imagesrc; },
setSplashPageImageUrl: function(value) { getSplashPage().imagesrc = value; },
getSplashPageBackground: function() { return getSplashPage().background; },
setSplashPageBackground: function(value) { getSplashPage().background = value; },
getSplashPageStatusText: function() { return getSplashPage().statusText; },
setSplashPageStatusText: function(value) { try { getSplashPage().statusText = value; } catch (e) {} },
getSplashPageContent: function() { return getSplashPage().content; },
};
function parseVersion(version) {
var v = (version || "0.0.0.0").split(".");
var ret = { major: 0, minor: 0, build: 0, revision: 0 };
if (v.length >= 1) ret.major = parseInt(v[0]);
if (v.length >= 2) ret.minor = parseInt(v[1]);
if (v.length >= 3) ret.build = parseInt(v[2]);
if (v.length >= 4) ret.revision = parseInt(v[3]);
return ret;
}
function stringifyVersion(version) {
return version.major + "." + version.minor + "." + version.build + "." + version.revision;
}
function setFlyoutDisplayInfo(pkginfo) {
var flyout = document.getElementById("moreinfo-flyout");
var content = document.getElementById("moreinfo-flyout-content");
(function() {
var name = content.querySelector(".id.name");
name.textContent = pkginfo.identity.name;
var publisher = content.querySelector(".id.publisher");
publisher.textContent = pkginfo.identity.publisher;
var version = content.querySelector(".id.version");
version.textContent = stringifyVersion(pkginfo.identity.realver);
var arch = content.querySelector(".id.arch");
if (pkginfo.type === 1) {
switch (pkginfo.identity.architecture) {
case 1:
arch.textContent = "x86";
break;
case 2:
arch.textContent = "x64";
break;
case 4:
arch.textContent = "ARM";
break;
case 8:
arch.textContent = "ARM64";
break;
case 16:
arch.textContent = "Neutral";
break;
}
} else if (pkginfo.type === 2) {
var varch = pkginfo.identity.architecture;
var strarr = [];
if (varch & 1) strarr.push("x86");
if (varch & 2) strarr.push("x64");
if (varch & 4) strarr.push("ARM");
if (varch & 8) strarr.push("ARM64");
arch.textContent = strarr.join(", ");
}
var family = content.querySelector(".id.family");
family.textContent = pkginfo.identity.package_family_name;
var full = content.querySelector(".id.full");
full.textContent = pkginfo.identity.package_full_name;
})();
(function() {
var framework = content.querySelector(".prop.framework");
framework.textContent = Bridge.Resources.byname(pkginfo.properties.framework ? "IDS_MOREINFO_PROPYES" : "IDS_MOREINFO_PROPNO");
var respkg = content.querySelector(".prop.respkg");
respkg.textContent = Bridge.Resources.byname(pkginfo.properties.removable ? "IDS_MOREINFO_PROPYES" : "IDS_MOREINFO_PROPNO");
})();
(function() {
var sys = content.querySelector(".info.sys");
var strutils = Bridge.External.String;
sys.textContent = strutils.format(Bridge.Resources.byname("IDS_MOREINFO_INFOSYS_VALUE"), pkginfo.prerequisites.os_min_version_description, stringifyVersion(pkginfo.prerequisites.os_min_version));
var lang = content.querySelector(".info.langs");
lang.innerHTML = "";
for (var i = 0; i < pkginfo.resources.languages.length; i++) {
var localeName = pkginfo.resources.languages[i];
var li = document.createElement("li");
li.textContent = Bridge.Locale.localeInfoEx(localeName, 2);
lang.appendChild(li);
}
})();
}
function noticeLoadPreinstallPage(ismul) {
setPage("preinstall", ismul);
var page = getPreinstallPage();
if (!page) return;
var content = page.querySelector(".content.preinstall");
if (!content) return;
var filelist = Bridge.Package.filepaths();
var fselect = content.querySelector(".currentfile select");
for (var i = 0; i < filelist.length; i++) {
var option = document.createElement("option");
option.value = filelist[i];
option.text = filelist[i];
fselect.appendChild(option);
}
if (filelist.length > 0) {
var strutils = Bridge.External.String;
var pkgtitle = null;
if (filelist.length <= 1) {
pkgtitle = content.querySelector(".pkgtitle");
} else {
pkgtitle = content.querySelector(".pkgtitle.multiple");
}
var pkgpublisher = content.querySelector(".pkgpublisher");
var pkgversion = content.querySelector(".pkgversion");
var storelogo = content.querySelector(".storelogo");
var storelogoimg = storelogo.querySelector("img");
var storelogofilter = storelogo.querySelector(".filter");
var pkginfo = Bridge.Package.pkginfo(filelist[0]);
if (filelist.length <= 1) {
if (!pkgtitle.hasAttribute("data-pkgname"))
pkgtitle.setAttribute("data-pkgname", pkginfo.properties.display_name);
if (!pkgtitle.hasAttribute("data-titlefmt"))
pkgtitle.setAttribute("data-titlefmt", Bridge.Resources.byname("IDS_PREINSTALL_TITLE"));
pkgtitle.innerHTML = strutils.formatInnerHtml(pkgtitle.getAttribute("data-titlefmt"), pkgtitle.getAttribute("data-pkgname"));
} else {
pkgtitle.innerHTML = strutils.formatInnerHtml(Bridge.Resources.byname("IDS_PREINSTALL_MPKGNAME"), pkginfo.properties.display_name);
}
pkgpublisher.innerHTML = strutils.formatInnerHtml(Bridge.Resources.byname("IDS_PUBLISHER"), pkginfo.properties.publisher_display_name);
pkgversion.innerHTML = strutils.formatInnerHtml(Bridge.Resources.byname("IDS_VERSION"), stringifyVersion(pkginfo.identity.version));
storelogoimg.src = pkginfo.properties.logo_base64;
storelogo.setAttribute("data-logoimg", pkginfo.properties.logo);
var backcolor = "";
if (pkginfo.applications.length > 0) {
var appinfo = pkginfo.applications[0];
backcolor = appinfo.BackgroundColor || Bridge.UI.themeColor;
} else { backcolor = Bridge.UI.themeColor; }
storelogo.style.backgroundColor = backcolor;
storelogofilter.style.background = Color.genTileBackFilter(backcolor);
var funclist = content.querySelector(".functions ul");
for (var j = 0; j < pkginfo.capabilities.capabilities_name.length; j++) {
var li = document.createElement("li");
var capname = pkginfo.capabilities.capabilities_name[j];
li.setAttribute("data-capability", capname);
li.textContent = Bridge.Package.capabilityDisplayName(capname);
if (Bridge.NString.empty(li.textContent)) li.textContent = capname;
funclist.appendChild(li);
}
for (var j = 0; j < pkginfo.capabilities.device_capabilities.length; j++) {
var capname = pkginfo.capabilities.device_capabilities[j];
var cdname = Bridge.Package.capabilityDisplayName(capname);
if (!Bridge.NString.empty(cdname)) {
var li = document.createElement("li");
li.setAttribute("data-capability", capname);
li.textContent = Bridge.Package.capabilityDisplayName(capname);
funclist.appendChild(li);
}
}
setFlyoutDisplayInfo(pkginfo);
}
}
function setPreinstallPagePkgTitleFormatSingle(fmt) {
var page = document.querySelector(".page");
if (!page) return;
var content = page.querySelector(".content.preinstall");
if (!content) return;
var pkgtitle = content.querySelector("h1.pkgtitle");
pkgtitle.setAttribute("data-titlefmt", fmt);
}
function setControlButtonState(serial, title, display, ban) {
var page = document.querySelector(".page");
if (!page) return;
var controls = page.querySelector(".controls");
if (!controls) return;
var commands = controls.querySelectorAll(".command button");
try {
if (title !== void 0) commands[serial - 1].textContent = title;
if (display !== void 0) commands[serial - 1].style.display = display ? "" : "none";
if (ban !== void 0) commands[serial - 1].disabled = ban;
} catch (e) {}
}
function setLaunchWhenReady(selected, ban) {
var page = document.querySelector(".page");
if (!page) return;
var controls = page.querySelector(".controls");
if (!controls) return;
var checkbox = controls.querySelector(".checkbox input");
if (!checkbox) return;
if (selected !== void 0) checkbox.checked = selected;
if (ban !== void 0) checkbox.disabled = ban;
}
function getLaunchWhenReady() {
var page = document.querySelector(".page");
if (!page) return false;
var controls = page.querySelector(".controls");
if (!controls) return false;
var checkbox = controls.querySelector(".checkbox input");
if (!checkbox) return false;
return checkbox.checked == true;
}
function noticeLoadSelectPage() {
setPage("select", false);
setPreinstallPagePkgTitleFormatSingle(Bridge.Resources.byname("IDS_SELECT_TITLE"))
setControlButtonState(1, Bridge.Resources.byname("IDS_SELECT_OPENFILE"), true, false);
setControlButtonState(2, Bridge.Resources.byname("IDS_PREINSTALL_CANCEL"), true, false);
}
function setInstallingPackageInfoMultiple(filepath) {
var page = document.querySelector(".page");
if (!page) return;
var content = page.querySelector(".content.installing");
if (!content) return;
var progress = page.querySelector(".progress");
if (!progress) return;
var pkgtitle = content.querySelector(".pkgtitle.multiple");
var title = content.querySelector(".title.multiple");
var pkgpublisher = content.querySelector(".pkgpublisher");
var pkgversion = content.querySelector(".pkgversion");
var storelogo = content.querySelector(".storelogo");
var storelogoimg = storelogo.querySelector("img");
var storelogofilter = storelogo.querySelector(".filter");
var pkginfo = Bridge.Package.pkginfo(filepath);
pkgtitle.innerHTML = Bridge.String.formatInnerHtml(Bridge.Resources.byname("IDS_PREINSTALL_MPKGNAME"), pkginfo.properties.display_name);
pkgpublisher.innerHTML = Bridge.String.formatInnerHtml(Bridge.Resources.byname("IDS_PUBLISHER"), pkginfo.properties.publisher_display_name);
pkgversion.innerHTML = Bridge.String.formatInnerHtml(Bridge.Resources.byname("IDS_VERSION"), stringifyVersion(pkginfo.identity.version));
storelogoimg.src = pkginfo.properties.logo_base64;
storelogo.setAttribute("data-logoimg", pkginfo.properties.logo);
var backcolor = "";
if (pkginfo.applications.length > 0) {
var appinfo = pkginfo.applications[0];
backcolor = appinfo.BackgroundColor || Bridge.UI.themeColor;
} else { backcolor = Bridge.UI.themeColor; }
storelogo.style.backgroundColor = backcolor;
storelogofilter.style.background = Color.genTileBackFilter(backcolor);
}
function noticeLoadInstallingPage(ismul) {
setPage("installing", ismul);
var page = document.querySelector(".page");
if (!page) return;
var content = page.querySelector(".content.installing");
if (!content) return;
var progress = page.querySelector(".progress");
if (!progress) return;
var pkgtitle = null;
if (!ismul) {
pkgtitle = content.querySelector(".pkgtitle");
pkgtitle.setAttribute("data-titlefmt", Bridge.Resources.byname("IDS_INSTALLING_TITLE"));
}
var title = null;
if (ismul) {
title = content.querySelector(".title.multiple");
title.textContent = Bridge.Resources.byname("IDS_INSTALLING_MTITLE");
} else title = content.querySelector(".title");
}
// 0 - 100, float
function setInstallingProgress(percent) {
var page = document.querySelector(".page");
if (!page) return;
var progress = page.querySelector(".progress");
if (!progress) return;
var bar = progress.querySelector("progress");
if (typeof bar.max !== "number") bar.max = 100;
if (typeof bar.min !== "number") bar.min = 0;
bar.value = bar.min + (bar.max - bar.min) * (percent * 0.01);
if (bar.value > bar.max) bar.value = bar.max;
if (bar.value < bar.min) bar.value = bar.min;
}
function setInstallingStatus(status) {
var page = document.querySelector(".page");
if (!page) return;
var progress = page.querySelector(".progress");
if (!progress) return;
var statusbar = progress.querySelector(".status");
if (!statusbar) return;
statusbar.textContent = status;
}
function noticeLoadInstallSuccessPage(ismul) {
setPage("installsuccess", ismul);
var page = document.querySelector(".page");
var files = Bridge.Package.filepaths();
var pkginfo = Bridge.Package.pkginfo(files[0]);
if (ismul) {
var content = page.querySelector(".content.installsuccess");
if (!content) return;
var title = content.querySelector(".currentfile .title.multiple");
title.textContent = Bridge.Resources.byname("IDS_SUCCESS_MTITLE");
var hasApp = false;
for (var i = 0; i < files.length; i++) {
var pi = Bridge.Package.pkginfo(files[i]);
if (pi.applications && pi.applications.length > 0) {
hasApp = true;
break;
}
}
setControlButtonState(1, Bridge.Resources.byname(hasApp ? "IDS_SUCCESS_LAUNCH" : "IDS_COMMAND_CANCEL"), true, false);
} else {
setPreinstallPagePkgTitleFormatSingle(Bridge.Resources.byname("IDS_SUCCESS_TITLE"));
setControlButtonState(1, Bridge.Resources.byname(pkginfo.applications && pkginfo.applications.length > 0 ? "IDS_SUCCESS_LAUNCH" : "IDS_COMMAND_CANCEL"), true, false);
}
}
function noticeLoadInstallFailedPage(ismul) {
setPage("installfailed", ismul);
var page = document.querySelector(".page");
if (!page) return;
var content = page.querySelector(".content.installfailed");
if (!content) return;
var files = Bridge.Package.filepaths();
setControlButtonState(1, Bridge.Resources.byname("IDS_COMMAND_CANCEL"), true, false);
var title = null;
var reason = page.querySelector(".reason textarea");
if (ismul) {
title = content.querySelector(".currentfile .title.multiple");
title.textContent = Bridge.Resources.byname("IDS_FAILED_MTITLE");
var select = content.querySelector(".currentfile select");
select.value = "";
select.value = files[0];
try {
if (document.createEvent) {
var event = document.createEvent('HTMLEvents');
event.initEvent('change', true, false); // bubbles, cancelable
select.dispatchEvent(event);
} else if (select.fireEvent) { // IE <= 8
select.fireEvent('onchange');
}
} catch (e) {}
} else {
title = content.querySelector(".title");
setPreinstallPagePkgTitleFormatSingle(Bridge.Resources.byname("IDS_FAILED_STITLE"));
var hres = Bridge.Package.installResult(files[0]);
reason.textContent = hres.message;
}
}
module.exports = {
noticeLoadPreinstallPage: noticeLoadPreinstallPage,
parseVersion: parseVersion,
stringifyVersion: stringifyVersion,
setFlyoutDisplayInfo: setFlyoutDisplayInfo,
setPreinstallPagePkgTitleFormatSingle: setPreinstallPagePkgTitleFormatSingle,
setControlButtonState: setControlButtonState,
setLaunchWhenReady: setLaunchWhenReady,
getLaunchWhenReady: getLaunchWhenReady,
noticeLoadSelectPage: noticeLoadSelectPage,
setInstallingPackageInfoMultiple: setInstallingPackageInfoMultiple,
noticeLoadInstallingPage: noticeLoadInstallingPage,
setInstallingProgress: setInstallingProgress,
setInstallingStatus: setInstallingStatus,
noticeLoadInstallSuccessPage: noticeLoadInstallSuccessPage,
noticeLoadInstallFailedPage: noticeLoadInstallFailedPage
};
})(this);

View File

@@ -0,0 +1,33 @@
(function() {
"use strict";
function calcColorComponent(x) {
var y;
if (x <= 127.5) {
y = 0.999 * x - 5.4361 + x;
} else {
y = -0.999 * x + 249.32 + x;
}
return (y < 0 ? 0 : y) % 256; // 确保y不小于0
}
function roundToNearestInt(num) {
return Math.round(num);
}
function genTileBackFilter(backcolor) {
var basecolor = Color.parse(backcolor);
var rightcolor = new Color(
roundToNearestInt(calcColorComponent(basecolor.red)),
roundToNearestInt(calcColorComponent(basecolor.green)),
roundToNearestInt(calcColorComponent(basecolor.blue)),
0.25
);
return "linear-gradient(to right, rgba(0,0,0,0), " + rightcolor.RGBA.stringify() + ")";
}
module.exports = {
Color: {
genTileBackFilter: genTileBackFilter
}
};
})();

View File

@@ -0,0 +1,412 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resource id="accessoryManager">
<lang name="zh-CN">作为附件应用注册,并选择加入特定应用的通知</lang>
</resource>
<resource id="activity">
<lang name="zh-CN">检测设备的当前动向</lang>
</resource>
<resource id="allJoyn">
<lang name="zh-CN">发现支持 AllJoyn 的应用和设备并与其交互</lang>
</resource>
<resource id="allowElevation">
<lang name="zh-CN">以管理员身份运行</lang>
</resource>
<resource id="appDiagnostics">
<lang name="zh-CN">收集有关其他应用的诊断信息</lang>
</resource>
<resource id="applicationData">
<lang name="zh-CN">访问存储在设备上的本地数据</lang>
</resource>
<resource id="applicationPackage">
<lang name="zh-CN">访问本地程序包内容</lang>
</resource>
<resource id="appLicensing">
<lang name="zh-CN">应用许可</lang>
</resource>
<resource id="appointments">
<lang name="zh-CN">使用日历中的约会</lang>
</resource>
<resource id="appointmentsSystem">
<lang name="zh-CN">读取并修改日历上的所有约会</lang>
</resource>
<resource id="appointmentSystem">
<lang name="zh-CN">系统级别约会访问</lang>
</resource>
<resource id="authenticationManagerAuthentication">
<lang name="zh-CN">获取经过身份验证的资源。</lang>
</resource>
<resource id="blockedChatMessages">
<lang name="zh-CN">读取已由“垃圾邮件筛选”应用阻止的短信和彩信</lang>
</resource>
<resource id="bluetooth">
<lang name="zh-CN">与已配对的蓝牙设备通信</lang>
</resource>
<resource id="bluetooth_genericAttributeProfile">
<lang name="zh-CN">蓝牙智能设备</lang>
</resource>
<resource id="bluetooth_rfcomm">
<lang name="zh-CN">蓝牙设备</lang>
</resource>
<resource id="broadFileSystemAccess">
<lang name="zh-CN">文件系统</lang>
</resource>
<resource id="callHistory">
<lang name="zh-CN">呼叫历史记录</lang>
</resource>
<resource id="callHistorySystem">
<lang name="zh-CN">系统级别呼叫历史记录访问</lang>
</resource>
<resource id="cellularDeviceControl">
<lang name="zh-CN">能够控制 Windows 设备</lang>
</resource>
<resource id="cellularDeviceIdentity">
<lang name="zh-CN">访问 Windows 设备标识数据</lang>
</resource>
<resource id="cellularMessaging">
<lang name="zh-CN">利用短信和富通信</lang>
</resource>
<resource id="chat">
<lang name="zh-CN">阅读并删除文本消息</lang>
</resource>
<resource id="chatSystem">
<lang name="zh-CN">阅读并编写所有短信和彩信</lang>
</resource>
<resource id="codeGeneration">
<lang name="zh-CN">动态生成代码</lang>
</resource>
<resource id="confirmAppClose">
<lang name="zh-CN">关闭自身及其窗口,并延迟关闭它们的应用</lang>
</resource>
<resource id="contacts">
<lang name="zh-CN">使用联系人</lang>
</resource>
<resource id="contactsSystem">
<lang name="zh-CN">读取联系人信息</lang>
</resource>
<resource id="contactSystem">
<lang name="zh-CN">系统级别联系人访问</lang>
</resource>
<resource id="cortanaSpeechAccessory">
<lang name="zh-CN">适用于附件的语音识别</lang>
</resource>
<resource id="customInstallActions">
<lang name="zh-CN">安装其他软件</lang>
</resource>
<resource id="deviceManagementDmAccount">
<lang name="zh-CN">设置和配置移动运营商开放移动联盟 - 设备管理 (MO OMA-DM) 帐户</lang>
</resource>
<resource id="deviceManagementEmailAccount">
<lang name="zh-CN">添加并管理电子邮件帐户</lang>
</resource>
<resource id="deviceManagementFoundation">
<lang name="zh-CN">移动设备管理配置</lang>
</resource>
<resource id="deviceManagementWapSecurityPolicies">
<lang name="zh-CN">配置无线应用程序协议 (WAP)</lang>
</resource>
<resource id="deviceMangementFoundation">
<lang name="zh-CN">对设备上的移动设备管理 (MDM) 云解决方案提供商 (CSP) 基础设施具有基本的访问权限</lang>
</resource>
<resource id="deviceUnlock">
<lang name="zh-CN">解锁适用于开发人员和企业方案的设备</lang>
</resource>
<resource id="documentsLibrary">
<lang name="zh-CN">使用文档库</lang>
</resource>
<resource id="dualSimTiles">
<lang name="zh-CN">在具有多张 SIM 卡的设备上创建另一个应用列表条目</lang>
</resource>
<resource id="email">
<lang name="zh-CN">读取、分类和发送电子邮件</lang>
</resource>
<resource id="emailSystem">
<lang name="zh-CN">读取、分类和发送限制或敏感的电子邮件。</lang>
</resource>
<resource id="enterpriseAuthentication">
<lang name="zh-CN">使用企业域凭据</lang>
</resource>
<resource id="enterpriseDataPolicy">
<lang name="zh-CN">为你的设备定义特定于企业的策略</lang>
</resource>
<resource id="enterpriseDeviceLockdown">
<lang name="zh-CN">使用设备锁定 API 并访问企业共享的存储文件夹</lang>
</resource>
<resource id="extendedExecutionBackgroundAudio">
<lang name="zh-CN">当应用不在前台时播放音频</lang>
</resource>
<resource id="extendedExecutionCritical">
<lang name="zh-CN">开始重要的扩展执行会话</lang>
</resource>
<resource id="extendedExecutionUnconstrained">
<lang name="zh-CN">开始不受限制的扩展执行会话</lang>
</resource>
<resource id="externalDependenciesVirtualCapability">
<lang name="zh-CN">安装外部依赖项</lang>
</resource>
<resource id="firstSignInSettings">
<lang name="zh-CN">在首次登录到设备时访问设置</lang>
</resource>
<resource id="gameList">
<lang name="zh-CN">游戏列表</lang>
</resource>
<resource id="humaninterfacedevice">
<lang name="zh-CN">使用支持人机接口设备 (HID) 协议的设备</lang>
</resource>
<resource id="hyperLinkLearnMore">
<lang name="zh-CN">了解详细信息</lang>
</resource>
<resource id="inputForegroundObservation">
<lang name="zh-CN">当应用程序在前台(处于焦点位置和活动状态)时,观察并截获各种形式的原始输入</lang>
</resource>
<resource id="inputInjection">
<lang name="zh-CN">授予应用权限以将各种形式的输入注入 OneCore 系统</lang>
</resource>
<resource id="inputInjection_Brokered">
<lang name="zh-CN">注入输入并以编程方式推动用户体验</lang>
</resource>
<resource id="inputObservation">
<lang name="zh-CN">观察正在由系统接收的原始输入</lang>
</resource>
<resource id="inputSuppression">
<lang name="zh-CN">取消正在由系统接收的原始输入</lang>
</resource>
<resource id="internetClient">
<lang name="zh-CN">访问 Internet 连接</lang>
</resource>
<resource id="internetClientServer">
<lang name="zh-CN">访问 Internet 连接并充当服务器。</lang>
</resource>
<resource id="interopServices">
<lang name="zh-CN">驱动程序访问</lang>
</resource>
<resource id="localSystemServices">
<lang name="zh-CN">在使用最大权限运行的计算机上安装服务</lang>
</resource>
<resource id="location">
<lang name="zh-CN">使用位置</lang>
</resource>
<resource id="locationHistory">
<lang name="zh-CN">访问设备的位置历史记录</lang>
</resource>
<resource id="locationSystem">
<lang name="zh-CN">定位系统</lang>
</resource>
<resource id="lockScreenCreatives">
<lang name="zh-CN">访问锁屏界面的创造性设置</lang>
</resource>
<resource id="lowLevelDevices">
<lang name="zh-CN">IoT 低级别总线硬件</lang>
</resource>
<resource id="microphone">
<lang name="zh-CN">使用麦克风</lang>
</resource>
<resource id="modifiableApp">
<lang name="zh-CN">允许用户修改应用</lang>
</resource>
<resource id="musicLibrary">
<lang name="zh-CN">使用音乐库</lang>
</resource>
<resource id="networkConnectionManagerProvisioning">
<lang name="zh-CN">定义将设备与 WWAN 和 WLAN 接口相连接的策略</lang>
</resource>
<resource id="networkDataPlanProvisioning">
<lang name="zh-CN">在设备上搜集有关流量套餐的信息并读取网络使用情况</lang>
</resource>
<resource id="networkingVpnProvider">
<lang name="zh-CN">访问 VPN 功能</lang>
</resource>
<resource id="objects3d">
<lang name="zh-CN">以编程方式访问 3D 对象</lang>
</resource>
<resource id="oemDeployment">
<lang name="zh-CN">OEM 和 MO 合作伙伴应用</lang>
</resource>
<resource id="oemPublicDirectory">
<lang name="zh-CN">OEM 和 MO 合作伙伴应用</lang>
</resource>
<resource id="optical">
<lang name="zh-CN">访问光盘驱动器上的功能</lang>
</resource>
<resource id="packagedServices">
<lang name="zh-CN">在计算机上安装服务</lang>
</resource>
<resource id="packageManagement">
<lang name="zh-CN">直接管理其他应用</lang>
</resource>
<resource id="packagePolicySystem">
<lang name="zh-CN">控制与安装在设备上的应用相关的系统策略</lang>
</resource>
<resource id="packageQuery">
<lang name="zh-CN">搜集有关其他应用的信息</lang>
</resource>
<resource id="packageWriteRedirectionCompatibilityShim">
<lang name="zh-CN">将文件写入应用的安装文件夹</lang>
</resource>
<resource id="phoneCall">
<lang name="zh-CN">访问设备上所有的电话线</lang>
</resource>
<resource id="phoneCallHistory">
<lang name="zh-CN">读取呼叫历史记录并删除历史记录中的条目</lang>
</resource>
<resource id="phoneCallHistoryPublic">
<lang name="zh-CN">电话呼叫公共历史记录</lang>
</resource>
<resource id="phoneCallHistorySystem">
<lang name="zh-CN">完全修改呼叫历史记录</lang>
</resource>
<resource id="picturesLibrary">
<lang name="zh-CN">使用图片库</lang>
</resource>
<resource id="pointOfService">
<lang name="zh-CN">使用条形码扫描仪和磁卡读卡器</lang>
</resource>
<resource id="previewStore">
<lang name="zh-CN">Microsoft Store 预览版功能</lang>
</resource>
<resource id="previewUiComposition">
<lang name="zh-CN">预览 Windows UI 构成 API 以接收反馈</lang>
</resource>
<resource id="privateNetworkClientServer">
<lang name="zh-CN">访问家庭或工作网络</lang>
</resource>
<resource id="proximity">
<lang name="zh-CN">使用支持近场通信 (NFC) 服务的设备</lang>
</resource>
<resource id="recordedCallsFolder">
<lang name="zh-CN">访问电话录音</lang>
</resource>
<resource id="remotePassportAuthentication">
<lang name="zh-CN">访问可用于解锁远程电脑的凭据</lang>
</resource>
<resource id="removableStorage">
<lang name="zh-CN">使用存储在外部存储设备上的数据</lang>
</resource>
<resource id="runFullTrust">
<lang name="zh-CN">使用全部系统资源</lang>
</resource>
<resource id="screenDuplication">
<lang name="zh-CN">在其他设备上投射屏幕</lang>
</resource>
<resource id="sharedUserCertificates">
<lang name="zh-CN">使用设备上可用的软件和硬件证书</lang>
</resource>
<resource id="smsSend">
<lang name="zh-CN">发送短信和彩信</lang>
</resource>
<resource id="spatialPerception">
<lang name="zh-CN">查看你当前和过去的环境</lang>
</resource>
<resource id="systemManagement">
<lang name="zh-CN">IoT 系统管理</lang>
</resource>
<resource id="teamEditionExperience">
<lang name="zh-CN">访问控制试验体验的内部 API</lang>
</resource>
<resource id="uiAccess">
<lang name="zh-CN">与你的计算机上的每个应用程序交互</lang>
</resource>
<resource id="unvirtualizedResources">
<lang name="zh-CN">写入在卸载时不会清除的注册表项和文件</lang>
</resource>
<resource id="usb">
<lang name="zh-CN">访问 USB 连接的设备</lang>
</resource>
<resource id="userAccountInformation">
<lang name="zh-CN">访问帐户的用户名和头像</lang>
</resource>
<resource id="userDataAccountSetup">
<lang name="zh-CN">直接访问存储在设备上的帐户</lang>
</resource>
<resource id="userDataAccountsProvider">
<lang name="zh-CN">用户数据帐户提供程序</lang>
</resource>
<resource id="userDataSystem">
<lang name="zh-CN">对你的数据具有不受限制的访问权限</lang>
</resource>
<resource id="userPrincipalName">
<lang name="zh-CN">检索用户主体名称 (UPN),无需许可提示</lang>
</resource>
<resource id="userSigninSupport">
<lang name="zh-CN">在设备上使用帐户登录到应用</lang>
</resource>
<resource id="videosLibrary">
<lang name="zh-CN">使用视频库</lang>
</resource>
<resource id="visualElementsSystem">
<lang name="zh-CN">访问应用的磁贴数据</lang>
</resource>
<resource id="visualVoiceMail">
<lang name="zh-CN">对可视语音信箱具有完全访问权限</lang>
</resource>
<resource id="voipCall">
<lang name="zh-CN">使用设备的 IP 语音 (VoIP) 服务</lang>
</resource>
<resource id="walletSystem">
<lang name="zh-CN">对存储的“电子钱包”应用卡具有完全访问权限</lang>
</resource>
<resource id="webcam">
<lang name="zh-CN">使用网络摄像头</lang>
</resource>
<resource id="wiFiControl">
<lang name="zh-CN">扫描并连接到 WLAN 网络</lang>
</resource>
<resource id="xboxAccessoryManagement">
<lang name="zh-CN">Xbox 附件</lang>
</resource>
<resource id="backgroundMediaPlayback">
<lang name="zh-CN">在后台播放媒体</lang>
</resource>
<resource id="extendedExecution">
<lang name="zh-CN">允许应用程序在进入后台后继续执行一段时间的操作</lang>
</resource>
<resource id="graphicsCaptureProgrammatic">
<lang name="zh-CN">允许使用图形捕获</lang>
</resource>
<resource id="graphicsCaptureWithoutBorder">
<lang name="zh-CN">允许无边框图形捕获</lang>
</resource>
<resource id="inProcessMediaExtension">
<lang name="zh-CN">进程内媒体扩展</lang>
</resource>
<resource id="inputInjectionBrokered">
<lang name="zh-CN">允许应用程序以编程方式将各种形式的输入注入系统,例如 HID、触摸、笔、键盘或鼠标。</lang>
</resource>
<resource id="offlineMapsManagement">
<lang name="zh-CN">允许应用程序访问离线地图。</lang>
</resource>
<resource id="phoneCallSystem">
<lang name="zh-CN">允许应用访问设备上的所有电话线</lang>
</resource>
<resource id="remoteSystem">
<lang name="zh-CN">允许应用程序访问与用户的 Microsoft 帐户关联的设备列表</lang>
</resource>
<resource id="slapiQueryLicenseValue">
<lang name="zh-CN">查询软件许可政策</lang>
</resource>
<resource id="storeAppInstall">
<lang name="zh-CN">管理应用安装</lang>
</resource>
<resource id="userDataAccounts">
<lang name="zh-CN">可访问电子邮件、联系人、日历等的用户数据帐户</lang>
</resource>
<resource id="userDataTasks">
<lang name="zh-CN">允许应用程序访问任务设置的当前状态</lang>
</resource>
<resource id="userDataTasksSystem">
<lang name="zh-CN">可访问系统任务项</lang>
</resource>
<resource id="userNotificationListener">
<lang name="zh-CN">允许应用程序访问通知设置的当前状态</lang>
</resource>
<resource id="webPlatformMediaExtension">
<lang name="zh-CN">Web 平台媒体扩展</lang>
</resource>
</resources>