mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
Update Shell
This commit is contained in:
Binary file not shown.
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
248
appinstaller/localeex.h
Normal 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
@@ -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.
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
131
notice/notice.h
131
notice/notice.h
@@ -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 文档。第一个参数是必须的。第二个参数为图片 URI(file:///)。
|
||||
// 第二个参数如果为 NULL 或去掉首尾空的长度为 0 的文本则不会使用带图片的模板。
|
||||
// 注意:返回的指针要自己通过 free 释放
|
||||
// 注意:返回的指针要自己通过 NoticeApiFreeString 释放
|
||||
NOTICE_API LPWSTR GenerateSimpleToastNoticeXml (LPCWSTR lpText, LPCWSTR lpImagePath);
|
||||
// 获取一个简单的 Toast 通知 XML 文档。第一个参数是必须的。第三个参数为图片 URI(file:///)。
|
||||
// 第三个参数如果为 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
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }
|
||||
496
pkgmgr/pkgmgr.h
496
pkgmgr/pkgmgr.h
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
871
pkgread/filepath.h
Normal 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
51
pkgread/module.h
Normal 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
|
||||
@@ -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>
|
||||
@@ -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 ());
|
||||
}
|
||||
@@ -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.
@@ -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>
|
||||
@@ -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
121
pkgread/rctools.h
Normal 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
|
||||
@@ -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
154
pkgread/strcmp.h
Normal 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 ();
|
||||
}
|
||||
@@ -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
265
pkgread/typestrans.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
376
shared/html/deepseek_html_20251122_6d71df.html
Normal file
376
shared/html/deepseek_html_20251122_6d71df.html
Normal 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>
|
||||
@@ -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"></span> <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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; },
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
33
shared/html/js/tileback.js
Normal file
33
shared/html/js/tileback.js
Normal 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
|
||||
}
|
||||
};
|
||||
})();
|
||||
412
shared/locale/capabilities.xml
Normal file
412
shared/locale/capabilities.xml
Normal 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>
|
||||
Reference in New Issue
Block a user