Files
App-Installer-For-Windows-8…/appinstaller/main.cpp
冰糖XH 79674b639b Use external headers; remove local header links
Replace local header placeholders in appinstaller with direct references to upstream headers. Deleted the gitlink/header stubs (certmgr.h, notice.h, pkgmgr.h, pkgread.h, priformatcli.h) from appinstaller, updated main.cpp and appxinfo.h to include the ../path to those headers, and adjusted appinstaller.vcxproj.filters to point to the new locations. Cleans up redundant local links and ensures the project references the original header files.
2026-03-26 22:01:12 +08:00

1947 lines
62 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <Windows.h>
#include <msclr/marshal_cppstd.h>
#include <ShObjIdl.h>
#include <ShlObj.h> // KNOWNFOLDERID, SHGetKnownFolderPath
#include <commdlg.h> // OPENFILENAME
#include <comdef.h> // _com_error
#include <MsHTML.h>
#include <ExDisp.h>
#include <atlbase.h>
#include <fstream>
#include <comdef.h>
#include <vcclr.h>
#include "cmdargs.h"
#include "themeinfo.h"
#include "mpstr.h"
#include "initfile.h"
#include "resource.h"
#include "vemani.h"
#include "ieshell.h"
#include "resmap.h"
#include "appxinfo.h"
#include "localeex.h"
#include "../pkgmgr/pkgmgr.h"
#include "../notice/notice.h"
#include "../certmgr/certmgr.h"
#include "bridge.h"
#include "filepath.h"
using namespace System;
using namespace System::Runtime::InteropServices;
#ifdef _DEBUG
#define DEBUGMODE true
#else
#define DEBUGMODE false
#endif
#define JS_SAFE [MarshalAs (UnmanagedType::SafeArray, SafeArraySubType = VarEnum::VT_VARIANT)]
enum class CMDPARAM: DWORD
{
NONE = 0b000,
SILENT = 0b001,
VERYSILENT = 0b011,
MULTIPLE = 0b100
};
LPCWSTR g_lpAppId = L"Microsoft.DesktopAppInstaller!App";
auto &g_identity = g_lpAppId;
auto &m_idenName = g_lpAppId;
struct iconhandle
{
HICON hIcon = nullptr;
iconhandle (HICON hIcon = nullptr): hIcon (hIcon) {}
~iconhandle () { try { if (hIcon) DestroyIcon (hIcon); hIcon = nullptr; } catch (...) {} }
};
iconhandle g_hIconMain (LoadRCIcon (IDI_ICON_MAIN));
initfile g_initfile (CombinePath (GetProgramRootDirectoryW (), L"config.ini"));
ref class MainHtmlWnd;
msclr::gcroot <MainHtmlWnd ^> g_mainwnd;
vemanifest g_vemani (
IsFileExists (CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml")) ?
CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml") :
CombinePath (GetProgramRootDirectoryW (), L"AppInstaller.VisualElementsManifest.xml")
);
resxmldoc g_scaleres (
IsFileExists (CombinePath (GetProgramRootDirectoryW (), L"VisualElements\\scale.xml")) ?
CombinePath (GetProgramRootDirectoryW (), L"VisualElements\\scale.xml") :
CombinePath (GetProgramRootDirectoryW (), L"VisualElementsManifest.xml")
);
WORD g_wcmdflags = 0;
std::vector <std::wnstring> g_pkgfiles;
std::vector <pkginfo> g_pkginfo;
std::wstring g_lastfile;
struct package_installresult
{
HRESULT result = S_OK;
std::wstring error;
std::wstring reason;
bool succeeded () const { return SUCCEEDED (result); }
bool failed () const { return FAILED (result); }
package_installresult (HRESULT result, const std::wstring &err, const std::wstring &msg): result (result), reason (msg), error (err) {}
package_installresult (HRESULT result, const std::wstring &msg): result (result), reason (msg) {}
package_installresult () = default;
};
std::map <std::wnstring, package_installresult> g_pkgresult;
HRESULT GetWebBrowser2Interface (System::Windows::Forms::WebBrowser ^fwb, IWebBrowser2 **output)
{
if (fwb == nullptr || output == nullptr) return E_INVALIDARG;
*output = nullptr;
Object ^activeX = fwb->ActiveXInstance;
if (activeX == nullptr) return E_FAIL;
IntPtr pUnk = Marshal::GetIUnknownForObject (activeX);
if (pUnk == IntPtr::Zero) return E_FAIL;
HRESULT hr = ((IUnknown *)pUnk.ToPointer ())->QueryInterface (IID_IWebBrowser2, (void **)output);
Marshal::Release (pUnk);
return hr;
}
[ComVisible (true)]
public ref class _I_InitConfig
{
public:
Win32::InitConfig ^Create (String ^filepath) { return gcnew Win32::InitConfig (filepath); }
Win32::InitConfig ^GetConfig () { return Create (CStringToMPString (g_initfile.filepath)); }
};
[ComVisible (true)]
public ref class _I_Package
{
public:
ref class _I_Package_Manager
{
public:
_I_Package_Manager () {}
};
private:
_I_Package_Manager ^mgr = gcnew _I_Package_Manager ();
public:
String ^GetPackagesToJson ()
{
rapidjson::Document doc;
doc.SetArray ();
auto &alloc = doc.GetAllocator ();
for (auto &it : g_pkginfo)
{
rapidjson::Value member (rapidjson::kStringType);
member.SetString (ws2utf8 (it.filepath).c_str (), alloc);
doc.PushBack (member, alloc);
}
rapidjson::StringBuffer buffer;
rapidjson::Writer <rapidjson::StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return CStringToMPString (conv.from_bytes (utf8));
}
String ^GetPackageInfoToJson (String ^filepath)
{
std::wstring fpath = MPStringToStdW (filepath);
for (auto &it : g_pkginfo)
{
if (PathEquals (it.filepath, fpath))
{
return CStringToMPString (it.parseJson ());
}
}
return "{}";
}
property _I_Package_Manager ^Manager { _I_Package_Manager ^get () { return mgr; }}
String ^GetCapabilityDisplayName (String ^capabilityName)
{
return CStringToMPString (GetPackageCapabilityDisplayName (MPStringToStdW (capabilityName)));
}
_I_HResult ^GetPackageInstallResult (String ^filepath)
{
std::wstring path = MPStringToStdW (filepath);
if (g_pkgresult.find (path) == g_pkgresult.end ()) return nullptr;
auto &pres = g_pkgresult.at (path);
return gcnew _I_HResult (
pres.result,
CStringToMPString (pres.error),
CStringToMPString (pres.reason)
);
}
_I_HResult ^Activate (String ^appid)
{
DWORD dwProgressId = 0;
HRESULT hr = ActivateAppxApplication (MPStringToStdW (appid ? appid : "").c_str (), &dwProgressId);
return gcnew _I_HResult (hr);
}
};
[ComVisible (true)]
public ref class _I_Bridge_Base
{
protected:
_I_String ^str = gcnew _I_String ();
_I_InitConfig ^initconfig = gcnew _I_InitConfig ();
_I_Storage ^storage = gcnew _I_Storage ();
_I_Package ^pkg = gcnew _I_Package ();
public:
property _I_String ^String { _I_String ^get () { return str; }}
property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }}
property _I_Storage ^Storage { _I_Storage ^get () { return storage; }}
property _I_Package ^Package { _I_Package ^get () { return pkg; }}
};
[ComVisible (true)]
public interface class IScriptBridge
{
public:
virtual Object ^CallEvent (String ^funcName, Object ^e) = 0;
};
[ComVisible (true)]
public ref class _I_Window
{
private:
IScriptBridge ^wndinst = nullptr;
public:
_I_Window (IScriptBridge ^wnd): wndinst (wnd) {}
Object ^CallEvent (String ^name, ... array <Object ^> ^args) { return wndinst->CallEvent (name, args [0]); }
};
[ComVisible (true)]
public ref class _I_UI
{
private:
System::Windows::Forms::Form ^wndinst = nullptr;
public:
ref struct _I_UI_Size
{
private:
int m_width = 0;
int m_height = 0;
public:
property int width { int get () { return m_width; } }
property int height { int get () { return m_height; }}
property int Width { int get () { return m_width; } }
property int Height { int get () { return m_height; }}
int getWidth () { return m_width; }
int getHeight () { return m_height; }
_I_UI_Size (int w, int h): m_width (w), m_height (h) {}
};
_I_UI (System::Windows::Forms::Form ^wnd): wndinst (wnd) {}
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
property _I_UI_Size ^WndSize { _I_UI_Size ^get () { return gcnew _I_UI_Size (wndinst->Width, wndinst->Height); } }
property _I_UI_Size ^ClientSize { _I_UI_Size ^get () { auto cs = wndinst->ClientSize; return gcnew _I_UI_Size (cs.Width, cs.Height); } }
property String ^ThemeColor { String ^get () { return ColorToHtml (GetDwmThemeColor ()); } }
property bool DarkMode { bool get () { return IsAppInDarkMode (); }}
property String ^HighContrast
{
String ^get ()
{
auto highc = GetHighContrastTheme ();
switch (highc)
{
case HighContrastTheme::None: return "none";
break;
case HighContrastTheme::Black: return "black";
break;
case HighContrastTheme::White: return "white";
break;
case HighContrastTheme::Other: return "high";
break;
default: return "none";
break;
}
return "none";
}
}
};
[ComVisible (true)]
public ref class _I_Locale
{
public:
property String ^CurrentLocale { String ^get () { return CStringToMPString (GetComputerLocaleCodeW ()); } }
property LCID CurrentLCID { LCID get () { return LocaleCodeToLcid (GetComputerLocaleCodeW ()); } }
String ^ToLocaleName (LCID lcid) { return CStringToMPString (LcidToLocaleCodeW (lcid)); }
LCID ToLCID (String ^localename) { return LocaleCodeToLcidW (MPStringToStdW (localename)); }
Object ^LocaleInfo (LCID lcid, LCTYPE lctype) { return CStringToMPString (GetLocaleInfoW (lcid, lctype)); }
Object ^LocaleInfoEx (String ^localeName, LCTYPE lctype)
{
std::wstring output = L"";
int ret = GetLocaleInfoEx (MPStringToStdW (localeName), lctype, output);
if (output.empty ()) return ret;
else return CStringToMPString (output);
}
};
[ComVisible (true)]
public ref class _I_System
{
private:
_I_Resources ^ires = gcnew _I_Resources ();
_I_Locale ^ilocale = gcnew _I_Locale ();
public:
property _I_Resources ^Resources { _I_Resources ^get () { return ires; } }
property _I_Locale ^Locale { _I_Locale ^get () { return ilocale; } }
property bool IsWindows10
{
bool get ()
{
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;
}
}
property int Archievement
{
int get ()
{
SYSTEM_INFO si;
ZeroMemory (&si, sizeof (si));
typedef VOID (WINAPI *LPFN_GetNativeSystemInfo)(LPSYSTEM_INFO);
LPFN_GetNativeSystemInfo fnGetNativeSystemInfo =
(LPFN_GetNativeSystemInfo)GetProcAddress (
GetModuleHandleW (L"kernel32.dll"),
"GetNativeSystemInfo");
if (fnGetNativeSystemInfo) fnGetNativeSystemInfo (&si);
else GetSystemInfo (&si);
return (int)si.wProcessorArchitecture;
}
}
property _I_Version ^Version
{
_I_Version ^get ()
{
auto ver = Environment::OSVersion->Version;
try
{
return gcnew _I_Version (ver->Major, ver->Minor, ver->Build, ver->Revision);
}
catch (...)
{
return gcnew _I_Version (ver->Major, ver->Minor, ver->Build, 0);
}
}
}
};
public ref class _I_System2: public _I_System
{
protected:
_I_UI ^ui;
public:
_I_System2 (System::Windows::Forms::Form ^wnd)
{
ui = gcnew _I_UI (wnd);
}
property _I_UI ^UI { _I_UI ^get () { return ui; } }
};
[ComVisible (true)]
public ref class _I_Bridge_Base2: public _I_Bridge_Base
{
protected:
_I_Window ^window;
public:
_I_Bridge_Base2 (IScriptBridge ^iscr)
{
window = gcnew _I_Window (iscr);
}
property _I_Window ^Window { _I_Window ^get () { return window; }}
};
[ComVisible (true)]
public ref class _I_Bridge_Base3: public _I_Bridge_Base2
{
protected:
_I_System2 ^system;
public:
_I_Bridge_Base3 (IScriptBridge ^iscr, System::Windows::Forms::Form ^form): _I_Bridge_Base2 (iscr)
{
system = gcnew _I_System2 (form);
}
property _I_System2 ^System { _I_System2 ^get () { return system; }}
};
[ComVisible (true)]
public ref class _I_IEFrame_Base
{
public:
property int Version { int get () { return GetInternetExplorerVersionMajor (); }}
String ^ParseHtmlColor (String ^color)
{
auto dcolor = Drawing::ColorTranslator::FromHtml (color);
{
rapidjson::Document doc;
doc.SetObject ();
auto &alloc = doc.GetAllocator ();
doc.AddMember ("r", (uint16_t)dcolor.R, alloc);
doc.AddMember ("g", (uint16_t)dcolor.G, alloc);
doc.AddMember ("b", (uint16_t)dcolor.B, alloc);
doc.AddMember ("a", (uint16_t)dcolor.A, alloc);
rapidjson::StringBuffer buffer;
rapidjson::Writer <rapidjson::StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return CStringToMPString (conv.from_bytes (utf8));
}
return "{}";
}
};
[ComVisible (true)]
public ref class SplashForm: public System::Windows::Forms::Form
{
public:
using PictureBox = System::Windows::Forms::PictureBox;
using Timer = System::Windows::Forms::Timer;
private:
PictureBox ^picbox;
Timer ^timer;
System::Drawing::Image ^splashimg = nullptr;
System::Drawing::Color background = System::Drawing::Color::Transparent;
// System::Windows::Forms ^parent = nullptr;
double opastep = 0.05;
void InitForm ()
{
this->DoubleBuffered = true;
InitializeComponent ();
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->StartPosition = System::Windows::Forms::FormStartPosition::Manual;
this->ShowInTaskbar = false;
this->AllowTransparency = true;
this->Opacity = 1.0;
}
void InitializeComponent ()
{
double dDpi = GetDPI () * 0.01;
this->picbox = gcnew System::Windows::Forms::PictureBox ();
this->picbox->Size = System::Drawing::Size (620 * dDpi, 300 * dDpi);
this->picbox->BackColor = System::Drawing::Color::Transparent;
picbox->Anchor = System::Windows::Forms::AnchorStyles::None;
picbox->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
}
void OnFadeTimer (Object ^sender, EventArgs ^e)
{
auto fadeTimer = timer;
auto opacityStep = opastep;
if (this->Opacity > 0)
{
this->Opacity -= opacityStep;
}
else
{
fadeTimer->Stop ();
this->Close ();
}
}
void OnLoad (Object ^sender, EventArgs ^e)
{
this->ChangePosAndSize ();
this->Visible = true;
}
void OnResize (Object ^sender, EventArgs ^e)
{
if (IsHandleCreated && picbox->IsHandleCreated)
{
Drawing::Size sz = this->ClientSize;
this->picbox->Location = Drawing::Point (
(sz.Width - picbox->Width) * 0.5,
(sz.Height - picbox->Height) * 0.5
);
}
}
void OnResizeOwner (Object ^sender, EventArgs ^e) { this->ChangePosAndSize (); }
void OnLocationChangedOwner (Object ^sender, EventArgs ^e) { this->ChangePosAndSize (); }
protected:
virtual void OnHandleCreated (EventArgs^ e) override
{
Form::OnHandleCreated (e);
if (Environment::OSVersion->Version->Major >= 6)
{
INT mr = 0;
MARGINS margins = {mr, mr, mr, mr};
HRESULT hr = DwmExtendFrameIntoClientArea ((HWND)this->Handle.ToPointer (), &margins);
}
}
public:
SplashForm (System::String ^imgpath, System::Drawing::Color backcolor, System::Windows::Forms::Form ^owner)
{
if (owner != nullptr) this->Owner = owner;
InitForm ();
std::wstring filefullpath = MPStringToStdW (imgpath);
if (filefullpath.find (L'%') != filefullpath.npos) filefullpath = ProcessEnvVars (filefullpath);
filefullpath = GetFullPathName (imgpath ? MPStringToStdW (imgpath) : L"");
try
{
auto img = System::Drawing::Image::FromFile (gcnew System::String (filefullpath.c_str ()));
if (img != nullptr)
{
splashimg = img;
picbox->Image = img;
}
}
catch (...) {}
if (splashimg) picbox->Image = splashimg;
try
{
if (backcolor != Drawing::Color::Transparent)
{
background = backcolor;
picbox->BackColor = backcolor;
this->BackColor = backcolor;
}
else
{
picbox->BackColor = background;
this->BackColor = background;
}
}
catch (...) {}
if (this->Owner != nullptr)
{
this->Owner->Resize += gcnew System::EventHandler (this, &SplashForm::OnResizeOwner);
this->Owner->LocationChanged += gcnew System::EventHandler (this, &SplashForm::OnLocationChangedOwner);
}
this->Controls->Add (picbox);
this->Resize += gcnew EventHandler (this, &SplashForm::OnResize);
timer = gcnew System::Windows::Forms::Timer ();
timer->Interval = 15;
timer->Tick += gcnew System::EventHandler (this, &SplashForm::OnFadeTimer);
this->Load += gcnew EventHandler (this, &SplashForm::OnLoad);
}
void ReInit ()
{
InitForm ();
picbox = gcnew System::Windows::Forms::PictureBox ();
picbox->BackColor = background;
if (splashimg) picbox->Image = splashimg;
picbox->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
picbox->Anchor = System::Windows::Forms::AnchorStyles::None;
double dDpi = GetDPI () * 0.01;
picbox->Size = Drawing::Size (620 * dDpi, 300 * dDpi);
this->BackColor = background;
this->Controls->Clear ();
this->Controls->Add (picbox);
timer = gcnew System::Windows::Forms::Timer ();
timer->Interval = 15;
timer->Tick += gcnew EventHandler (this, &SplashForm::OnFadeTimer);
this->Resize += gcnew EventHandler (this, &SplashForm::OnResize);
this->Load += gcnew EventHandler (this, &SplashForm::OnLoad);
ChangePosAndSize ();
this->Opacity = 1.0;
}
void ChangePosAndSize ()
{
if (this->Owner && this->Owner->IsHandleCreated)
{
this->Owner->Update ();
System::Drawing::Point pt = this->Owner->PointToScreen (this->Owner->ClientRectangle.Location);
this->Location = pt;
this->Size = this->Owner->ClientSize;
}
else if (this->Parent && this->Parent->IsHandleCreated)
{
this->Parent->Update ();
System::Drawing::Point pt = this->Parent->PointToScreen (this->Parent->ClientRectangle.Location);
this->Location = pt;
this->Size = this->Parent->ClientSize;
}
if (IsHandleCreated && picbox->IsHandleCreated)
{
Drawing::Size sz = this->ClientSize;
this->picbox->Location = Drawing::Point (
(sz.Width - picbox->Width) * 0.5,
(sz.Height - picbox->Height) * 0.5
);
}
}
void SetSplashImage (System::Drawing::Image ^img) { if (picbox && picbox->IsHandleCreated) { splashimg = img; picbox->Image = splashimg; } else splashimg = img; }
void SetSplashImage (System::String ^imgpath) { try { SetSplashImage (System::Drawing::Image::FromFile (imgpath)); } catch (...) {} }
void SetSplashImage (const std::wstring &imgpath) { SetSplashImage (CStringToMPString (imgpath)); }
void SetSplashBackgroundColor (System::Drawing::Color color) { background = color; picbox->BackColor = color; this->BackColor = color; }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ
void FadeOut () { timer->Start (); }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ
void FadeAway () { timer->Start (); }
~SplashForm ()
{
if (this->Owner != nullptr)
{
this->Owner->Resize -= gcnew System::EventHandler (this, &SplashForm::OnResizeOwner);
this->Owner->LocationChanged -= gcnew System::EventHandler (this, &SplashForm::OnLocationChangedOwner);
}
}
};
enum class InstallType
{
normal,
update,
reinstall
};
inline std::wstring ToStdWString (const std::wstring &str) { return str; }
size_t ExploreFile (HWND hParent, std::vector <std::wstring> &results, LPWSTR lpFilter = L"Windows Store App Package (*.appx; *.appxbundle)\0*.appx;*.appxbundle", DWORD dwFlags = OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST, const std::wstring &swWndTitle = std::wstring (L"Please select the file(-s): "), const std::wstring &swInitDir = GetFileDirectoryW (g_lastfile))
{
results.clear ();
const DWORD BUFFER_SIZE = 65536; // 64KB
std::vector <WCHAR> buffer (BUFFER_SIZE, 0);
OPENFILENAME ofn;
ZeroMemory (&ofn, sizeof (ofn));
ofn.hwndOwner = hParent;
ofn.lpstrFile = (LPWSTR)buffer.data ();
ofn.nMaxFile = BUFFER_SIZE;
ofn.lpstrFilter = lpFilter;
ofn.nFilterIndex = 1;
ofn.lpstrTitle = swWndTitle.c_str ();
ofn.Flags = dwFlags;
ofn.lpstrInitialDir = swInitDir.c_str ();
ofn.lStructSize = sizeof (ofn);
if (GetOpenFileNameW (&ofn))
{
LPCWSTR p = buffer.data ();
std::wstring dir = p;
p += dir.length () + 1;
if (*p == 0) results.push_back (dir);
else
{
while (*p)
{
std::wstring fullPath = dir + L"\\" + p;
results.push_back (fullPath);
p += wcslen (p) + 1;
}
}
if (!results.empty ()) g_lastfile = results.back ();
}
return results.size ();
}
public delegate void InstallProgressCallbackDelegate (DWORD progress);
#pragma managed(push, off)
void NativeProgressCallback (DWORD progress, void* context)
{
(void)progress;
(void)context;
}
#pragma managed(pop)
static void ManagedThunk (DWORD progress, void *context)
{
if (context == nullptr) return;
GCHandle handle = GCHandle::FromIntPtr (IntPtr (context));
auto cb = (InstallProgressCallbackDelegate ^)handle.Target;
if (cb != nullptr) cb (progress);
}
HRESULT AddAppxPackageFromPath (
const std::wstring &pkgpath,
const std::vector <std::wstring> &deplist,
DWORD deployoption,
InstallProgressCallbackDelegate ^callback,
std::wstring &errorcode,
std::wstring &detailmsg
)
{
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = (DWORD)deplist.size ();
for (size_t i = 0; i < deplist.size (); ++i)
lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
GCHandle handle;
void *ctx = nullptr;
PKGMRR_PROGRESSCALLBACK pfnCallback = nullptr;
if (callback != nullptr)
{
handle = GCHandle::Alloc (callback);
ctx = (void *)GCHandle::ToIntPtr (handle).ToPointer ();
pfnCallback = (PKGMRR_PROGRESSCALLBACK)&ManagedThunk; // <20><><EFBFBD>й<EFBFBD> thunk <20><> native
}
LPWSTR lperr = nullptr, lpmsg = nullptr;
destruct relt ([&] () {
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
lperr = nullptr;
lpmsg = nullptr;
});
HRESULT hr = AddAppxPackageFromPath (
pkgpath.c_str (),
lpdeplist,
deployoption,
pfnCallback,
ctx,
&lperr,
&lpmsg
);
if (callback != nullptr && handle.IsAllocated) handle.Free ();
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
return hr;
}
HRESULT UpdateAppxPackageFromPath (
const std::wstring &pkgpath,
const std::vector <std::wstring> &deplist,
DWORD deployoption,
InstallProgressCallbackDelegate ^callback,
std::wstring &errorcode,
std::wstring &detailmsg
)
{
std::vector <BYTE> bytes (sizeof (REGISTER_PACKAGE_DEFENDENCIES) + sizeof (LPWSTR) * deplist.size ());
auto lpdeplist = (PREGISTER_PACKAGE_DEFENDENCIES)bytes.data ();
lpdeplist->dwSize = (DWORD)deplist.size ();
for (size_t i = 0; i < deplist.size (); ++i)
lpdeplist->alpDepUris [i] = (LPWSTR)deplist [i].c_str ();
GCHandle handle;
void *ctx = nullptr;
PKGMRR_PROGRESSCALLBACK pfnCallback = nullptr;
if (callback != nullptr)
{
handle = GCHandle::Alloc (callback);
ctx = (void *)GCHandle::ToIntPtr (handle).ToPointer ();
pfnCallback = (PKGMRR_PROGRESSCALLBACK)&ManagedThunk; // <20><><EFBFBD>й<EFBFBD> thunk <20><> native
}
LPWSTR lperr = nullptr, lpmsg = nullptr;
destruct relt ([&] () {
if (lperr) PackageManagerFreeString (lperr);
if (lpmsg) PackageManagerFreeString (lpmsg);
lperr = nullptr;
lpmsg = nullptr;
});
HRESULT hr = UpdateAppxPackageFromPath (
pkgpath.c_str (),
lpdeplist,
deployoption,
pfnCallback,
ctx,
&lperr,
&lpmsg
);
if (callback != nullptr && handle.IsAllocated) handle.Free ();
errorcode = lperr ? lperr : L"";
detailmsg = lpmsg ? lpmsg : L"";
return hr;
}
bool IsWindows10 ()
{
#pragma warning(push)
#pragma warning(disable:4996)
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;
#pragma warning(pop)
}
void ActivateApp (Object ^appid)
{
auto res = ActivateAppxApplication (MPStringToStdW (appid->ToString ()));
}
[ComVisible (true)]
public ref class AppListWnd: public System::Windows::Forms::Form, public IScriptBridge
{
public:
using WebBrowser = System::Windows::Forms::WebBrowser;
using Timer = System::Windows::Forms::Timer;
[ComVisible (true)]
ref class IBridge: public _I_Bridge_Base3
{
private:
AppListWnd ^wndinst = nullptr;
public:
IBridge (AppListWnd ^wnd): wndinst (wnd), _I_Bridge_Base3 (wnd, wnd) {}
ref class _I_IEFrame: public _I_IEFrame_Base
{
private:
AppListWnd ^wndinst = nullptr;
public:
_I_IEFrame (AppListWnd ^wnd): wndinst (wnd) {}
property int Scale
{
int get () { return wndinst->PageScale; }
void set (int value) { return wndinst->PageScale = value; }
}
};
private:
_I_IEFrame ^ieframe = gcnew _I_IEFrame (wndinst);
public:
property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }}
};
private:
WebBrowser ^webui = nullptr;
Timer ^showtimer = gcnew Timer ();
Timer ^hidetimer = gcnew Timer ();
int aminedelay = 150;
int framedelay = 25;
double movelen = 10 * DPI;
int frametotal = aminedelay / framedelay;
double movestep = movelen / (double)frametotal;
int framenow = 0;
int finaltop = 0;
public:
property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } }
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
AppListWnd ()
{
this->Visible = false;
this->DoubleBuffered = true;
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->ShowInTaskbar = false;
this->TopMost = true;
this->Size = System::Drawing::Size (392 * DPI, 494 * DPI);
if (IsWindows10 ()) this->MinimumSize = System::Drawing::Size (392 * DPI, 226 * DPI);
else this->MinimumSize = System::Drawing::Size (392 * DPI, 129 * DPI);
if (IsWindows10 ()) this->MaximumSize = System::Drawing::Size (392 * DPI, 522 * DPI);
else this->MaximumSize = System::Drawing::Size (368 * DPI, 394 * DPI);
this->Text = GetRCStringCli (IDS_APPLIST_WINTITLE);
webui = gcnew System::Windows::Forms::WebBrowser ();
webui->Dock = System::Windows::Forms::DockStyle::Fill;
this->Controls->Add (webui);
webui->Visible = false;
webui->ObjectForScripting = gcnew IBridge (this);
this->webui->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler (this, &AppListWnd::OnDocumentCompleted);
this->Load += gcnew EventHandler (this, &AppListWnd::OnCreate);
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Deactivate += gcnew EventHandler (this, &AppListWnd::OnDeactivate);
webui->Navigate (CStringToMPString (CombinePath (GetProgramRootDirectoryW (), L"html\\applist.html")));
showtimer->Interval = framedelay;
hidetimer->Interval = framedelay;
showtimer->Tick += gcnew EventHandler (this, &AppListWnd::OnTick_ShowTimer);
hidetimer->Tick += gcnew EventHandler (this, &AppListWnd::OnTick_HideTimer);
this->Opacity = 0;
}
protected:
void OnCreate (System::Object ^sender, System::EventArgs ^e) {}
void OnDocumentCompleted (Object ^sender, System::Windows::Forms::WebBrowserDocumentCompletedEventArgs ^e)
{
if (e->Url->ToString () == webui->Url->ToString ())
{
ExecScript ("Windows.UI.DPI.mode = 1");
ExecScript ("Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
InvokeCallScriptFunction ("setWindows10Style", IsWindows10 ());
size_t cnt = 0;
for (auto &it : g_pkginfo)
{
for (auto &app : it.applications)
{
std::wstring launchid = it.identity.package_family_name + L'!' + app [L"Id"];
std::wnstring color = app [L"BackgroundColor"];
if (color.empty () || color.equals (L"transparent")) color = MPStringToStdW (ColorToHtml (GetDwmThemeColor ()));
std::wnstring displayName = app [L"DisplayName"];
if (displayName.empty ()) displayName = app [L"ShortName"];
auto logo = app [L"Square44x44Logo"];
if (std::wnstring::empty (logo)) logo = app [L"SmallLogo"];
InvokeCallScriptFunction (
"addAppToList",
CStringToMPString (displayName),
CStringToMPString (logo),
CStringToMPString (launchid),
CStringToMPString (color)
);
cnt ++;
}
}
if (cnt == 0) this->Close ();
{
bool isWin10 = IsWindows10 ();
size_t height = ((cnt) * (isWin10 ? 50 : 60) * DPI) + (isWin10 ? 206 : 120) * DPI;
if (height < (isWin10 ? 522 : 394) * DPI) this->Height = height;
else this->Height = 522 * DPI;
this->Left = (GetScreenWidth () - this->Width) / 2;
this->Top = (GetScreenHeight () - this->Height) / 2;
}
finaltop = this->Top;
this->Top -= movelen;
webui->Visible = true;
this->Visible = true;
}
}
void OnPress_Cancel ()
{
if (!this->IsHandleCreated) return;
if (InvokeRequired) this->Invoke (gcnew Action (this, &AppListWnd::HideAmine));
else this->HideAmine ();
return;
}
void OnPress_AppItem ()
{
// OnPress_Cancel ();
if (!this->IsHandleCreated) return;
if (InvokeRequired) this->Invoke (gcnew Action (this, &AppListWnd::Close));
else this->Close ();
return;
}
void OnDeactivate (Object ^sender, EventArgs ^e)
{
OnPress_Cancel ();
}
void OnTick_ShowTimer (Object ^sender, EventArgs ^e)
{
framenow ++;
if (framenow > frametotal)
{
showtimer->Stop ();
this->Top = finaltop;
this->Opacity = 1;
}
else
{
this->Top = finaltop + movestep * (frametotal - framenow);
this->Opacity = framenow / (double)frametotal;
}
}
void OnTick_HideTimer (Object ^sender, EventArgs ^e)
{
framenow ++;
if (framenow > frametotal)
{
showtimer->Stop ();
this->Opacity = 0;
this->Close ();
}
else
{
this->Opacity = 1.0 - framenow / (double)frametotal;
}
}
public:
static void DisplayWindow ()
{
auto wnd = gcnew AppListWnd ();
wnd->ShowAmine ();
}
Object ^CallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try { return this->webui->Document->InvokeScript (lpFuncName, alpParams); }
catch (Exception ^e) {}
return nullptr;
}
Object ^CallScriptFunction (String ^lpScriptName)
{
try { return this->webui->Document->InvokeScript (lpScriptName); }
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, array <Object ^> ^, Object ^> (this, &AppListWnd::CallScriptFunction), lpFuncName, alpParams);
else return CallScriptFunction (lpFuncName, alpParams);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpScriptName)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, Object ^> (this, &AppListWnd::CallScriptFunction), lpScriptName);
else return CallScriptFunction (lpScriptName);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^ExecScript (... array <Object ^> ^alpScript) { return InvokeCallScriptFunction ("eval", alpScript); }
Object ^CallEvent (String ^funcName, Object ^e) override
{
std::wstring fname = MPStringToStdW (funcName);
if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_CancelButton")) OnPress_Cancel ();
else if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_AppItem")) OnPress_AppItem ();
return nullptr;
}
property int PageScale
{
int get ()
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return 0;
VARIANT v;
VariantInit (&v);
hr = web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, nullptr, &v);
if (FAILED (hr) || v.vt != VT_I4) return 0;
int val = v.lVal;
VariantClear (&v);
return val;
}
void set (int value)
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return;
VARIANT v;
VariantInit (&v);
v.vt = VT_I4;
v.lVal = value;
web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &v, nullptr);
}
}
void ShowAmine ()
{
this->Show ();
hidetimer->Stop ();
showtimer->Start ();
}
void HideAmine ()
{
framenow = 0;
showtimer->Stop ();
hidetimer->Start ();
}
};
[ComVisible (true)]
public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScriptBridge
{
public:
using WebBrowser = System::Windows::Forms::WebBrowser;
private:
WebBrowser ^webui;
SplashForm ^splash;
String ^pagetag = "splash";
InstallType insmode = InstallType::normal;
size_t nowinstall = 0;
ITaskbarList3 *taskbar = nullptr;
public:
[ComVisible (true)]
ref class _I_UI2: public _I_UI
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
_I_UI2 (MainHtmlWnd ^wnd): wndinst (wnd), _I_UI (wnd) {}
property String ^SplashImage
{
String ^get ()
{
auto uri = gcnew Uri (CStringToMPString (wndinst->GetSuitSplashImage ()));
return uri->AbsoluteUri;
}
}
property String ^SplashBackgroundColor
{
String ^get ()
{
std::wnstring ret = L"";
auto personal = g_initfile [L"Personalization"];
auto thememode = personal [L"AppInstaller:ThemeMode"];
auto custommode = personal [L"AppInstaller:CustomThemeMode"];
bool nowdark =
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"dark") ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"auto") && IsAppInDarkMode () ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"custom") && IsNormalizeStringEquals (custommode.read_wstring ().c_str (), L"dark") ||
IsNormalizeStringEquals (thememode.read_wstring ().c_str (), L"custom") && IsNormalizeStringEquals (custommode.read_wstring ().c_str (), L"auto") && IsAppInDarkMode ();
if (nowdark) ret = g_vemani.splash_screen_backgroundcolor_darkmode (L"App");
else ret = g_vemani.splash_screen_backgroundcolor (L"App");
if (ret.empty ()) ret = g_vemani.splash_screen_backgroundcolor (L"App");
if (ret.empty ()) ret = g_vemani.background_color (L"App");
return CStringToMPString (ret);
}
}
void ShowSplash () { if (wndinst->SplashScreen->IsHandleCreated) wndinst->SplashScreen->Show (); else wndinst->SplashScreen->ReInit (); }
void FadeAwaySplash () { wndinst->SplashScreen->FadeAway (); }
void FadeOutSplash () { wndinst->SplashScreen->FadeOut (); }
};
[ComVisible (true)]
ref class IBridge: public _I_Bridge_Base2
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
[ComVisible (true)]
ref class _I_IEFrame: public _I_IEFrame_Base
{
private:
MainHtmlWnd ^wndinst = nullptr;
public:
_I_IEFrame (MainHtmlWnd ^wnd): wndinst (wnd) {}
property int Scale
{
int get () { return wndinst->PageScale; }
void set (int value) { return wndinst->PageScale = value; }
}
};
[ComVisible (true)]
ref class _I_System3: public _I_System
{
protected:
_I_UI2 ^ui2;
public:
_I_System3 (MainHtmlWnd ^wnd)
{
ui2 = gcnew _I_UI2 (wnd);
}
property _I_UI2 ^UI { _I_UI2 ^get () { return ui2; } }
};
private:
_I_IEFrame ^ieframe;
_I_System3 ^sys;
public:
IBridge (MainHtmlWnd ^wnd): wndinst (wnd), _I_Bridge_Base2 (wnd)
{
ieframe = gcnew _I_IEFrame (wnd);
sys = gcnew _I_System3 (wnd);
}
property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }}
property _I_System3 ^System { _I_System3 ^get () { return sys; }}
};
protected:
property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } }
property SplashForm ^SplashScreen { SplashForm ^get () { return this->splash; } }
property int DPIPercent { int get () { return GetDPI (); }}
property double DPI { double get () { return DPIPercent * 0.01; }}
property String ^PageTag { String ^get () { return GetPage (); } void set (String ^tag) { SetPage (tag); }}
void InitSize ()
{
unsigned ww = 0, wh = 0;
auto &ini = g_initfile;
auto setsect = ini ["Settings"];
auto savepos = setsect [L"AppInstaller:SavePosAndSizeBeforeCancel"];
auto lastw = setsect [L"AppInstaller:LastWidth"];
auto lasth = setsect [L"AppInstaller:LastHeight"];
auto defw = setsect [L"AppInstaller:DefaultWidth"];
auto defh = setsect [L"AppInstaller:DefaultHeight"];
auto minw = setsect [L"AppInstaller:MinimumWidth"];
auto minh = setsect [L"AppInstaller:MinimumHeight"];
auto lasts = setsect [L"AppInstaller:LastWndState"];
if (savepos.read_bool ())
{
ww = lastw.read_uint (defw.read_uint (rcInt (IDS_DEFAULTWIDTH)));
wh = lasth.read_uint (defh.read_uint (rcInt (IDS_DEFAULTHEIGHT)));
}
else
{
ww = defw.read_uint (rcInt (IDS_DEFAULTWIDTH));
wh = defh.read_uint (rcInt (IDS_DEFAULTHEIGHT));
}
this->ClientSize = System::Drawing::Size (ww * DPI, wh * DPI);
int hborder = this->Size.Width - this->ClientSize.Width,
vborder = this->Size.Height - this->ClientSize.Height;
this->MinimumSize = System::Drawing::Size (
minw.read_uint (rcInt (IDS_MINWIDTH)) * DPI + hborder,
minh.read_uint (rcInt (IDS_MINHIEHGT)) * DPI + vborder
);
this->WindowState = (System::Windows::Forms::FormWindowState)lasts.read_int ((int)System::Windows::Forms::FormWindowState::Normal);
}
void Init ()
{
this->Visible = false;
this->webui = gcnew System::Windows::Forms::WebBrowser ();
this->SuspendLayout ();
this->webui->Dock = System::Windows::Forms::DockStyle::Fill;
this->webui->IsWebBrowserContextMenuEnabled = DEBUGMODE;
this->webui->AllowWebBrowserDrop = false;
this->Controls->Add (this->webui);
if (g_hIconMain.hIcon)
{
try { this->Icon = System::Drawing::Icon::FromHandle (IntPtr (g_hIconMain.hIcon)); }
catch (...) {}
}
this->Text = GetRCStringCli (IDS_WINTITLE);
this->ResumeLayout (false);
webui->ObjectForScripting = gcnew IBridge (this);
this->webui->DocumentCompleted += gcnew System::Windows::Forms::WebBrowserDocumentCompletedEventHandler (this, &MainHtmlWnd::OnDocumentCompleted);
this->webui->PreviewKeyDown += gcnew System::Windows::Forms::PreviewKeyDownEventHandler (this, &MainHtmlWnd::OnPreviewKeyDown_WebBrowser);
this->Resize += gcnew System::EventHandler (this, &MainHtmlWnd::OnResize);
this->Load += gcnew EventHandler (this, &MainHtmlWnd::OnCreate);
this->ResizeEnd += gcnew EventHandler (this, &MainHtmlWnd::OnResizeEnd);
}
void OnDocumentCompleted (Object ^sender, System::Windows::Forms::WebBrowserDocumentCompletedEventArgs ^e)
{
if (e->Url->ToString () == webui->Url->ToString ())
{
ExecScript ("Windows.UI.DPI.mode = 1");
ExecScript ("Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
auto &ini = g_initfile;
auto setsect = ini ["Settings"];
auto lwr = setsect [L"AppInstaller:LaunchWhenReady"];
bool launchwhenready = lwr.read_bool (true);
if (g_wcmdflags & (DWORD)CMDPARAM::SILENT) launchwhenready = false;
InvokeCallScriptFunction ("setLaunchWhenReady", launchwhenready, g_wcmdflags & (DWORD)CMDPARAM::SILENT);
SetPage ("splash");
splash->FadeAway ();
ThreadPackageLoadTask ();
}
}
void OnCreate (System::Object ^sender, System::EventArgs ^e)
{
splash->Owner = this;
splash->ChangePosAndSize ();
splash->Show ();
splash->Update ();
splash->SetSplashImage (GetSuitSplashImage ());
System::Windows::Forms::Application::DoEvents ();
auto htmlpath = CombinePath (GetProgramRootDirectoryW (), L"html\\install.html");
webui->Navigate (CStringToMPString (htmlpath));
if (!IsFileExists (htmlpath))
{
std::wstring msg = L"Error: cannot find file \"" + htmlpath + L"\".";
MessageBoxW (InvokeGetHWND (), msg.c_str (), GetRCStringSW (IDS_WINTITLE).c_str (), MB_ICONERROR);
this->Close ();
return;
}
}
void OnPreviewKeyDown_WebBrowser (System::Object ^sender, System::Windows::Forms::PreviewKeyDownEventArgs ^e)
{
if (e->KeyCode == System::Windows::Forms::Keys::F5 || (e->KeyCode == System::Windows::Forms::Keys::R && e->Control))
e->IsInputKey = true;
}
void ResponseSplashChange ()
{
splash->SetSplashImage (GetSuitSplashImage ());
ExecScript (
"(function () {"
"var splash = Page.splash;"
"if (!splash) return null;"
"splash.imagesrc = Bridge.UI.Splash.imageurl;"
"splash.background = Bridge.UI.Splash.backcolor;"
"var progress = splash.content.querySelector (\"progress\");"
"if (Bridge.Frame.WindowSize.height / Bridge.UI.dpi < 500) {"
"if (progress.classList.contains(\"win-ring\")) progress.classList.remove(\"win-ring\");}"
"else { if (!progress.classList.contains(\"win-ring\")) progress.classList.add(\"win-ring\"); }"
"}) ();"
);
}
void OnResize (Object ^sender, EventArgs ^e) { ResizeEvent (); }
void OnResizeEnd (Object ^sender, EventArgs ^e) {}
std::wstring GetSuitSplashImage ()
{
int limitw = 800 * DPI;
int limith = 600 * DPI;
std::wstring tag = L"splash";
int noww = this->Width;
int nowh = this->Height;
if (noww >= limitw && nowh >= limith)
tag = L"splashlarge";
std::wstring path = g_scaleres [tag];
if (IsNormalizeStringEmpty (path))
path = g_scaleres [L"splash"];
if (IsNormalizeStringEmpty (path))
path = g_vemani.splash_screen_image (L"App");
return path;
}
void ResizeEvent ()
{
auto &ini = g_initfile;
auto setsect = ini ["Settings"];
auto lasts = setsect [L"AppInstaller:LastWndState"];
auto savepos = setsect [L"AppInstaller:SavePosAndSizeBeforeCancel"];
auto lastw = setsect [L"AppInstaller:LastWidth"];
auto lasth = setsect [L"AppInstaller:LastHeight"];
switch (this->WindowState)
{
case System::Windows::Forms::FormWindowState::Normal:
case System::Windows::Forms::FormWindowState::Maximized:
lasts = (int)this->WindowState;
}
if (this->WindowState == System::Windows::Forms::FormWindowState::Normal && savepos)
{
lastw = (int)(this->ClientSize.Width / DPI);
lasth = (int)(this->ClientSize.Height / DPI);
}
ResponseSplashChange ();
}
System::Threading::Thread ^ThreadPackageLoadTask ()
{
auto thread = gcnew Threading::Thread (gcnew Threading::ThreadStart (this, &MainHtmlWnd::PackageLoadTask));
thread->IsBackground = true;
thread->Start ();
return thread;
}
void PackageLoadTask ()
{
bool res = ReadPackagesTask (gcnew Action <String ^> (this, &MainHtmlWnd::ReadPackageCallback));
InvokeCallScriptFunction ("setSplashPageStatusText", "");
if (res)
{
String ^fmt = GetRCStringCli (IDS_PREINSTALL_TITLE);
String ^btn1 = GetRCStringCli (IDS_PREINSTALL_TINSTALL);
String ^btn2 = GetRCStringCli (IDS_PREINSTALL_CANCEL);
if (g_pkginfo.size () == 1)
{
try
{
const auto &pi = g_pkginfo.at (0);
const std::wstring
&name = pi.identity.name,
&publisher = pi.identity.publisher,
&family = pi.identity.package_family_name,
&fullname = pi.identity.package_full_name;
std::vector <find_pkginfo> fpkgs;
std::wstring err, msg;
HRESULT hr = S_OK;
if (g_initfile [L"Settings"] [L"AppInstaller:CheckPackageIsIntalled"].read_bool ())
hr = GetAppxPackages (family, fpkgs, err, msg);
bool isfind = false;
find_pkginfo findpkg;
if (fpkgs.size () > 0)
{
for (auto &it : fpkgs)
{
if (it.identity.name != pi.identity.name) continue;
auto archs = pi.get_architectures ();
for (auto &arch : archs)
{
if (arch == it.identity.architecture)
{
isfind = true;
findpkg = it;
break;
}
else if (arch == 11 || it.identity.architecture == 11)
{
isfind = true;
findpkg = it;
break;
}
}
if (isfind) break;
if (it.properties.resource_package && pi.properties.resource_package && it.identity.resource_id == pi.identity.resource_id)
{
isfind = true;
findpkg = it;
break;
}
if (archs.size () == 0 && it.identity.architecture == (WORD)-1)
{
isfind = true;
findpkg = it;
break;
}
}
}
if (isfind)
{
version fver = findpkg.identity.version,
pver (pi.identity.realver.major, pi.identity.realver.minor, pi.identity.realver.build, pi.identity.realver.revision);
if (pver > fver) // <20><><EFBFBD><EFBFBD>ģʽ
{
insmode = InstallType::update;
fmt = GetRCStringCli (IDS_PREINSTALL_TUPDATE);
btn1 = GetRCStringCli (IDS_PREINSTALL_CUPDATE);
btn2 = GetRCStringCli (IDS_PREINSTALL_CANCEL);
}
else if (pver == fver)
{
insmode = InstallType::reinstall;
fmt = GetRCStringCli (IDS_PREINSTALL_TREINSTALL);
btn1 = GetRCStringCli (IDS_PREINSTALL_CREINSTALL);
btn2 = GetRCStringCli (IDS_SUCCESS_LAUNCH);
}
else
{
insmode = InstallType::reinstall;
fmt = GetRCStringCli (IDS_PREINSTALL_HASINSTALLED);
btn1 = GetRCStringCli (IDS_PREINSTALL_CREINSTALL);
btn2 = GetRCStringCli (IDS_SUCCESS_LAUNCH);
}
}
}
catch (...) {}
}
InvokeCallScriptFunction ("noticeLoadPreinstallPage", g_pkginfo.size () > 1);
InvokeCallScriptFunction ("setPreinstallPagePkgTitleFormatSingle", fmt);
InvokeCallScriptFunction ("setControlButtonState", 1, btn1, true, false);
InvokeCallScriptFunction ("setControlButtonState", 2, btn2, true, false);
pagetag = "preinstall";
if (g_wcmdflags & (DWORD)CMDPARAM::SILENT) ThreadPackageInstallTask ();
}
else
{
InvokeCallScriptFunction ("noticeLoadSelectPage", g_pkginfo.size () > 1);
pagetag = "select";
}
}
void ReadPackageCallback (String ^lpPath)
{
size_t pkgfilelen = g_pkgfiles.size ();
if (pkgfilelen > 1)
{
InvokeCallScriptFunction (
"setSplashPageStatusText",
System::String::Format (GetRCStringCli (IDS_SPLASH_MLOAD), lpPath)
);
}
}
bool ReadPackagesTask (System::Action <String ^> ^callback)
{
std::vector <std::wstring> noread;
std::vector <std::wstring> hasread;
for (auto &it : g_pkgfiles)
{
bool isfind = false;
for (auto &rit : g_pkginfo)
{
if (rit.filepath == it)
{
isfind == true;
push_unique <std::wstring> (hasread, it);
break;
}
}
if (!isfind) push_unique <std::wstring> (noread, it);
}
for (auto &it : noread)
{
try { if (callback) callback (gcnew String (it.c_str ())); }
catch (Exception ^e) { if (DEBUGMODE) OutputDebugStringW (MPStringToPtrW (e->Message)); }
auto pi = pkginfo::parse (it);
if (pi.valid)
{
push_unique (hasread, pi.filepath);
g_pkginfo.push_back (pi);
}
}
g_pkgfiles.clear ();
for (auto &it : hasread) push_unique <std::wnstring> (g_pkgfiles, it);
return hasread.size ();
}
void InstallProgressCallback (DWORD dwProgress)
{
InvokeCallScriptFunction ("setInstallingProgress", dwProgress);
InvokeCallScriptFunction ("setInstallingStatus", String::Format (GetRCStringCli (IDS_INSTALLING_SINSTALLING_PROGRESS), dwProgress));
taskbar->SetProgressValue (InvokeGetHWND (), dwProgress, 100);
}
void InstallProgressCallbackMultiple (DWORD dwProgress)
{
double progress = (dwProgress * 0.01 + nowinstall) / (double)g_pkginfo.size () * 100;
InvokeCallScriptFunction ("setInstallingProgress", progress);
InvokeCallScriptFunction ("setInstallingStatus", String::Format (GetRCStringCli (IDS_INSTALLING_MSINSTALLING_PROGRESS), dwProgress, nowinstall + 1, g_pkginfo.size ()));
taskbar->SetProgressValue (InvokeGetHWND (), progress * g_pkginfo.size (), 100 * g_pkginfo.size ());
}
System::Threading::Thread ^ThreadPackageInstallTask ()
{
auto thread = gcnew Threading::Thread (gcnew Threading::ThreadStart (this, &MainHtmlWnd::PackageInstallTask));
thread->IsBackground = true;
thread->Start ();
return thread;
}
void PackageInstallTask ()
{
InvokeCallScriptFunction ("noticeLoadInstallingPage", g_pkginfo.size () > 1);
std::vector <std::wstring> blankdeplist;
if (g_pkginfo.size () == 1)
{
auto &pi = *g_pkginfo.begin ();
InvokeCallScriptFunction ("setInstallingStatus", GetRCStringCli (IDS_INSTALLING_SLOADCER));
LoadCertFromSignedFile (pi.filepath.c_str ());
InvokeCallScriptFunction ("setInstallingStatus", GetRCStringCli (IDS_INSTALLING_SINSTALLING));
InvokeCallScriptFunction ("setInstallingProgress", 0);
package_installresult pir;
if (insmode == InstallType::update)
{
pir.result = UpdateAppxPackageFromPath (pi.filepath, blankdeplist, DEPOLYOPTION_NONE, gcnew InstallProgressCallbackDelegate (this, &MainHtmlWnd::InstallProgressCallback), pir.error, pir.reason);
if (FAILED (pir.result))
pir.result = AddAppxPackageFromPath (pi.filepath, blankdeplist, DEPOLYOPTION_NONE, gcnew InstallProgressCallbackDelegate (this, &MainHtmlWnd::InstallProgressCallback), pir.error, pir.reason);
}
else pir.result = AddAppxPackageFromPath (pi.filepath, blankdeplist, DEPOLYOPTION_NONE, gcnew InstallProgressCallbackDelegate (this, &MainHtmlWnd::InstallProgressCallback), pir.error, pir.reason);
g_pkgresult [pi.filepath] = pir;
taskbar->SetProgressState (InvokeGetHWND (), TBPF_NOPROGRESS);
if (pir.succeeded ())
{
InvokeCallScriptFunction ("noticeLoadInstallSuccessPage", false);
pagetag = "installsuccess";
InvokeLaunchAppForLaunchWhenReady ();
CreateToastNoticeWithImgBase64 (
g_identity,
MPStringToStdW (
System::String::Format (
GetRCStringCli (IDS_SUCCESS_TITLE),
CStringToMPString (pi.properties.display_name)
)
),
pi.properties.logo_base64
);
ThreadPackageSuccessInstallCountTask ();
}
else
{
InvokeCallScriptFunction ("noticeLoadInstallFailedPage", false);
pagetag = "installfailed";
CreateToastNotice2WithImgBase64 (
g_identity,
MPStringToStdW (
System::String::Format (
GetRCStringCli (IDS_FAILED_STITLE),
CStringToMPString (pi.properties.display_name)
)
),
pir.reason,
pi.properties.logo_base64
);
if (g_wcmdflags & (DWORD)CMDPARAM::SILENT) ThreadPackageSuccessInstallCountTask ();
}
}
else
{
for (nowinstall = 0; nowinstall < g_pkginfo.size (); nowinstall ++)
{
auto &it = g_pkginfo.at (nowinstall);
InvokeCallScriptFunction ("setInstallingPackageInfoMultiple", CStringToMPString (it.filepath));
InvokeCallScriptFunction (
"setInstallingStatus",
String::Format (
GetRCStringCli (IDS_INSTALLING_MLOADCER),
nowinstall + 1,
g_pkginfo.size ()
)
);
LoadCertFromSignedFile (it.filepath.c_str ());
InvokeCallScriptFunction (
"setInstallingStatus",
String::Format (
GetRCStringCli (IDS_INSTALLING_MPKGNAME),
nowinstall + 1,
g_pkginfo.size ()
)
);
package_installresult pir;
pir.result = AddAppxPackageFromPath (
it.filepath,
blankdeplist,
DEPOLYOPTION_NONE,
gcnew InstallProgressCallbackDelegate (this, &MainHtmlWnd::InstallProgressCallbackMultiple),
pir.error,
pir.reason
);
if (pir.failed ()) taskbar->SetProgressState (InvokeGetHWND (), TBPF_ERROR);
g_pkgresult [it.filepath] = pir;
}
taskbar->SetProgressState (InvokeGetHWND (), TBPF_NOPROGRESS);
bool allsuccess = true;
for (auto &it : g_pkgresult)
{
allsuccess = allsuccess && it.second.succeeded ();
if (!allsuccess) break;
}
if (allsuccess)
{
InvokeCallScriptFunction ("noticeLoadInstallSuccessPage", true);
InvokeLaunchAppForLaunchWhenReady ();
pagetag = "installsuccess";
CreateToastNotice (g_identity, GetRCStringSW (IDS_SUCCESS_MTITLE), L"");
ThreadPackageSuccessInstallCountTask ();
}
else
{
InvokeCallScriptFunction ("noticeLoadInstallFailedPage", true);
CreateToastNotice (g_identity, GetRCStringSW (IDS_FAILED_MTITLE), L"");
pagetag = "installfailed";
if (g_wcmdflags & (DWORD)CMDPARAM::SILENT) ThreadPackageSuccessInstallCountTask ();
}
}
}
System::Threading::Thread ^ThreadPackageSuccessInstallCountTask ()
{
auto thread = gcnew Threading::Thread (gcnew Threading::ThreadStart (this, &MainHtmlWnd::PackageSuccessInstallCountTask));
thread->IsBackground = true;
thread->Start ();
return thread;
}
void PackageSuccessInstallCountTask ()
{
size_t cnt = 0;
for (auto &it : g_pkginfo)
for (auto &it_s : it.applications)
if (!it_s [L"Id"].empty ()) cnt ++;
if (cnt <= 0) cnt = 1;
if (cnt > 3) cnt = 3;
if (g_wcmdflags & (DWORD)CMDPARAM::SILENT && cnt > 1) cnt = 2;
System::Threading::Thread::Sleep (System::TimeSpan (0, 0, 5 * cnt));
this->InvokeClose ();
}
void InvokeClose ()
{
if (this->InvokeRequired) this->Invoke (gcnew Action (this, &MainHtmlWnd::Close));
else this->Close ();
}
String ^GetPage () { return pagetag; }
String ^SetPage (String ^tag)
{
InvokeCallScriptFunction ("setPage", tag, g_pkginfo.size () > 1);
return pagetag = tag;
}
#define nequals(_str1_, _str2_) IsNormalizeStringEquals (ToStdWString (_str1_), ToStdWString (_str2_))
void OnPress_Button1 ()
{
std::wstring current = MPStringToStdW (pagetag);
if (nequals (current, L"select"))
{
std::vector <std::wstring> files;
std::wstring item1 = GetRCStringSW (IDS_SELECT_DLGAPPX),
item1type = L"*.appx;*.appxbundle",
item2 = GetRCStringSW (IDS_SELECT_DLGALL),
item2type = L"*.*";
std::vector <WCHAR> buf (item1.capacity () + item1type.capacity () + item2.capacity () + item2type.capacity () + 5);
strcpynull (buf.data (), item1.c_str (), buf.size ());
strcpynull (buf.data (), item1type.c_str (), buf.size ());
strcpynull (buf.data (), item2.c_str (), buf.size ());
strcpynull (buf.data (), item2type.c_str (), buf.size ());
ExploreFile (
this->InvokeGetHWND (),
files,
buf.data (),
OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST,
GetRCStringSW (IDS_SELECT_DLGTITLE)
);
if (files.empty ()) return;
for (auto &it : files) g_pkgfiles.push_back (it);
this->PageTag = "loading";
ThreadPackageLoadTask ();
return;
}
else if (nequals (current, L"preinstall"))
{
if (g_pkginfo.size () == 1)
{
switch (insmode)
{
case InstallType::reinstall:
ThreadPackageInstallTask ();
break;
default:
case InstallType::normal:
case InstallType::update:
ThreadPackageInstallTask ();
break;
}
}
else ThreadPackageInstallTask ();
return;
}
else if (nequals (current, L"installsuccess"))
{
std::vector <std::wnstring> appids;
for (auto &it : g_pkginfo)
for (auto &it_s : it.applications)
if (!it_s [L"Id"].empty ())
appids.emplace_back (it.identity.package_family_name + L'!' + it_s [L"Id"]);
if (appids.size () == 1) ActivateAppxApplication (appids.at (0));
else if (appids.size () > 1) AppListWnd::DisplayWindow ();
else this->Close ();
}
else if (nequals (current, L"installfailed")) this->Close ();
return;
System::Windows::Forms::MessageBox::Show ("Button1 <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>");
}
void OnPress_Button2 ()
{
std::wstring current = MPStringToStdW (pagetag);
if (nequals (current, L"select"))
{
this->Close ();
return;
}
else if (nequals (current, L"preinstall"))
{
if (g_pkginfo.size () == 1)
{
switch (insmode)
{
case InstallType::reinstall: {
auto &pi = *g_pkginfo.begin ();
if (pi.applications.size () == 1) ActivateAppxApplication (pi.identity.package_family_name + L"!" + pi.applications.at (0).at (L"Id"));
else AppListWnd::DisplayWindow ();
} break;
default:
case InstallType::normal:
case InstallType::update:
this->Close ();
break;
}
}
else this->Close ();
return;
}
else if (nequals (current, L"installfailed")) this->Close ();
return;
System::Windows::Forms::MessageBox::Show ("Button2 <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>");
}
void LaunchAppForLaunchWhenReady ()
{
if (!(g_wcmdflags & (DWORD)CMDPARAM::SILENT))
{
auto launch_when_ready = (bool)InvokeCallScriptFunction ("getLaunchWhenReady");
if (!launch_when_ready) return;
std::vector <std::wnstring> appids;
for (auto &it : g_pkginfo)
for (auto &it_s : it.applications)
if (!it_s [L"Id"].empty ())
appids.emplace_back (it.identity.package_family_name + L'!' + it_s [L"Id"]);
if (appids.size () == 1) ActivateAppxApplication (appids.at (0));
else if (appids.size () > 1) AppListWnd::DisplayWindow ();
}
}
void InvokeLaunchAppForLaunchWhenReady ()
{
if (this->InvokeRequired) this->Invoke (gcnew Action (this, &MainHtmlWnd::LaunchAppForLaunchWhenReady));
else LaunchAppForLaunchWhenReady ();
}
#ifdef nequals
#undef nequals
#endif
IntPtr GetHWnd () { return this->Handle; }
delegate IntPtr GetHwndDelegate ();
HWND InvokeGetHWND ()
{
if (this->InvokeRequired)
{
GetHwndDelegate ^del = gcnew GetHwndDelegate (this, &MainHtmlWnd::GetHWnd);
IntPtr result = safe_cast <IntPtr> (this->Invoke (del));
return static_cast <HWND> (result.ToPointer ());
}
else return static_cast <HWND> (this->Handle.ToPointer ());
}
public:
MainHtmlWnd ()
{
InitSize ();
System::Windows::Forms::Application::DoEvents ();
splash = gcnew SplashForm (
CStringToMPString (GetSuitSplashImage ()),
StringToColor (CStringToMPString (g_vemani.splash_screen_backgroundcolor (L"App"))),
this
);
System::Windows::Forms::Application::DoEvents ();
Init ();
ITaskbarList3 *ptr = nullptr;
HRESULT hr = CoCreateInstance (CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&ptr);
if (SUCCEEDED (hr))
{
taskbar = ptr;
taskbar->HrInit ();
}
else
{
taskbar = nullptr;
if (ptr) ptr->Release ();
}
}
Object ^CallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try { return this->webui->Document->InvokeScript (lpFuncName, alpParams); }
catch (Exception ^e)
{
try
{
this->webui->Document->InvokeScript ("messageBoxAsync", gcnew array <Object ^> {
e->Message,
e->Source,
0,
CStringToMPString (g_vemani.background_color (L"App"))
});
}
catch (Exception ^ex)
{
MessageBoxW (InvokeGetHWND (), MPStringToStdW (e->Message).c_str (), MPStringToStdW (e->Source).c_str (), 0);
}
}
return nullptr;
}
Object ^CallScriptFunction (String ^lpScriptName)
{
try { return this->webui->Document->InvokeScript (lpScriptName); }
catch (Exception ^ex) { System::Windows::Forms::MessageBox::Show ("Error calling JavaScript function: " + ex->Message); }
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpFuncName, ... array <Object ^> ^alpParams)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, array <Object ^> ^, Object ^> (this, &MainHtmlWnd::CallScriptFunction), lpFuncName, alpParams);
else return CallScriptFunction (lpFuncName, alpParams);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^InvokeCallScriptFunction (String ^lpScriptName)
{
try
{
if (this->InvokeRequired) return (Object ^)this->Invoke (gcnew Func <String ^, Object ^> (this, &MainHtmlWnd::CallScriptFunction), lpScriptName);
else return CallScriptFunction (lpScriptName);
}
catch (Exception ^e) {}
return nullptr;
}
Object ^ExecScript (... array <Object ^> ^alpScript) { return InvokeCallScriptFunction ("eval", alpScript); }
Object ^CallEvent (String ^funcName, Object ^e) override
{
std::wstring fname = MPStringToStdW (funcName);
if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_Button1")) OnPress_Button1 ();
else if (IsNormalizeStringEquals (fname.c_str (), L"OnPress_Button2")) OnPress_Button2 ();
return nullptr;
}
property int PageScale
{
int get ()
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return 0;
VARIANT v;
VariantInit (&v);
hr = web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, nullptr, &v);
if (FAILED (hr) || v.vt != VT_I4) return 0;
int val = v.lVal;
VariantClear (&v);
return val;
}
void set (int value)
{
CComPtr <IWebBrowser2> web2;
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
if (FAILED (hr)) return;
VARIANT v;
VariantInit (&v);
v.vt = VT_I4;
v.lVal = value;
web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &v, nullptr);
}
}
~MainHtmlWnd ()
{
if (taskbar) taskbar->Release ();
taskbar = nullptr;
}
};
using MainWnd = MainHtmlWnd;
std::vector <std::wstring> LoadFileListW (const std::wstring &filePath)
{
std::vector <std::wstring> result;
std::wifstream file (filePath);
if (!file.is_open ()) return result;
file.imbue (std::locale (file.getloc (), new std::codecvt_utf8_utf16 <wchar_t>));
std::wstring line;
while (std::getline (file, line))
{
if (!line.empty () && line.back () == L'\r') line.pop_back ();
if (!line.empty () && !std::wnstring::empty (line) && IsFileExists (line)) result.push_back (line);
}
return result;
}
std::wstring GenerateCmdHelper ()
{
std::wstring ret = GetRCStringSW (IDS_CMDTIP_PRETEXT) + L"\r\n";
for (auto &it : g_argslist)
{
if (it.description.empty ()) continue;
ret += L"\r\n";
ret += L"\t" + (it.prefixs.size () ? it.prefixs.at (0) : L"") + it.commands.at (0) + L"\r\n";
ret += L"\t" + it.description + L"\r\n";
}
return ret;
}
DWORD CmdMapsToFlags (std::map <cmdkey, cmdvalue> cmdpairs, std::vector <std::wnstring> &files = std::vector <std::wnstring> (), std::vector <std::wnstring> &uris = std::vector <std::wnstring> ())
{
DWORD dwret = 0;
for (auto &it : cmdpairs)
{
switch (it.first.type)
{
case paramtype::file: {
if (IsFileExists (it.first.key)) push_unique (files, it.first.key);
} break;
case paramtype::uri: {
push_unique (uris, it.first.key);
} break;
default:
case paramtype::string: {
auto &key = it.first;
auto &value = it.second;
if (key.key.equals (L"silent")) dwret |= (DWORD)CMDPARAM::SILENT;
else if (key.key.equals (L"verysilent")) dwret |= (DWORD)CMDPARAM::SILENT;
else if (key.key.equals (L"multiple"))
{
if (value.type == paramtype::file)
{
auto strlist = LoadFileListW (value.value);
for (auto &it_s : strlist)
{
if (std::wnstring::empty (it_s)) continue;
std::wnstring filepath = it_s;
std::wstring listdir = GetFileDirectoryW (value.value);
if (!IsFileExists (filepath)) filepath = ProcessEnvVars (filepath);
if (!IsFileExists (filepath)) filepath = CombinePath (listdir, filepath);
if (!IsFileExists (filepath)) filepath = CombinePath (listdir, it_s);
if (!IsFileExists (filepath)) continue;
else push_unique (files, filepath);
}
}
}
else if (key.key.equals (L"language")) SetThreadUILanguage (LocaleCodeToLcid (value.value));
} break;
}
}
if (files.size () > 1) dwret |= (DWORD)CMDPARAM::MULTIPLE;
return dwret;
}
HRESULT SetCurrentAppUserModelID (PCWSTR appID)
{
typedef HRESULT (WINAPI *SetAppUserModelIDFunc)(PCWSTR);
HMODULE shell32 = LoadLibraryW (L"shell32.dll");
destruct freelib ([&] () {
if (shell32) FreeLibrary (shell32);
});
try
{
if (!shell32) return E_FAIL;
auto SetAppUserModelID = (SetAppUserModelIDFunc)GetProcAddress (shell32, "SetCurrentProcessExplicitAppUserModelID");
if (!SetAppUserModelID)
{
FreeLibrary (shell32);
return E_FAIL;
}
return SetAppUserModelID (appID);
}
catch (...) { return E_FAIL; }
return E_FAIL;
}
void InstallPackageTaskVerySilent ()
{
for (auto &it : g_pkgfiles)
{
AddAppxPackageFromPath (it.c_str ());
}
}
[STAThread]
int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
SetCurrentProcessExplicitAppUserModelID (m_idenName);
SetProcessDPIAware ();
{
// <20><><EFBFBD>õ<EFBFBD>ǰĿ¼Ϊ<C2BC><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼
std::wnstring currdir = GetCurrentDirectoryW ();
std::wnstring rootdir = GetProgramRootDirectoryW ();
if (!PathEquals (currdir, rootdir)) SetCurrentDirectoryW (rootdir.c_str ());
}
CoInitializeEx (NULL, COINIT_MULTITHREADED | COINIT_APARTMENTTHREADED);
SetupInstanceEnvironment ();
destruct relco ([] () {
CoUninitialize ();
});
{
std::map <cmdkey, cmdvalue> pair_cmdkv;
ParseCmdLine (lpCmdLine, pair_cmdkv);
for (auto pair : pair_cmdkv)
{
if (pair.first.key == std::wnstring (L"help"))
{
MessageBoxW (nullptr, GenerateCmdHelper ().c_str (), GetRCStringSW (IDS_WINTITLE).c_str (), 0);
return 0;
}
}
g_wcmdflags = CmdMapsToFlags (pair_cmdkv, g_pkgfiles);
if (g_wcmdflags & (DWORD)CMDPARAM::VERYSILENT)
{
try
{
InstallPackageTaskVerySilent ();
return 0;
}
catch (...) { return 1; }
}
}
SetWebBrowserEmulation ();
System::Windows::Forms::Application::EnableVisualStyles ();
System::Windows::Forms::Application::SetCompatibleTextRenderingDefault (false);
auto mwnd = gcnew MainHtmlWnd ();
g_mainwnd = mwnd;
System::Windows::Forms::Application::Run (mwnd);
return 0;
}