Updates for WebUI:

· [Important] Fixed the destruction issue with PriReader (caused by incorrect pointer types leading to unexecuted object destruction tasks).
· [Important] Added a program execution selection interface for packages containing multiple applications (still using WebUI).
 Issue: Since the selection window is set to close when losing focus, checking the "Launch when ready" option after successful installation causes the pop-up window to disappear when a Toast notification appears (due to focus loss). Currently, the selection window can only be displayed by clicking a button.
· [Optimization] Reduced the creation of PriReader objects to lower memory and storage consumption.
(Translated by DeepSeek)
This commit is contained in:
Bruce
2025-03-02 00:33:09 +08:00
parent ff0cebc7cc
commit 949759ffe9
14 changed files with 2445 additions and 60 deletions

View File

@@ -1,6 +1,5 @@
// Microsoft Visual C++ generated resource script. // Microsoft Visual C++ generated resource script.
// //
#include <Windows.h>
#include "resource.h" #include "resource.h"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources // 中文(简体,中国) resources
@@ -115,8 +114,8 @@ IDR_MANIFEST1 RT_MANIFEST "res/manifest.xml"
// //
IDR_VERSION_ZH_CN VERSIONINFO IDR_VERSION_ZH_CN VERSIONINFO
FILEVERSION 1,0,1,7 FILEVERSION 1,0,1,9
PRODUCTVERSION 1,0,1,7 PRODUCTVERSION 1,0,1,9
FILEFLAGSMASK 0x0L FILEFLAGSMASK 0x0L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@@ -133,9 +132,9 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Bruce Winter" VALUE "CompanyName", "Bruce Winter"
VALUE "FileDescription", "应用安装程序" VALUE "FileDescription", "应用安装程序"
VALUE "FileVersion", "1.0.1.7" VALUE "FileVersion", "1.0.1.9"
VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved." VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved."
VALUE "ProductVersion", "1.0.1.7" VALUE "ProductVersion", "1.0.1.9"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@@ -145,8 +144,8 @@ BEGIN
END END
IDR_VERSION_EN_US VERSIONINFO IDR_VERSION_EN_US VERSIONINFO
FILEVERSION 1,0,1,7 FILEVERSION 1,0,1,9
PRODUCTVERSION 1,0,1,7 PRODUCTVERSION 1,0,1,9
FILEFLAGSMASK 0x0L FILEFLAGSMASK 0x0L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@@ -163,9 +162,9 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Bruce Winter" VALUE "CompanyName", "Bruce Winter"
VALUE "FileDescription", "App Installer" VALUE "FileDescription", "App Installer"
VALUE "FileVersion", "1.0.1.7" VALUE "FileVersion", "1.0.1.9"
VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved." VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved."
VALUE "ProductVersion", "1.0.1.7" VALUE "ProductVersion", "1.0.1.9"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@@ -239,6 +238,9 @@ BEGIN
PAGE_1_APP "Microsoft Store 应用" PAGE_1_APP "Microsoft Store 应用"
PAGE_2_LOADING "请稍候..." PAGE_2_LOADING "请稍候..."
PAGE_2_INSTALLING "正在安装 %d%%" PAGE_2_INSTALLING "正在安装 %d%%"
APPLIST_WINTITLE "应用选择列表"
APPLIST_TITLE "你要从哪个应用开始?"
APPLIST_BUTTON_CANCEL "取消"
CLHELP_1 "命令行参数说明:\n\n" CLHELP_1 "命令行参数说明:\n\n"
CLHELP_2 "\t/?, /Help\n\t显示帮助窗口 (命令行参数说明)\n\n" CLHELP_2 "\t/?, /Help\n\t显示帮助窗口 (命令行参数说明)\n\n"
CLHELP_3 "\t/DisableFrame\n\t禁止使用自绘的窗口边框\n\n" CLHELP_3 "\t/DisableFrame\n\t禁止使用自绘的窗口边框\n\n"
@@ -404,6 +406,9 @@ BEGIN
PAGE_1_APP "Microsoft Store App" PAGE_1_APP "Microsoft Store App"
PAGE_2_LOADING "Please wait..." PAGE_2_LOADING "Please wait..."
PAGE_2_INSTALLING "Installing %d%%" PAGE_2_INSTALLING "Installing %d%%"
APPLIST_WINTITLE "App Select List"
APPLIST_TITLE "Which app do you want to start with?"
APPLIST_BUTTON_CANCEL "Cancel"
CLHELP_1 "Usage:\n\n" CLHELP_1 "Usage:\n\n"
CLHELP_2 "\t/?, /Help\n\tDisplay help window (command line parameter description).\n\n" CLHELP_2 "\t/?, /Help\n\tDisplay help window (command line parameter description).\n\n"
CLHELP_3 "\t/DisableFrame\n\tDisable the use of self-drawn window borders.\n\n" CLHELP_3 "\t/DisableFrame\n\tDisable the use of self-drawn window borders.\n\n"

View File

@@ -138,6 +138,11 @@
<AdditionalDependencies>shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib</AdditionalDependencies> <AdditionalDependencies>shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel> <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link> </Link>
<Manifest>
<AdditionalManifestFiles>app.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles>
<InputResourceManifests>
</InputResourceManifests>
</Manifest>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile> <ClCompile>
@@ -191,6 +196,9 @@
</Link> </Link>
<Manifest> <Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness> <EnableDpiAwareness>false</EnableDpiAwareness>
<AdditionalManifestFiles>app.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles>
<InputResourceManifests>
</InputResourceManifests>
</Manifest> </Manifest>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
@@ -252,6 +260,7 @@
<ResourceCompile Include="AppInstaller.rc" /> <ResourceCompile Include="AppInstaller.rc" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="CustomMarshalers" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Drawing"> <Reference Include="System.Drawing">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll</HintPath> <HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll</HintPath>

17
AppInstaller/app.manifest Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>

View File

@@ -31,18 +31,20 @@ std::wstring GetFileNameWithoutExtension (const std::wstring &filePath)
return GetFileNameWithoutExtension (filePath.c_str ()); return GetFileNameWithoutExtension (filePath.c_str ());
} }
std::string GetLogoBase64FromReader (PackageReader &reader, IStream **getOutput = NULL) std::string GetLogoBase64FromReader (PackageReader &reader, IStream **getOutput = NULL, PriReader *priread = NULL)
{ {
if (!&reader) return std::string (""); if (!&reader) return std::string ("");
if (!reader.isAvailable ()) return std::string (""); if (!reader.isAvailable ()) return std::string ("");
std::wstring logoPath = reader.getPropertyLogo (); std::wstring logoPath = reader.getPropertyLogo ();
if (logoPath.empty () || logoPath.length () == 0) return std::string (""); if (logoPath.empty () || logoPath.length () == 0) return std::string ("");
PriReader pri (reader.getPriFileStream ()); PriReader *pri = ((priread != NULL) ? priread : new PriReader (reader.getPriFileStream ()));
if (pri.isAvailable ()) if (pri->isAvailable ())
{ {
std::wstring logoPathFromPri = pri.findFilePathValue (logoPath); std::wstring logoPathFromPri = pri->findFilePathValue (logoPath);
if (!logoPathFromPri.empty () && logoPath.length () > 0) logoPath = logoPathFromPri; if (!logoPathFromPri.empty () && logoPath.length () > 0) logoPath = logoPathFromPri;
} }
if (priread == NULL) delete pri;
pri = NULL;
IStream *imgfile = reader.extractFileToStream (logoPath); IStream *imgfile = reader.extractFileToStream (logoPath);
if (getOutput) *getOutput = imgfile; if (getOutput) *getOutput = imgfile;
if (!imgfile) if (!imgfile)
@@ -288,4 +290,528 @@ std::string GetLogoBase64FromReader (PackageReader &reader, IStream **getOutput
b64res = "data:image/png;base64," + b64res; b64res = "data:image/png;base64," + b64res;
} }
return b64res; return b64res;
}
std::string GetBase64FromPath (PackageReader &reader, LPCWSTR lpswImgPath, IStream **getOutput = NULL, PriReader *priread = NULL)
{
if (!&reader) return std::string ("");
if (!reader.isAvailable ()) return std::string ("");
if (!lpswImgPath) return std::string ("");
std::wstring logoPath = std::wstring (lpswImgPath);
if (logoPath.empty () || logoPath.length () == 0) return std::string ("");
PriReader *pri = ((priread != NULL) ? priread : new PriReader (reader.getPriFileStream ()));
if (pri->isAvailable ())
{
std::wstring logoPathFromPri = pri->findFilePathValue (logoPath);
if (!logoPathFromPri.empty () && logoPath.length () > 0) logoPath = logoPathFromPri;
}
if (priread == NULL) delete pri;
pri = NULL;
IStream *imgfile = reader.extractFileToStream (logoPath);
if (getOutput) *getOutput = imgfile;
if (!imgfile)
{
std::wstring fileName = GetFileNameWithoutExtension (logoPath);
IAppxPackageReader *appxreader = reader.getAppxPackageReader ();
CComPtr <IAppxFilesEnumerator> fe = NULL;
HRESULT hr = appxreader->GetPayloadFiles (&fe);
if (SUCCEEDED (hr) && fe)
{
std::vector <std::wstring> files;
BOOL hasCurrent = FALSE;
hr = fe->GetHasCurrent (FALSE);
while (SUCCEEDED (hr) && hasCurrent)
{
CComPtr <IAppxFile> ifile = NULL;
hr = fe->GetCurrent (&ifile);
if (SUCCEEDED (hr) && ifile)
{
LPWSTR lpstr = NULL;
if (SUCCEEDED (ifile->GetName (&lpstr)) && lpstr)
{
std::wstring strWillSearch = StringToUpper (StringTrim (lpstr));
std::wstring strWillToSearch = StringToUpper (StringTrim (fileName));
if (StrStrW (strWillSearch.c_str (), strWillToSearch.c_str ()))
{
bool isFind = LabelEqual (PathFindExtensionW (lpstr), L".png");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpg");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpeg");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".bmp");
if (isFind)
{
std::wstring temp (L"");
if (lpstr) temp += lpstr;
if (temp.length () > 0) push_no_repeat (files, temp);
}
}
}
}
}
bool isFindSuit = false;
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-white")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-black")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
for (auto it : files)
{
logoPath = std::wstring (L"") + it;
break;
}
}
}
imgfile = reader.extractFileToStream (logoPath);
}
if (getOutput) *getOutput = imgfile;
if (!imgfile) return std::string ("");
std::string b64res ("");
LPSTR szRes = StreamToBase64 (imgfile);
if (!getOutput)
{
if (imgfile)
{
imgfile->Release ();
imgfile = NULL;
}
}
if (!szRes) return b64res;
if (szRes) b64res += szRes;
free (szRes);
if (b64res.length () > 0)
{
b64res = "data:image/png;base64," + b64res;
}
return b64res;
}
std::wstring GetBase64FromPathW (PackageReader &reader, LPCWSTR lpswImgPath, IStream **getOutput = NULL, PriReader *priread = NULL)
{
if (!&reader) return std::wstring (L"");
if (!reader.isAvailable ()) return std::wstring (L"");
if (!lpswImgPath) return std::wstring (L"");
std::wstring logoPath = std::wstring (lpswImgPath);
if (logoPath.empty () || logoPath.length () == 0) return std::wstring (L"");
PriReader *pri = ((priread != NULL) ? priread : new PriReader (reader.getPriFileStream ()));
if (pri->isAvailable ())
{
std::wstring logoPathFromPri = pri->findFilePathValue (logoPath);
if (!logoPathFromPri.empty () && logoPath.length () > 0) logoPath = logoPathFromPri;
}
if (priread == NULL) delete pri;
pri = NULL;
IStream *imgfile = reader.extractFileToStream (logoPath);
if (getOutput) *getOutput = imgfile;
if (!imgfile)
{
std::wstring fileName = GetFileNameWithoutExtension (logoPath);
IAppxPackageReader *appxreader = reader.getAppxPackageReader ();
CComPtr <IAppxFilesEnumerator> fe = NULL;
HRESULT hr = appxreader->GetPayloadFiles (&fe);
if (SUCCEEDED (hr) && fe)
{
std::vector <std::wstring> files;
BOOL hasCurrent = FALSE;
hr = fe->GetHasCurrent (FALSE);
while (SUCCEEDED (hr) && hasCurrent)
{
CComPtr <IAppxFile> ifile = NULL;
hr = fe->GetCurrent (&ifile);
if (SUCCEEDED (hr) && ifile)
{
LPWSTR lpstr = NULL;
if (SUCCEEDED (ifile->GetName (&lpstr)) && lpstr)
{
std::wstring strWillSearch = StringToUpper (StringTrim (lpstr));
std::wstring strWillToSearch = StringToUpper (StringTrim (fileName));
if (StrStrW (strWillSearch.c_str (), strWillToSearch.c_str ()))
{
bool isFind = LabelEqual (PathFindExtensionW (lpstr), L".png");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpg");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpeg");
if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".bmp");
if (isFind)
{
std::wstring temp (L"");
if (lpstr) temp += lpstr;
if (temp.length () > 0) push_no_repeat (files, temp);
}
}
}
}
}
bool isFindSuit = false;
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-white")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
std::map <int, std::wstring> scaleFiles;
std::wregex pattern (L"(scale-(\\d+))");
for (auto it : files)
{
if (StrStrW (it.c_str (), L"contrast-black")) continue;
std::wsmatch match;
if (std::regex_search (it, match, pattern))
{
int temp = StrToIntW (match [1].str ().c_str ());
if (!temp)
{
scaleFiles [temp] = it;
}
}
}
if (scaleFiles.find (GetDPI ()) != scaleFiles.end ())
{
isFindSuit = true;
logoPath = scaleFiles [GetDPI ()];
}
else
{
bool isFindScale = false;
for (auto it : scaleFiles)
{
if (it.first >= GetDPI ())
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
if (it.first >= 100)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
}
if (!isFindScale)
{
for (auto it : scaleFiles)
{
isFindScale = true;
logoPath = scaleFiles [GetDPI ()];
break;
}
}
isFindSuit = isFindScale;
}
}
if (!isFindSuit)
{
for (auto it : files)
{
logoPath = std::wstring (L"") + it;
break;
}
}
}
imgfile = reader.extractFileToStream (logoPath);
}
if (getOutput) *getOutput = imgfile;
if (!imgfile) return std::wstring (L"");
std::wstring b64res (L"");
LPWSTR szRes = StreamToBase64W (imgfile);
if (!getOutput)
{
if (imgfile)
{
imgfile->Release ();
imgfile = NULL;
}
}
if (!szRes) return b64res;
if (szRes) b64res += szRes;
free (szRes);
if (b64res.length () > 0)
{
b64res = L"data:image/png;base64," + b64res;
}
return b64res;
} }

View File

@@ -28,6 +28,16 @@
using namespace System; using namespace System;
using namespace System::Windows::Forms; using namespace System::Windows::Forms;
using namespace System::Threading; using namespace System::Threading;
using namespace msclr::interop;
int GetScreenWidth ()
{
return GetSystemMetrics (SM_CXSCREEN);
}
int GetScreenHeight ()
{
return GetSystemMetrics (SM_CYSCREEN);
}
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_) #define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_) #define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
@@ -177,27 +187,23 @@ std::wstring StrPrintFormatW (LPCWSTR format, ...)
void SetWebBrowserEmulation () void SetWebBrowserEmulation ()
{ {
// 获取应用程序的可执行文件 String^ appName = System::IO::Path::GetFileName (Application::ExecutablePath); // 包含扩展
String ^appName = System::IO::Path::GetFileNameWithoutExtension (System::Windows::Forms::Application::ExecutablePath); IntPtr appNamePtr = System::Runtime::InteropServices::Marshal::StringToHGlobalUni (appName);
const wchar_t *appNameWChar = (const wchar_t *)(void *)System::Runtime::InteropServices::Marshal::StringToHGlobalUni (appName); const wchar_t* appNameWChar = static_cast<const wchar_t*>(appNamePtr.ToPointer ());
BOOL is64Bit = FALSE; BOOL isWow64 = FALSE;
IsWow64Process (GetCurrentProcess (), &is64Bit); IsWow64Process (GetCurrentProcess (), &isWow64);
HKEY hKey; HKEY hKey;
long regOpenResult = ERROR_SUCCESS; LPCWSTR keyPath = isWow64
if (is64Bit) ? L"SOFTWARE\\WOW6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION"
: L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION";
LONG result = RegOpenKeyExW (HKEY_CURRENT_USER, keyPath, 0, KEY_WRITE, &hKey);
if (result == ERROR_SUCCESS)
{ {
regOpenResult = RegOpenKeyExW (HKEY_CURRENT_USER, L"SOFTWARE\\WOW6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", 0, KEY_WRITE, &hKey); DWORD value = 11001;
} RegSetValueExW (hKey, appNameWChar, 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof (value));
else
{
regOpenResult = RegOpenKeyExW (HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", 0, KEY_WRITE, &hKey);
}
if (regOpenResult == ERROR_SUCCESS)
{
DWORD ie11Mode = 11001;
RegSetValueExW (hKey, appNameWChar, 0, REG_DWORD, (const BYTE *)&ie11Mode, sizeof (DWORD));
RegCloseKey (hKey); RegCloseKey (hKey);
} }
System::Runtime::InteropServices::Marshal::FreeHGlobal (appNamePtr);
} }
#include <windows.h> #include <windows.h>
@@ -237,6 +243,17 @@ bool IsIeVersion10 ()
RegCloseKey (hKey); RegCloseKey (hKey);
return isIe10; return isIe10;
} }
bool IsWindows10AndLater ()
{
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
osvi.dwMajorVersion = 10;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION (conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfoW (&osvi, VER_MAJORVERSION, conditionMask)) return TRUE;
DWORD error = GetLastError ();
return (error == ERROR_OLD_WIN_VERSION) ? FALSE : FALSE;
}
size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter, size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter,
std::vector <std::wstring> &outFiles, bool recursive = false) std::vector <std::wstring> &outFiles, bool recursive = false)
@@ -313,6 +330,136 @@ HRESULT SetCurrentAppUserModelID (PCWSTR appID)
void ProgressCallback (unsigned progress); void ProgressCallback (unsigned progress);
void ToastPressCallback (); void ToastPressCallback ();
void OutputDebugStringFormatted (const wchar_t* format, ...);
public ref class AppWindow: public Form
{
private:
WebBrowser ^webUI;
std::vector <appmap> *appItems = new std::vector <appmap> ();
System::Collections::Generic::Dictionary <String ^, Delegate ^> ^jsFunctionHandlers;
public:
AppWindow ()
{
this->Visible = false;
jsFunctionHandlers = gcnew System::Collections::Generic::Dictionary <String ^, Delegate ^> ();
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->ShowInTaskbar = false;
this->TopMost = true;
this->Size = System::Drawing::Size (392, 494);
if (IsWindows10AndLater ()) this->MinimumSize = System::Drawing::Size (392, 226);
else this->MinimumSize = System::Drawing::Size (392, 129);
if (IsWindows10AndLater ()) this->MaximumSize = System::Drawing::Size (392, 522);
else this->MaximumSize = System::Drawing::Size (368, 394);
this->Text = rcString (APPLIST_WINTITLE);
webUI = gcnew WebBrowser ();
webUI->Dock = DockStyle::Fill;
this->Controls->Add (webUI);
String ^rootDir = System::IO::Path::GetDirectoryName (System::Windows::Forms::Application::ExecutablePath);
String ^htmlFilePath = System::IO::Path::Combine (rootDir, "HTML\\Libs\\AppList.html");
if (IsIeVersion10 ()) htmlFilePath = System::IO::Path::Combine (rootDir, "HTML\\Libs\\AppListIE10.html"); // IE10 (Win8) 特供
if (IsWindows10AndLater ()) htmlFilePath = System::IO::Path::Combine (rootDir, "HTML\\Libs\\AppListWin10.html"); // Windows 10 及以上版本的风格
webUI->Navigate (htmlFilePath);
webUI->ObjectForScripting = this;
this->webUI->IsWebBrowserContextMenuEnabled = false;
webUI->DocumentCompleted += gcnew WebBrowserDocumentCompletedEventHandler (this, &AppWindow::OnDocumentCompleted);
this->StartPosition = FormStartPosition::CenterScreen;
this->Deactivate += gcnew EventHandler (this, &AppWindow::eventOnDeactivate);
}
void OnDocumentCompleted (Object ^sender, WebBrowserDocumentCompletedEventArgs ^e)
{
CallJSFunction ("SetText", gcnew array <Object ^> {
"span-title",
rcString (APPLIST_TITLE)
});
CallJSFunction ("SetText", gcnew array <Object ^> {
"button-cancel-window",
rcString (APPLIST_BUTTON_CANCEL)
});
this->Visible = true;
Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &AppWindow::InvokeRefreshAppItems));
thread->Start ();
}
void SendAppData (std::vector<appmap> apps)
{
if (appItems) delete appItems;
appItems = nullptr;
appItems = new std::vector <appmap> ();
for (auto it : apps)
{
appItems->push_back (it);
}
this->InvokeRefreshAppItems ();
}
void eventLaunchApp (String ^appModelUserId)
{
DWORD dwPId = 0;
LaunchApp ((marshal_as <std::wstring> (appModelUserId)).c_str (), &dwPId);
this->Close ();
}
void eventCancelWindow ()
{
if (this->IsHandleCreated) this->Close ();
}
void eventOnDeactivate (Object ^sender, EventArgs ^e)
{
if (this->IsHandleCreated) this->Close ();
}
~AppWindow ()
{
if (appItems) delete appItems;
appItems = nullptr;
}
private:
Object ^CallJSFunction (String ^functionName, ... array<Object^> ^args)
{
if (webUI->Document != nullptr)
{
try
{
return webUI->Document->InvokeScript (functionName, args);
}
catch (Exception^ ex)
{
MessageBox::Show ("Error calling JavaScript function: " + ex->Message);
return nullptr;
}
}
return nullptr;
}
void InvokeRefreshAppItems ()
{
if (this->InvokeRequired)
{
this->Invoke (gcnew Action (this, &AppWindow::RefreshAppItems));
}
else
{
RefreshAppItems ();
}
}
void RefreshAppItems ()
{
CallJSFunction ("ClearListItems", gcnew array <Object ^> { });
bool isWin10 = IsWindows10AndLater ();
size_t height = ((appItems->size ()) * (isWin10 ? 50 : 60)) + (isWin10 ? 206 : 120);
if (height < (isWin10 ? 522 : 394)) this->Height = height;
else this->Height = 522;
this->Left = (GetScreenWidth () - this->Width) / 2;
this->Top = (GetScreenHeight () - this->Height) / 2;
for (auto it : *appItems)
{
String ^colorStr = gcnew String (it [L"BackgroundColor"].c_str ());
if (LabelEqual (it [L"BackgroundColor"], L"transparent")) colorStr = ColorToHtml (GetAeroColor ());
CallJSFunction ("AddListItems", gcnew array <Object ^> {
gcnew String (it [L"AppUserModelID"].c_str ()),
gcnew String (it [L"Square44x44LogoBase64"].c_str ()),
colorStr,
gcnew String (it [L"DisplayName"].c_str ())
});
}
}
};
public ref class MainWnd: public Form public ref class MainWnd: public Form
{ {
@@ -432,7 +579,9 @@ public ref class MainWnd: public Form
{ {
this->Visible = true; this->Visible = true;
this->setLaunchWhenReadyJS (m_initConfig.readBoolValue (L"Settings", L"LaunchWhenReady", true)); this->setLaunchWhenReadyJS (m_initConfig.readBoolValue (L"Settings", L"LaunchWhenReady", true));
#ifdef _DEBUG
if (IsIeVersion10 ()) hideFrameJS (false); if (IsIeVersion10 ()) hideFrameJS (false);
#endif
Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskReadFile)); Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskReadFile));
thread->Start (); thread->Start ();
Thread ^thread2 = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountDarkMode)); Thread ^thread2 = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountDarkMode));
@@ -468,6 +617,7 @@ public ref class MainWnd: public Form
thread->SetApartmentState (ApartmentState::STA); thread->SetApartmentState (ApartmentState::STA);
thread->Start (); thread->Start ();
} break; } break;
case 3: break;
case 4: case 4:
{ {
// this->setButtonDisabledJS (true); // this->setButtonDisabledJS (true);
@@ -481,6 +631,17 @@ public ref class MainWnd: public Form
m_pkgInfo.getApplicationUserModelIDs (ids); m_pkgInfo.getApplicationUserModelIDs (ids);
DWORD dwPId = 0; DWORD dwPId = 0;
if (ids.size () == 1) LaunchApp (ids [0].c_str (), &dwPId); if (ids.size () == 1) LaunchApp (ids [0].c_str (), &dwPId);
else if (ids.size () > 1)
{
AppWindow ^appWnd = gcnew AppWindow ();
std::vector <appmap> apps;
m_pkgInfo.getApplications (apps);
appWnd->SendAppData (apps);
appWnd->StartPosition = FormStartPosition::CenterScreen;
//appWnd->Owner = this;
appWnd->Show ();
//appWnd->ShowDialog ();
}
} }
// this->setButtonDisabledJS (false); // this->setButtonDisabledJS (false);
} break; } break;
@@ -490,6 +651,17 @@ public ref class MainWnd: public Form
} break; } break;
} }
} }
void invokeEventOnPress_button1 ()
{
if (this->InvokeRequired)
{
this->Invoke (gcnew Action (this, &MainWnd::eventOnPress_button1));
}
else
{
eventOnPress_button1 ();
}
}
void eventOnPress_button2 () void eventOnPress_button2 ()
{ {
@@ -830,18 +1002,21 @@ public ref class MainWnd: public Form
setPicBoxVisibilityJS (false); setPicBoxVisibilityJS (false);
if (serial > 1) if (serial > 1)
{ {
std::string res = m_pkgInfo.getPropertyLogoBase64 (); if (serial = 2)
if (m_pkgInfo.getPropertyLogoIStream () && !res.empty () && res.length () > 10)
{ {
std::string b64logo = res; std::string res = m_pkgInfo.getPropertyLogoBase64 ();
// MessageBox::Show (gcnew String ((std::string ("Base 64 String: ") + b64logo).c_str ())); if (m_pkgInfo.getPropertyLogoIStream () && !res.empty () && res.length () > 10)
this->setStoreLogoJS (gcnew String (res.c_str ())); {
setPicBoxVisibilityJS (true); std::string b64logo = res;
} // MessageBox::Show (gcnew String ((std::string ("Base 64 String: ") + b64logo).c_str ()));
else this->setStoreLogoJS (gcnew String (res.c_str ()));
{ setPicBoxVisibilityJS (true);
this->setStoreLogoJS ("./Libs/Images/StoreLogo.png"); }
setPicBoxVisibilityJS (false); else
{
this->setStoreLogoJS ("./Libs/Images/StoreLogo.png");
setPicBoxVisibilityJS (false);
}
} }
} }
else else
@@ -896,6 +1071,17 @@ public ref class MainWnd: public Form
pTaskbarList->Release (); pTaskbarList->Release ();
} }
} }
void invokeSetTaskbarProgress (int value)
{
if (this->InvokeRequired)
{
this->Invoke (gcnew Action <int> (this, &MainWnd::setTaskbarProgress), value);
}
else
{
setTaskbarProgress (value);
}
}
void clearTaskbarProgress () void clearTaskbarProgress ()
{ {
IntPtr hwnd = this->Handle; IntPtr hwnd = this->Handle;
@@ -911,6 +1097,17 @@ public ref class MainWnd: public Form
pTaskbarList->Release (); pTaskbarList->Release ();
} }
} }
void invokeClearTaskbarProgress ()
{
if (this->InvokeRequired)
{
this->Invoke (gcnew Action (this, &MainWnd::clearTaskbarProgress));
}
else
{
clearTaskbarProgress ();
}
}
bool invokeGetLaunchWhenReady () bool invokeGetLaunchWhenReady ()
{ {
if (this->InvokeRequired) if (this->InvokeRequired)
@@ -985,10 +1182,7 @@ public ref class MainWnd: public Form
if (status == InstallStatus::Success) if (status == InstallStatus::Success)
{ {
invokeSetPage (4); invokeSetPage (4);
if (this->invokeGetLaunchWhenReady ()) if (m_pkgInfo.applications.size () == 1 && !m_silentMode) this->eventOnPress_button1 (); // 用于启用 APP
{
if (reader.isPackageApplication ()) this->eventOnPress_button1 (); // 用于启用 APP
}
Thread ^closeThread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountCancel)); Thread ^closeThread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountCancel));
closeThread->IsBackground = true; closeThread->IsBackground = true;
closeThread->Start (); closeThread->Start ();
@@ -1003,7 +1197,7 @@ public ref class MainWnd: public Form
closeThread->Start (); closeThread->Start ();
} }
} }
this->clearTaskbarProgress (); this->invokeClearTaskbarProgress ();
std::wstring title = StrPrintFormatW (GetRCString_cpp (PAGE_4_TITLE).c_str (), m_pkgInfo.getPropertyName ().c_str ()); std::wstring title = StrPrintFormatW (GetRCString_cpp (PAGE_4_TITLE).c_str (), m_pkgInfo.getPropertyName ().c_str ());
std::wstring text (L""); std::wstring text (L"");
if (GetLastErrorDetailTextLength ()) text += GetLastErrorDetailText (); if (GetLastErrorDetailTextLength ()) text += GetLastErrorDetailText ();
@@ -1015,7 +1209,12 @@ public ref class MainWnd: public Form
} }
void taskCountCancel () void taskCountCancel ()
{ {
for (char cnt = 0; cnt < 100; cnt ++) int size = (int)m_pkgInfo.applications.size ();
if (size < 1) size = 1;
if (size > 5) size = 5;
if (m_silentMode) size = 1; // 不耽误时间
int tcnt = size * 100;
for (int cnt = 0; cnt < tcnt; cnt ++)
{ {
if (!this->IsHandleCreated) break; if (!this->IsHandleCreated) break;
Thread::Sleep (50); Thread::Sleep (50);
@@ -1052,7 +1251,7 @@ public ref class MainWnd: public Form
} }
public: public:
[STAThread] [STAThread]
void Button1_PressEvent () { eventOnPress_button1 (); } void Button1_PressEvent () { invokeEventOnPress_button1 (); }
[STAThread] [STAThread]
void Button2_PressEvent () { eventOnPress_button2 (); } void Button2_PressEvent () { eventOnPress_button2 (); }
[STAThread] [STAThread]
@@ -1075,7 +1274,7 @@ public ref class MainWnd: public Form
StrPrintFormatW (GetRCString_cpp (PAGE_2_INSTALLING).c_str (), (int)value).c_str () StrPrintFormatW (GetRCString_cpp (PAGE_2_INSTALLING).c_str (), (int)value).c_str ()
) )
); );
this->setTaskbarProgress ((unsigned)value); this->invokeSetTaskbarProgress ((unsigned)value);
} }
bool launchInstalledApp () bool launchInstalledApp ()
{ {

View File

@@ -323,7 +323,8 @@ std::vector <std::wstring> applicationItems =
L"DisplayName", L"DisplayName",
L"BackgroundColor", L"BackgroundColor",
L"ForegroundText", L"ForegroundText",
L"ShortName" L"ShortName",
L"Square44x44Logo"
}; };
typedef std::wstring strlabel, StringLabel; typedef std::wstring strlabel, StringLabel;
std::wstring StringTrim (const std::wstring &str) std::wstring StringTrim (const std::wstring &str)

View File

@@ -89,9 +89,40 @@ struct PackageInfomation
this->properties.description = reader.getPropertyDescription (); this->properties.description = reader.getPropertyDescription ();
this->properties.publisher = reader.getPropertyPublisher (); this->properties.publisher = reader.getPropertyPublisher ();
} }
this->properties.logoBase64 = GetLogoBase64FromReader (reader, &this->properties.logoStream); this->properties.logoBase64 = GetLogoBase64FromReader (reader, &this->properties.logoStream, &pri);
this->prerequisites.osMinVersion = reader.getPrerequisiteOSMinVersion (); this->prerequisites.osMinVersion = reader.getPrerequisiteOSMinVersion ();
reader.getApplications (this->applications); reader.getApplications (this->applications);
for (auto &it : this->applications)
{
for (auto &sit : it)
{
if (LabelEqual (sit.first, L"AppUserModelID")) continue;
else if (LabelEqual (sit.first, L"Id")) continue;
else if (LabelEqual (sit.first, L"DisplayName"))
{
if (isMsResourceLabel (sit.second))
{
std::wstring temp (L"");
temp += pri.findStringValue (sit.second);
it [L"DisplayName"] = temp;
}
}
else if (LabelEqual (sit.first, L"ShortName"))
{
if (isMsResourceLabel (sit.second))
{
std::wstring temp (L"");
temp += pri.findStringValue (sit.second);
it [L"ShortName"] = temp;
}
}
else if (LabelEqual (sit.first, L"Square44x44Logo"))
{
sit.second = pri.findFilePathValue (sit.second);
it [strlabel (L"Square44x44LogoBase64")] = GetBase64FromPathW (reader, sit.second.c_str (), NULL, &pri);
}
}
}
reader.getCapabilities (capabilities); reader.getCapabilities (capabilities);
reader.getDependencies (dependencies); reader.getDependencies (dependencies);
return reader.isAvailable (); return reader.isAvailable ();

View File

@@ -316,7 +316,7 @@ class PriReader
PriReader (): priReader (NULL) {} PriReader (): priReader (NULL) {}
void destroy () void destroy ()
{ {
if (!priReader) return; if (priReader == NULL) return;
DestroyPriReader (priReader); DestroyPriReader (priReader);
priReader = NULL; priReader = NULL;
} }

View File

@@ -3,10 +3,12 @@
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="Company.Product.Name" type="win32" /> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="Company.Product.Name" type="win32" />
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings> <windowsSettings>
<dpiAware xmlns= <!-- Windows 8 -->
"https://schemas.microsoft.com/SMI/2005/WindowsSettings"> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
True/PM <!-- Windows 8.1 -->
</dpiAware> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 / Windows 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</windowsSettings> </windowsSettings>
</application> </application>
<description></description> <description></description>

File diff suppressed because it is too large Load Diff

View File

@@ -316,7 +316,7 @@ class PriReader
PriReader (): priReader (NULL) {} PriReader (): priReader (NULL) {}
void destroy () void destroy ()
{ {
if (!priReader) return; if (priReader == NULL) return;
DestroyPriReader (priReader); DestroyPriReader (priReader);
priReader = NULL; priReader = NULL;
} }

View File

@@ -31,4 +31,33 @@ LPSTR StreamToBase64 (HISTREAM ifile)
if (!lpszStr) return NULL; if (!lpszStr) return NULL;
lstrcpyA (lpszStr, res.c_str ()); lstrcpyA (lpszStr, res.c_str ());
return lpszStr; return lpszStr;
} }
LPWSTR StreamToBase64W (HISTREAM ifile)
{
if (!ifile) return NULL;
IStream *pStream = (IStream *)ifile;
LARGE_INTEGER liZero = {};
pStream->Seek (liZero, STREAM_SEEK_SET, nullptr);
STATSTG statstg;
pStream->Stat (&statstg, STATFLAG_NONAME);
ULARGE_INTEGER uliSize = statstg.cbSize;
std::vector<BYTE> buffer (uliSize.QuadPart);
ULONG bytesRead;
pStream->Read (buffer.data (), static_cast<ULONG>(buffer.size ()), &bytesRead);
DWORD base64Size = 0;
if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &base64Size))
{
return NULL;
}
std::vector <WCHAR> base64Buffer (base64Size);
if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64Buffer.data (), &base64Size))
{
return NULL;
}
std::wstring res = std::wstring (base64Buffer.begin (), base64Buffer.end ());
LPWSTR lpszStr = (LPWSTR)calloc (res.capacity (), sizeof (WCHAR));
if (!lpszStr) return NULL;
lstrcpyW (lpszStr, res.c_str ());
return lpszStr;
}

View File

@@ -14,3 +14,5 @@ typedef HANDLE HISTREAM;
typedef char *LPSTR; typedef char *LPSTR;
extern "C" BASE64IMG_API LPSTR StreamToBase64 (HISTREAM ifile); extern "C" BASE64IMG_API LPSTR StreamToBase64 (HISTREAM ifile);
extern "C" BASE64IMG_API LPWSTR StreamToBase64W (HISTREAM ifile);

View File

@@ -1652,6 +1652,10 @@ class PriReader
if (xmlreader) delete xmlreader; if (xmlreader) delete xmlreader;
xmlreader = nullptr; xmlreader = nullptr;
if (IsFileExists (txmlpath)) DeleteFileW (txmlpath.c_str ()); if (IsFileExists (txmlpath)) DeleteFileW (txmlpath.c_str ());
if (IsFileExists (txmlpath.substr (0, txmlpath.length () - 4)))
{
DeleteFileW (txmlpath.substr (0, txmlpath.length () - 4).c_str ());
}
txmlpath = L""; txmlpath = L"";
prifile = L""; prifile = L"";
} }
@@ -1760,6 +1764,10 @@ class PriReader
} }
bool res = this->create (tempPriFile); bool res = this->create (tempPriFile);
DeleteFileW (tempPriFile.c_str ()); DeleteFileW (tempPriFile.c_str ());
if (IsFileExists (tempPriFile.substr (0, tempPriFile.length () - 4)))
{
DeleteFileW (tempPriFile.substr (0, tempPriFile.length () - 4).c_str ());
}
return res; return res;
} }
// 获取到的指针需要 free 手动释放。 // 获取到的指针需要 free 手动释放。
@@ -1905,7 +1913,7 @@ void DestroyPriReader (HPRIREADER hpr)
{ {
if (!hpr) return; if (!hpr) return;
PriReader *ptr = (PriReader *)hpr; PriReader *ptr = (PriReader *)hpr;
delete hpr; delete ptr;
return; return;
} }
// 返回的字符串只能肯定不是宽字符串,而不确定具体的编码方式(可能为 ANSI 也有可能为 UTF-8 // 返回的字符串只能肯定不是宽字符串,而不确定具体的编码方式(可能为 ANSI 也有可能为 UTF-8