diff --git a/AppInstallerReset.sln b/AppInstallerReset.sln index e0e0ff3..78ada54 100644 --- a/AppInstallerReset.sln +++ b/AppInstallerReset.sln @@ -18,63 +18,94 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest\dlltest. EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "..\priformatcli\priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}" + ProjectSection(ProjectDependencies) = postProject + {EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgmgr", "pkgmgr\pkgmgr.vcxproj", "{8EAC0230-4990-4E41-8E0F-D641D1561396}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notice", "notice\notice.vcxproj", "{798ED492-EECE-457D-8FD8-129DA93CE126}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriFile", "PriFileFormat\PriFile.csproj", "{EF4012D4-EF08-499C-B803-177739350B2D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|Any CPU.ActiveCfg = Debug|Win32 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x64.ActiveCfg = Debug|x64 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x64.Build.0 = Debug|x64 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x86.ActiveCfg = Debug|Win32 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x86.Build.0 = Debug|Win32 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|Any CPU.ActiveCfg = Release|Win32 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x64.ActiveCfg = Release|x64 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x64.Build.0 = Release|x64 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x86.ActiveCfg = Release|Win32 {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x86.Build.0 = Release|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|Any CPU.ActiveCfg = Debug|Win32 {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.ActiveCfg = Debug|x64 {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.Build.0 = Debug|x64 {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.ActiveCfg = Debug|Win32 {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.Build.0 = Debug|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|Any CPU.ActiveCfg = Release|Win32 {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.ActiveCfg = Release|x64 {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.Build.0 = Release|x64 {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32 {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|Any CPU.ActiveCfg = Debug|Win32 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.ActiveCfg = Debug|x64 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.Build.0 = Debug|x64 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x86.ActiveCfg = Debug|Win32 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x86.Build.0 = Debug|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|Any CPU.ActiveCfg = Release|Win32 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x64.ActiveCfg = Release|x64 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x64.Build.0 = Release|x64 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.ActiveCfg = Release|Win32 {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.Build.0 = Release|Win32 + {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|Any CPU.ActiveCfg = Debug|Win32 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.ActiveCfg = Debug|x64 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.Build.0 = Debug|x64 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32 + {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|Any CPU.ActiveCfg = Release|Win32 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.ActiveCfg = Release|x64 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.Build.0 = Release|x64 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32 {33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32 + {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|Any CPU.ActiveCfg = Debug|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x64.ActiveCfg = Debug|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.ActiveCfg = Debug|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.Build.0 = Debug|Win32 + {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|Any CPU.ActiveCfg = Release|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x64.ActiveCfg = Release|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.ActiveCfg = Release|Win32 {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.Build.0 = Release|Win32 + {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|Any CPU.ActiveCfg = Debug|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x64.ActiveCfg = Debug|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.ActiveCfg = Debug|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.Build.0 = Debug|Win32 + {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|Any CPU.ActiveCfg = Release|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x64.ActiveCfg = Release|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.ActiveCfg = Release|Win32 {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.Build.0 = Release|Win32 + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x64.ActiveCfg = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x64.Build.0 = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.ActiveCfg = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.Build.0 = Debug|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.Build.0 = Release|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|x64.ActiveCfg = Release|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|x64.Build.0 = Release|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.ActiveCfg = Release|Any CPU + {EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PriFileFormat b/PriFileFormat new file mode 120000 index 0000000..3758023 --- /dev/null +++ b/PriFileFormat @@ -0,0 +1 @@ +E:/Profiles/Bruce/Documents/Visual Studio 2015/Projects/PriFileFormat/PriFileFormat \ No newline at end of file diff --git a/notice/notice.cpp b/notice/notice.cpp index fb4413b..77dd569 100644 --- a/notice/notice.cpp +++ b/notice/notice.cpp @@ -5,8 +5,11 @@ #include "notice.h" #include "raii.h" #include "version.h" +#include "nstring.h" +#ifdef GetFullPathName #undef GetFullPathName +#endif std::wstring GetFullPathName (const std::wstring &lpFileName) { if (lpFileName.empty ()) return L""; @@ -18,9 +21,6 @@ std::wstring GetFullPathName (const std::wstring &lpFileName) return std::wstring (buffer.data (), result); } -std::wstring g_swExceptionCode = L""; -std::wstring g_swExceptionDetail = L""; - struct destruct { std::function endtask = nullptr; @@ -36,4 +36,299 @@ static std::wstring StringToWString (const std::string &str, UINT codePage = CP_ MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len); return wstr; } +LPWSTR GetToastNoticeXml (LPCWSTR lpTemplateName) +{ + auto xmldoc = ref new Windows::Data::Xml::Dom::XmlDocument (); + auto root = xmldoc->CreateElement ("toast"); + xmldoc->AppendChild (root); + auto visual = xmldoc->CreateElement ("visual"); + root->AppendChild (visual); + auto binding = xmldoc->CreateElement ("binding"); + visual->AppendChild (binding); + std::wnstring temp = lpTemplateName ? lpTemplateName : L""; + if (temp.equals (L"ToastText01")) + { + binding->SetAttribute ("template", "ToastText01"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + binding->AppendChild (text1); + } + else if (temp.equals (L"ToastText02")) + { + binding->SetAttribute ("template", "ToastText02"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto text2 = xmldoc->CreateElement ("text"); + text2->SetAttribute ("id", "2"); + binding->AppendChild (text1); + binding->AppendChild (text2); + } + else if (temp.equals (L"ToastText03")) + { + binding->SetAttribute ("template", "ToastText03"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto text2 = xmldoc->CreateElement ("text"); + text2->SetAttribute ("id", "2"); + binding->AppendChild (text1); + binding->AppendChild (text2); + } + else if (temp.equals (L"ToastText04")) + { + binding->SetAttribute ("template", "ToastText04"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto text2 = xmldoc->CreateElement ("text"); + text2->SetAttribute ("id", "2"); + auto text3 = xmldoc->CreateElement ("text"); + text3->SetAttribute ("id", "3"); + binding->AppendChild (text1); + binding->AppendChild (text2); + binding->AppendChild (text3); + } + else if (temp.equals (L"ToastImageAndText01")) + { + binding->SetAttribute ("template", "ToastImageAndText01"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto img1 = xmldoc->CreateElement ("image"); + img1->SetAttribute ("id", "1"); + img1->SetAttribute ("src", ""); + img1->SetAttribute ("alt", ""); + binding->AppendChild (img1); + binding->AppendChild (text1); + } + else if (temp.equals (L"ToastImageAndText02")) + { + binding->SetAttribute ("template", "ToastImageAndText02"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto img1 = xmldoc->CreateElement ("image"); + img1->SetAttribute ("id", "1"); + img1->SetAttribute ("src", ""); + img1->SetAttribute ("alt", ""); + binding->AppendChild (img1); + binding->AppendChild (text1); + } + else if (temp.equals (L"ToastImageAndText03")) + { + binding->SetAttribute ("template", "ToastImageAndText03"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto text2 = xmldoc->CreateElement ("text"); + text2->SetAttribute ("id", "2"); + auto img1 = xmldoc->CreateElement ("image"); + img1->SetAttribute ("id", "1"); + img1->SetAttribute ("src", ""); + img1->SetAttribute ("alt", ""); + binding->AppendChild (img1); + binding->AppendChild (text1); + binding->AppendChild (text2); + } + else if (temp.equals (L"ToastImageAndText04")) + { + binding->SetAttribute ("template", "ToastImageAndText04"); + auto text1 = xmldoc->CreateElement ("text"); + text1->SetAttribute ("id", "1"); + auto text2 = xmldoc->CreateElement ("text"); + text2->SetAttribute ("id", "2"); + auto text3 = xmldoc->CreateElement ("text"); + text3->SetAttribute ("id", "3"); + auto img1 = xmldoc->CreateElement ("image"); + img1->SetAttribute ("id", "1"); + img1->SetAttribute ("src", ""); + img1->SetAttribute ("alt", ""); + binding->AppendChild (img1); + binding->AppendChild (text1); + binding->AppendChild (text2); + binding->AppendChild (text3); + } + else + { + binding->SetAttribute ("template", "ToastImageAndText04"); + auto text1 = xmldoc->CreateElement ("text"); + binding->AppendChild (text1); + } + return _wcsdup (xmldoc->GetXml ()->Data ()); +} +LPWSTR GenerateSimpleToastNoticeXml (LPCWSTR lpText, LPCWSTR lpImagePath) +{ + auto xmldoc = ref new Windows::Data::Xml::Dom::XmlDocument (); + std::wnstring img = lpImagePath ? lpImagePath : L""; + std::wstring text = std::wnstring::trim (std::wstring (lpText ? lpText : L"")); + { + std::wstring xmltemplate = L""; + LPWSTR xt = nullptr; + raii relt ([&xt] () { + if (xt) free (xt); + xt = nullptr; + }); + xt = GetToastNoticeXml (img.empty () ? L"ToastText01" : L"ToastImageAndText01"); + if (xt && *xt) xmltemplate = xt; + xmldoc->LoadXml (ref new Platform::String (xmltemplate.c_str ())); + } + Windows::Foundation::Uri ^imguri = nullptr; + try { imguri = ref new Windows::Foundation::Uri (ref new Platform::String (img.c_str ())); } + catch (...) + { + try + { + std::wstring fullpath = GetFullPathName (lpImagePath ? lpImagePath : L""); + if (fullpath.empty ()) fullpath = lpImagePath ? lpImagePath : L""; + imguri = ref new Windows::Foundation::Uri (ref new Platform::String (img.c_str ())); + } + catch (...) { imguri = nullptr; } + } + auto toast = xmldoc->FirstChild; + auto visual = toast->FirstChild; + auto binding = visual->FirstChild; + auto binds = binding->ChildNodes; + auto textNodes = binding->SelectNodes (ref new Platform::String (L"text")); + if (textNodes && textNodes->Length > 0) + { + auto node = dynamic_cast (textNodes->Item (0)); + if (node) node->InnerText = ref new Platform::String (text.c_str ()); + } + auto imageNodes = binding->SelectNodes (ref new Platform::String (L"image")); + if (imageNodes && imageNodes->Length > 0 && !img.empty ()) + { + auto node = dynamic_cast (imageNodes->Item (0)); + if (node) + { + node->SetAttribute (L"src", ref new Platform::String (imguri && imguri->ToString ()->Data () ? imguri->ToString ()->Data () : img.c_str ())); + node->SetAttribute (L"alt", ref new Platform::String (L"image")); + } + } + return _wcsdup (xmldoc->GetXml ()->Data ()); +} +LPWSTR GenerateSimpleToastNoticeXml2 (LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImagePath) +{ + auto xmldoc = ref new Windows::Data::Xml::Dom::XmlDocument (); + std::wnstring img = lpImagePath ? lpImagePath : L""; + std::wstring title = std::wnstring (lpTitle ? lpTitle : L"").trim (); + std::wstring text = std::wnstring (lpText ? lpText : L"").trim (); + { + std::wstring xmltemplate = L""; + LPWSTR xt = nullptr; + raii relt ([&xt] () { + if (xt) free (xt); + xt = nullptr; + }); + std::wstring templatename = L""; + WORD flag = (bool)(!img.empty ()) << 2 | (bool)title.size () << 1 | (bool)text.size (); + switch (flag) + { + case 0b001: templatename = L"ToastText01"; break; // 仅正文 + case 0b011: templatename = L"ToastText02"; break; // 标题 + 正文 + case 0b101: templatename = L"ToastImageAndText01"; break; // 图 + 正文 + case 0b111: templatename = L"ToastImageAndText02"; break; // 图 + 标题 + 正文 + default: templatename = L"ToastText01"; break; + } + xt = GetToastNoticeXml (templatename.c_str ()); + if (xt && *xt) xmltemplate = xt; + xmldoc->LoadXml (ref new Platform::String (xmltemplate.c_str ())); + } + Windows::Foundation::Uri ^imguri = nullptr; + try { imguri = ref new Windows::Foundation::Uri (ref new Platform::String (img.c_str ())); } + catch (...) + { + try + { + std::wstring fullpath = GetFullPathName (lpImagePath ? lpImagePath : L""); + if (fullpath.empty ()) fullpath = lpImagePath ? lpImagePath : L""; + imguri = ref new Windows::Foundation::Uri (ref new Platform::String (img.c_str ())); + } + catch (...) { imguri = nullptr; } + } + auto binding = xmldoc->SelectSingleNode (ref new Platform::String (L"/toast/visual/binding")); + auto textNodes = binding->SelectNodes (ref new Platform::String (L"text")); + if (textNodes && textNodes->Length > 0) + { + unsigned int idx = 0; + if (!title.empty ()) + { + auto node = dynamic_cast (textNodes->Item (idx++)); + if (node) node->InnerText = ref new Platform::String (title.c_str ()); + } + if (!text.empty () && idx < textNodes->Length) + { + auto node = dynamic_cast (textNodes->Item (idx)); + if (node) node->InnerText = ref new Platform::String (text.c_str ()); + } + else if (!text.empty () && title.empty ()) + { + auto node = dynamic_cast (textNodes->Item (0)); + if (node) node->InnerText = ref new Platform::String (text.c_str ()); + } + } + auto imageNodes = binding->SelectNodes (ref new Platform::String (L"image")); + if (imageNodes && imageNodes->Length > 0 && !img.empty ()) + { + auto node = dynamic_cast (imageNodes->Item (0)); + if (node) + { + node->SetAttribute (L"src", ref new Platform::String (imguri && imguri->ToString ()->Data () ? imguri->ToString ()->Data () : img.c_str ())); + node->SetAttribute (L"alt", ref new Platform::String (L"image")); + } + } + return _wcsdup (xmldoc->GetXml ()->Data ()); +} +// 会实时记录 hResult; +HRESULT g_lasthr = S_OK; +// 记录上一次异常(不会根据操作更新)的信息 +std::wstring g_lastexc = L""; +#define catch_lasterr(_PHRESULT_Outptr_lphResult_, _HLPWSTR_Outptr_lpExcepMsg_) \ +catch (Platform::Exception ^e) \ +{ \ + g_lastexc = e->ToString ()->Data (); \ + if (_HLPWSTR_Outptr_lpExcepMsg_) *(_HLPWSTR_Outptr_lpExcepMsg_) = _wcsdup (g_lastexc.c_str ()); \ + g_lasthr = SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult; \ + if (_PHRESULT_Outptr_lphResult_) *(_PHRESULT_Outptr_lphResult_) = g_lasthr; \ +} \ +catch (const std::exception &e) \ +{ \ + g_lastexc = StringToWString (e.what () ? e.what () : "Unknown exception."); \ + if (_HLPWSTR_Outptr_lpExcepMsg_) *(_HLPWSTR_Outptr_lpExcepMsg_) = _wcsdup (g_lastexc.c_str ()); \ + g_lasthr = E_FAIL; \ + if (_PHRESULT_Outptr_lphResult_) *(_PHRESULT_Outptr_lphResult_) = g_lasthr; \ +} \ +catch (...) \ +{ \ + g_lastexc = L"Unknown exception"; \ + if (_HLPWSTR_Outptr_lpExcepMsg_) *(_HLPWSTR_Outptr_lpExcepMsg_) = _wcsdup (g_lastexc.c_str ()); \ + g_lasthr = E_FAIL; \ + if (_PHRESULT_Outptr_lphResult_) *(_PHRESULT_Outptr_lphResult_) = g_lasthr; \ +} +HRESULT CreateToastNoticeFromXmlDocument (LPCWSTR lpIdName, LPCWSTR lpXmlString, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg) +{ + using XmlDoc = Windows::Data::Xml::Dom::XmlDocument; + using ToastNotification = Windows::UI::Notifications::ToastNotification; + using Toast = ToastNotification; + using ToastMgr = Windows::UI::Notifications::ToastNotificationManager; + using String = Platform::String; + using Object = Platform::Object; + auto &hr = g_lasthr; + if (lpExceptMsg) *lpExceptMsg = nullptr; + try + { + Windows::UI::Notifications::ToastNotifier ^notifier = nullptr; + if (lpIdName && *lpIdName) notifier = ToastMgr::CreateToastNotifier (ref new String (lpIdName)); + else notifier = ToastMgr::CreateToastNotifier (); + auto xmldoc = ref new XmlDoc (); + xmldoc->LoadXml (ref new String (lpXmlString)); + auto toast = ref new Toast (xmldoc); + toast->Activated += ref new Windows::Foundation::TypedEventHandler < + Windows::UI::Notifications::ToastNotification ^, + Platform::Object ^ + > ([=] (Windows::UI::Notifications::ToastNotification ^sender, Platform::Object ^args) { + if (pfCallback) pfCallback (pCustom); + }); + notifier->Show (toast); + return S_OK; + } + catch_lasterr (&hr, lpExceptMsg); + return hr; +} + + diff --git a/notice/notice.h b/notice/notice.h index ca66229..348e25e 100644 --- a/notice/notice.h +++ b/notice/notice.h @@ -18,7 +18,7 @@ extern "C" #endif #ifdef __cplusplus #define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_ -#ifndef PKGMGR_EXPORTS +#ifndef NOTICE_EXPORTS #define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_ #else #define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) @@ -27,6 +27,29 @@ extern "C" #define _DEFAULT_INIT_VALUE_(_init_value_) #define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) #endif + typedef void (*NOTICE_ACTIVECALLBACK) (void *pCustom); + // 参考:https://learn.microsoft.com/zh-cn/previous-versions/windows/apps/hh761494(v=win.10) + // 通过 Toast 通知名来获取 XML 模板。 + // 不符合会返回一个默认模板(只会有一个 text 节点。根据需要的话可以自己添加) + // 注意:返回的指针要自己 free 释放 + NOTICE_API LPWSTR GetToastNoticeXml (LPCWSTR lpTemplateName); + // 获取一个简单的 Toast 通知 XML 文档。第一个参数是必须的。第二个参数为图片 URI(file:///)。 + // 第二个参数如果为 NULL 或去掉首尾空的长度为 0 的文本则不会使用带图片的模板。 + // 注意:返回的指针要自己通过 free 释放 + NOTICE_API LPWSTR GenerateSimpleToastNoticeXml (LPCWSTR lpText, LPCWSTR lpImagePath); + // 获取一个简单的 Toast 通知 XML 文档。第一个参数是必须的。第三个参数为图片 URI(file:///)。 + // 第三个参数如果为 NULL 或去掉首尾空的长度为 0 的文本则不会使用带图片的模板。 + // 第二个参数可以为 NULL 或空文本。当为空时不会使用相关模板 + // 注意:返回的指针要自己通过 free 释放 + NOTICE_API LPWSTR GenerateSimpleToastNoticeXml2 (LPCWSTR lpTitle, LPCWSTR lpText, LPCWSTR lpImagePath); + // 创建并显示一个 Toast 通知 + // 参数1 为非必须项,这意味着可以传入 NULL 或空文本。但是建议必须填。桌面应用 + // 必须在开始菜单快捷方式储存处创建一个含有 AppUserModelID 的快捷方式才能使用 Toast 通知。而这个限制 + // 在 Windows 10 已经去除。 + // pfCallback 为点击 Toast 通知本体后触发的回调函数。注意:仅运行期才能用,且不一定会调用成功 + // pCustom 可以传入自定义内容并在回调中使用 + // lpExceptMsg 返回异常信息。获取到的指针必须由 free 释放。 + NOTICE_API HRESULT CreateToastNoticeFromXmlDocument (LPCWSTR lpIdName, LPCWSTR lpXmlString, NOTICE_ACTIVECALLBACK pfCallback, void *pCustom, LPWSTR *lpExceptMsg); #ifdef _DEFAULT_INIT_VALUE_ #undef _DEFAULT_INIT_VALUE_ diff --git a/notice/notice.vcxproj b/notice/notice.vcxproj index c46e2d1..d690f34 100644 --- a/notice/notice.vcxproj +++ b/notice/notice.vcxproj @@ -32,9 +32,7 @@ false - - - + @@ -89,19 +87,11 @@ + - - - - - - 杩欏彴璁$畻鏈轰笂缂哄皯姝ら」鐩紩鐢ㄧ殑 NuGet 绋嬪簭鍖呫備娇鐢ㄢ淣uGet 绋嬪簭鍖呰繕鍘熲濆彲涓嬭浇杩欎簺绋嬪簭鍖呫傛湁鍏虫洿澶氫俊鎭紝璇峰弬瑙 http://go.microsoft.com/fwlink/?LinkID=322105銆傜己灏戠殑鏂囦欢鏄 {0}銆 - - - \ No newline at end of file diff --git a/notice/notice.vcxproj.filters b/notice/notice.vcxproj.filters index 0ea694c..b3775e9 100644 --- a/notice/notice.vcxproj.filters +++ b/notice/notice.vcxproj.filters @@ -38,8 +38,8 @@ 澶存枃浠 - - - + + 澶存枃浠 + \ No newline at end of file diff --git a/notice/nstring.h b/notice/nstring.h new file mode 100644 index 0000000..bf3d12e --- /dev/null +++ b/notice/nstring.h @@ -0,0 +1,457 @@ +#pragma once +#include +#include +#include +namespace l0km +{ + template , typename AL = std::allocator > inline std::basic_string toupper (const std::basic_string &src) + { + std::basic_string dst = src; + static const std::locale loc; + const std::ctype &ctype = std::use_facet > (loc); + for (typename std::basic_string ::size_type i = 0; i < src.size (); ++ i) + { + dst [i] = ctype.toupper (src [i]); + } + return dst; + } + template , typename AL = std::allocator > inline std::basic_string tolower (const std::basic_string &src) + { + std::basic_string dst = src; + static const std::locale loc; + const std::ctype &ctype = std::use_facet > (loc); + for (typename std::basic_string ::size_type i = 0; i < src.size (); ++ i) + { + dst [i] = ctype.tolower (src [i]); + } + return dst; + } + inline char toupper (char ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline char tolower (char ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } + inline wchar_t toupper (wchar_t ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline wchar_t tolower (wchar_t ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } + inline int toupper (int ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline int tolower (int ch) + { + if (ch < -1) return ch; + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } +} +template bool is_blank (ct &ch) +{ + return ch == ct (' ') || ch == ct ('\t') || ch == ct ('\n'); +} +template , typename AL = std::allocator > std::basic_string NormalizeString (const std::basic_string &str, bool upper = false, bool includemidblank = false) +{ + typedef std::basic_string string_type; + string_type result; + if (str.empty ()) return result; + auto begin_it = str.begin (); + auto end_it = str.end (); + while (begin_it != end_it && is_blank (*begin_it)) ++begin_it; + while (end_it != begin_it && is_blank (*(end_it - 1))) --end_it; + bool in_space = false; + for (auto it = begin_it; it != end_it; ++ it) + { + if (is_blank (*it)) + { + if (includemidblank) + { + if (!in_space) + { + result.push_back (E (' ')); + in_space = true; + } + } + else + { + result.push_back (*it); + in_space = true; + } + } + else + { + result.push_back (*it); + in_space = false; + } + } + if (upper) return l0km::toupper (result); + else return l0km::tolower (result); +} +template , typename AL = std::allocator > bool IsNormalizeStringEquals (const std::basic_string &l, const std::basic_string &r, bool includemidblank = false) +{ + auto _local_strlen = [] (const E *p) -> size_t { + size_t cnt = 0; + while (*(p + cnt)) { cnt ++; } + return cnt; + }; + const E *pl = l.c_str (); + const E *pr = r.c_str (); + while (*pl && is_blank (*pl)) ++ pl; + while (*pr && is_blank (*pr)) ++ pr; + const E *el = l.c_str () + _local_strlen (l.c_str ()); + const E *er = r.c_str () + _local_strlen (r.c_str ()); + while (el > pl && is_blank (*(el - 1))) --el; + while (er > pr && is_blank (*(er - 1))) --er; + while (pl < el && pr < er) + { + if (includemidblank) + { + if (is_blank (*pl) && is_blank (*pr)) + { + while (pl < el && is_blank (*pl)) ++pl; + while (pr < er && is_blank (*pr)) ++pr; + continue; + } + else if (is_blank (*pl)) + { + while (pl < el && is_blank (*pl)) ++pl; + continue; + } + else if (is_blank (*pr)) + { + while (pr < er && is_blank (*pr)) ++pr; + continue; + } + } + if (l0km::tolower (*pl) != l0km::tolower (*pr)) return false; + ++ pl; + ++ pr; + } + while (pl < el && is_blank (*pl)) ++ pl; + while (pr < er && is_blank (*pr)) ++ pr; + return pl == el && pr == er; +} +template , typename AL = std::allocator > int64_t NormalizeStringCompare (const std::basic_string &l, const std::basic_string &r, bool includemidblank = false) +{ + auto _local_strlen = [] (const E *p) -> size_t { + size_t cnt = 0; + while (*(p + cnt)) { cnt ++; } + return cnt; + }; + const E *pl = l.c_str (); + const E *pr = r.c_str (); + while (*pl && is_blank (*pl)) ++ pl; + while (*pr && is_blank (*pr)) ++ pr; + const E *el = l.c_str () + _local_strlen (l.c_str ()); + const E *er = r.c_str () + _local_strlen (r.c_str ()); + while (el > pl && is_blank (*(el - 1))) -- el; + while (er > pr && is_blank (*(er - 1))) -- er; + while (pl < el && pr < er) + { + if (includemidblank) + { + if (is_blank (*pl) && is_blank (*pr)) + { + while (pl < el && is_blank (*pl)) ++pl; + while (pr < er && is_blank (*pr)) ++pr; + continue; + } + else if (is_blank (*pl)) + { + while (pl < el && is_blank (*pl)) ++pl; + continue; + } + else if (is_blank (*pr)) + { + while (pr < er && is_blank (*pr)) ++pr; + continue; + } + } + E chl = l0km::tolower (*pl); + E chr = l0km::tolower (*pr); + if (chl != chr) return (int64_t)chl - (int64_t)chr; + ++ pl; + ++ pr; + } + while (pl < el && is_blank (*pl)) ++ pl; + while (pr < er && is_blank (*pr)) ++ pr; + if (pl == el && pr == er) return 0; + if (pl == el) return -1; + if (pr == er) return 1; + return (int64_t)l0km::tolower (*pl) - (int64_t)l0km::tolower (*pr); +} +template bool IsNormalizeStringEquals (const CharT *l, const CharT *r, bool includemidblank = false) +{ + if (!l || !r) return l == r; + auto skip_blank = [] (const CharT *&p) + { + while (*p && is_blank (*p)) ++ p; + }; + const CharT *p1 = l; + const CharT *p2 = r; + skip_blank (p1); + skip_blank (p2); + while (*p1 && *p2) + { + CharT ch1 = l0km::tolower (*p1); + CharT ch2 = l0km::tolower (*p2); + if (ch1 != ch2) return false; + ++ p1; + ++ p2; + if (includemidblank) + { + if (is_blank (*p1) || is_blank (*p2)) + { + skip_blank (p1); + skip_blank (p2); + } + } + } + skip_blank (p1); + skip_blank (p2); + return *p1 == 0 && *p2 == 0; +} +template int64_t NormalizeStringCompare (const CharT *l, const CharT *r, bool includemidblank = false) +{ + if (!l || !r) return l ? 1 : (r ? -1 : 0); + auto skip_blank = [] (const CharT *&p) + { + while (*p && is_blank (*p)) ++ p; + }; + const CharT *p1 = l; + const CharT *p2 = r; + skip_blank (p1); + skip_blank (p2); + while (*p1 && *p2) + { + CharT ch1 = l0km::tolower (*p1); + CharT ch2 = l0km::tolower (*p2); + if (ch1 != ch2) return (ch1 < ch2) ? -1 : 1; + ++ p1; + ++ p2; + if (includemidblank) + { + if (is_blank (*p1) || is_blank (*p2)) + { + skip_blank (p1); + skip_blank (p2); + } + } + } + skip_blank (p1); + skip_blank (p2); + if (*p1 == 0 && *p2 == 0) return 0; + if (*p1 == 0) return -1; + return 1; +} +template , typename AL = std::allocator > bool IsNormalizeStringEmpty (const std::basic_string &str) +{ + return IsNormalizeStringEquals (str, std::basic_string ()); +} +template , typename AL = std::allocator > std::basic_string StringTrim (const std::basic_string &str, bool includemidblank = false) +{ + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + if (str.empty ()) return string_type (); + size_type first = 0; + size_type last = str.size (); + while (first < last && is_blank (str [first])) ++first; + while (last > first && is_blank (str [last - 1])) --last; + if (first == last) return string_type (); + string_type result; + result.reserve (last - first); + bool in_space = false; + for (size_type i = first; i < last; ++ i) + { + if (is_blank (str [i])) + { + if (includemidblank) + { + if (!in_space) + { + result.push_back (E (' ')); + in_space = true; + } + } + else + { + result.push_back (str [i]); + in_space = true; + } + } + else + { + result.push_back (str [i]); + in_space = false; + } + } + return result; +} +template , typename AL = std::allocator > size_t GetNormalizeStringLength (const std::basic_string &str, bool includemidblank = false) +{ + typedef typename std::basic_string ::size_type size_type; + if (str.empty ()) return 0; + size_type first = 0, last = str.size (); + while (first < last && is_blank (str [first])) ++first; + while (last > first && is_blank (str [last - 1])) --last; + if (first == last) return 0; + size_t length = 0; + bool in_space = false; + for (size_type i = first; i < last; ++i) + { + if (is_blank (str [i])) + { + if (includemidblank) + { + if (!in_space) + { + ++ length; + in_space = true; + } + } + else + { + ++ length; + in_space = true; + } + } + else + { + ++ length; + in_space = false; + } + } + return length; +} +namespace std +{ + + template , typename al = std::allocator > class basic_nstring: public std::basic_string + { + bool default_upper = false, default_include_blank_in_str = false; + public: + using base = std::basic_string ; + using derive = std::basic_nstring ; + using typename base::size_type; + using typename base::value_type; + using base::base; + basic_nstring (): base (), default_upper (false), default_include_blank_in_str (false) {} + basic_nstring (const ct *pStr): base (pStr), default_upper (false), default_include_blank_in_str (false) {} + basic_nstring (const base &str): base (str) {} + basic_nstring (base &&str): base (std::move (str)) {} + basic_nstring (const ct *data, size_type count): base (data, count), default_upper (false), default_include_blank_in_str (false) {} + template basic_nstring (const ct (&arr) [N]) : base (arr, N) {} + template basic_nstring (InputIt first, InputIt last): base (first, last), default_upper (false), default_include_blank_in_str (false) {} + bool upper_default () const { return this->default_upper; } + bool upper_default (bool value) { return this->default_upper = value; } + bool include_blank_in_str_middle () const { return this->default_include_blank_in_str; } + bool include_blank_in_str_middle (bool value) { return this->default_include_blank_in_str = value; } + base normalize (bool upper, bool includemidblank) const + { + return NormalizeString (*this, upper, includemidblank); + } + base normalize (bool upper) const + { + return this->normalize (upper, default_include_blank_in_str); + } + base normalize () const { return this->normalize (default_upper); } + base upper (bool includemidblank) const + { + return NormalizeString (*this, true, includemidblank); + } + base upper () const { return this->upper (default_include_blank_in_str); } + base lower (bool includemidblank) const + { + return NormalizeString (*this, false, includemidblank); + } + base lower () const { return this->lower (default_include_blank_in_str); } + base trim (bool includemidblank) const + { + return StringTrim (*this, includemidblank); + } + base trim () const { return this->trim (default_include_blank_in_str); } + size_t length (bool includemidblank) const { return GetNormalizeStringLength (*this, includemidblank); } + size_t length () const { return length (default_include_blank_in_str); } + bool empty () const + { + return IsNormalizeStringEmpty (*this); + } + bool equals (const base &another, bool includemidblank) const + { + return IsNormalizeStringEquals (*this, another, includemidblank); + } + bool equals (const base &another) const { return equals (another, default_include_blank_in_str); } + int64_t compare (const base &another, bool includemidblank) const + { + return NormalizeStringCompare (*this, another, includemidblank); + } + int64_t compare (const base &another) const { return compare (another, default_include_blank_in_str); } + base &string () { return *this; } + base to_string (bool upper, bool includemidblank) const { return this->normalize (upper, includemidblank); } + base to_string (bool upper) const { return this->normalize (upper, default_include_blank_in_str); } + base to_string () const { return this->normalize (default_upper); } + bool operator == (const base &other) const { return equals (other, false); } + bool operator != (const base &other) const { return !equals (other, false); } + bool operator < (const base &other) const { return compare (other, false) < 0; } + bool operator > (const base &other) const { return compare (other, false) > 0; } + bool operator <= (const base &other) const { return compare (other, false) <= 0; } + bool operator >= (const base &other) const { return compare (other, false) >= 0; } + int64_t operator - (const base &other) const { return compare (other, false); } + template , typename AL = std::allocator > + static bool equals (const std::basic_string &l, const std::basic_string &r, bool remove_mid_blank = false) + { + return IsNormalizeStringEquals (l, r, remove_mid_blank); + } + template , typename AL = std::allocator > + static int64_t compare (const std::basic_string &l, const std::basic_string &r, bool remove_mid_blank = false) + { + return NormalizeStringCompare (l, r, remove_mid_blank); + } + template , typename AL = std::allocator > + static std::basic_string normalize (const std::basic_string &str, bool to_upper = false, bool remove_mid_blank = false) + { + return NormalizeString (str, to_upper, remove_mid_blank); + } + template , typename AL = std::allocator > + static std::basic_string trim (const std::basic_string &str, bool remove_mid_blank = false) + { + return StringTrim (str, remove_mid_blank); + } + template , typename AL = std::allocator > + static size_t length (const std::basic_string &str, bool remove_mid_blank = false) + { + return GetNormalizeStringLength (str, remove_mid_blank); + } + template , typename AL = std::allocator > + static bool empty (const std::basic_string &str) + { + return IsNormalizeStringEmpty (str); + } + template , typename AL = std::allocator > + static std::basic_nstring to_nstring (std::basic_string &str) { return std::basic_nstring (str); } + template , typename AL = std::allocator > + static std::basic_nstring toupper (const std::basic_nstring &str) { return l0km::toupper (str); } + template , typename AL = std::allocator > + static std::basic_nstring tolower (const std::basic_nstring &str) { return l0km::tolower (str); } + }; + + typedef basic_nstring nstring; + typedef basic_nstring wnstring; +} \ No newline at end of file diff --git a/notice/packages.config b/notice/packages.config deleted file mode 100644 index c2da1c1..0000000 --- a/notice/packages.config +++ /dev/null @@ -1,4 +0,0 @@ -锘 - - - \ No newline at end of file diff --git a/notice/stdafx.h b/notice/stdafx.h index 0a55300..9fd51c8 100644 --- a/notice/stdafx.h +++ b/notice/stdafx.h @@ -28,11 +28,8 @@ #include #include #include - +#using using namespace Microsoft::WRL; using namespace ABI::Windows::UI::Notifications; using namespace ABI::Windows::Data::Xml::Dom; using namespace Microsoft::WRL::Wrappers; - -#include -#include \ No newline at end of file diff --git a/pkgmgr/pkgmgr.cpp b/pkgmgr/pkgmgr.cpp index 2e5f9e6..7c62204 100644 --- a/pkgmgr/pkgmgr.cpp +++ b/pkgmgr/pkgmgr.cpp @@ -142,7 +142,9 @@ HRESULT AddAppxPackageFromURI (LPCWSTR lpPkgFileUri, PCREGISTER_PACKAGE_DEFENDEN } } if (depuris->Size > 0) depuris = nullptr; - auto ope = pkgmgr->AddPackageAsync (ref new Uri (ref new String (lpPkgFileUri)), depuris, (DeploymentOptions)dwDeployOption); + auto pkguri = ref new Uri (ref new String (lpPkgFileUri)); + auto pkguristr = pkguri->ToString (); + auto ope = pkgmgr->AddPackageAsync (pkguri, depuris, (DeploymentOptions)dwDeployOption); return ope; }, pfCallback, pCustom, pErrorCode, pDetailMsg); } @@ -426,7 +428,7 @@ HRESULT RegisterAppxPackageByPath (LPCWSTR lpManifestPath, PCREGISTER_PACKAGE_DE { std::wstring fullpath = GetFullPathName (lpManifestPath ? lpManifestPath : L""); if (fullpath.empty ()) fullpath = lpManifestPath ? lpManifestPath : L""; - return RegisterAppxPackageByPath (fullpath.c_str (), alpDependencyUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg); + return RegisterAppxPackageByUri (fullpath.c_str (), alpDependencyUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg); } [MTAThread] HRESULT RegisterAppxPackageByFullName (LPCWSTR lpPackageFullName, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg) @@ -527,7 +529,7 @@ HRESULT StageAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDEN { std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L""); if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L""; - return StageAppxPackageFromPath (fullpath.c_str (), alpDepUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg); + return StageAppxPackageFromURI (fullpath.c_str (), alpDepUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg); } [MTAThread] HRESULT StageAppxUserData (LPCWSTR lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg) diff --git a/pkgmgr/pkgmgr.rc b/pkgmgr/pkgmgr.rc new file mode 100644 index 0000000..1428052 Binary files /dev/null and b/pkgmgr/pkgmgr.rc differ diff --git a/pkgmgr/pkgmgr.vcxproj b/pkgmgr/pkgmgr.vcxproj index a291e39..77b3848 100644 --- a/pkgmgr/pkgmgr.vcxproj +++ b/pkgmgr/pkgmgr.vcxproj @@ -88,9 +88,13 @@ + + + + \ No newline at end of file diff --git a/pkgmgr/pkgmgr.vcxproj.filters b/pkgmgr/pkgmgr.vcxproj.filters index b2849fa..541b8c6 100644 --- a/pkgmgr/pkgmgr.vcxproj.filters +++ b/pkgmgr/pkgmgr.vcxproj.filters @@ -38,5 +38,13 @@ 澶存枃浠 + + 澶存枃浠 + + + + + 璧勬簮鏂囦欢 + \ No newline at end of file diff --git a/pkgmgr/resource.h b/pkgmgr/resource.h new file mode 100644 index 0000000..e1ea71a --- /dev/null +++ b/pkgmgr/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pkgmgr.rc + +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/pkgread/pkgread.rc b/pkgread/pkgread.rc index 66d27f3..cc870e1 100644 Binary files a/pkgread/pkgread.rc and b/pkgread/pkgread.rc differ