The encapsulation of the package manager API has been completed (only a portion of the API has been encapsulated).

This commit is contained in:
Bruce
2025-11-08 23:50:27 +08:00
parent 1b30f3caa5
commit 978f9b6a45
36 changed files with 2855 additions and 40 deletions
+30
View File
@@ -0,0 +1,30 @@
========================================================================
动态链接库:pkgmgr 项目概述
========================================================================
应用程序向导已为您创建了此 pkgmgr DLL。
本文件概要介绍组成 pkgmgr 应用程序的每个文件的内容。
pkgmgr.vcxproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
pkgmgr.vcxproj.filters
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
pkgmgr.cpp
这是主 DLL 源文件。
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
这些文件用于生成名为 pkgmgr.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
/////////////////////////////////////////////////////////////////////////////
+19
View File
@@ -0,0 +1,19 @@
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
+629
View File
@@ -0,0 +1,629 @@
// pkgmgr.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "pkgmgr.h"
#include "raii.h"
#include "version.h"
#undef GetFullPathName
std::wstring GetFullPathName (const std::wstring &lpFileName)
{
if (lpFileName.empty ()) return L"";
DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
if (length == 0) return L"";
std::vector <WCHAR> buffer (length + 1, L'\0');
DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
if (result == 0) return L"";
return std::wstring (buffer.data (), result);
}
std::wstring g_swExceptionCode = L"";
std::wstring g_swExceptionDetail = L"";
struct destruct
{
std::function <void ()> endtask = nullptr;
destruct (std::function <void ()> pfunc): endtask (pfunc) {}
~destruct () { if (endtask) endtask (); }
};
static std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP)
{
if (str.empty ()) return std::wstring ();
int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0);
if (len == 0) return std::wstring ();
std::wstring wstr (len - 1, L'\0');
MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len);
return wstr;
}
using onprogress = AsyncOperationProgressHandler <DeploymentResult ^, DeploymentProgress>;
using onprogresscomp = AsyncOperationWithProgressCompletedHandler <DeploymentResult ^, DeploymentProgress>;
using progressopt = IAsyncOperationWithProgress <DeploymentResult ^, DeploymentProgress> ^;
template <typename TAsyncOpCreator> HRESULT RunPackageManagerOperation (TAsyncOpCreator asyncCreator, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
if (pErrorCode) *pErrorCode = nullptr;
if (pDetailMsg) *pDetailMsg = nullptr;
try
{
HANDLE hCompEvt = nullptr;
destruct closeevt ([&hCompEvt] () {
if (hCompEvt) { CloseHandle (hCompEvt); hCompEvt = nullptr; }
});
hCompEvt = CreateEventExW (nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (!hCompEvt) return E_FAIL;
auto depopt = asyncCreator ();
depopt->Progress = ref new onprogress ([pfCallback, pCustom] (progressopt operation, DeploymentProgress progress) {
if (pfCallback) pfCallback ((DWORD)progress.percentage, pCustom);
});
depopt->Completed = ref new onprogresscomp ([&hCompEvt] (progressopt, AsyncStatus) {
SetEvent (hCompEvt);
});
WaitForSingleObject (hCompEvt, INFINITE);
switch (depopt->Status)
{
case AsyncStatus::Completed:
return S_OK;
case AsyncStatus::Error:
{
auto depresult = depopt->GetResults ();
auto errorcode = depopt->ErrorCode;
HResult hr = errorcode;
String ^errstr = Exception::CreateException (errorcode.Value)->ToString ();
g_swExceptionCode += errstr && errstr->Data () ? errstr->Data () : L"";
g_swExceptionDetail += depresult->ErrorText->Data ();
if (pErrorCode) *pErrorCode = _wcsdup (g_swExceptionCode.c_str ());
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (HRESULT)errorcode.Value;
}
case AsyncStatus::Canceled:
g_swExceptionDetail = L"Installation Canceled";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_ABORT;
case AsyncStatus::Started:
g_swExceptionDetail = L"Installation is Running";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_PENDING;
}
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[MTAThread]
HRESULT AddAppxPackageFromURI (LPCWSTR lpPkgFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
auto depuris = ref new Platform::Collections::Vector <Uri ^> ();
if (alpDepUrlList)
{
for (size_t i = 0; i < alpDepUrlList->dwSize; i ++)
{
auto &pstr = alpDepUrlList->alpDepUris [i];
try
{
if (pstr && *pstr)
{
auto depuristr = ref new String (pstr);
Uri ^duri = nullptr;
try { duri = ref new Uri (depuristr); }
catch (Exception ^e)
{
try
{
std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
duri = ref new Uri (ref new String (fullpath.c_str ()));
}
catch (Exception ^e) { continue; }
}
depuris->Append (duri);
}
}
catch (Exception ^e) { continue; }
}
}
if (depuris->Size > 0) depuris = nullptr;
auto ope = pkgmgr->AddPackageAsync (ref new Uri (ref new String (lpPkgFileUri)), depuris, (DeploymentOptions)dwDeployOption);
return ope;
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L"");
if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L"";
return AddAppxPackageFromURI (fullpath.c_str (), alpDepUrlList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
std::wstring WinRTStringToStdString (String ^pstr)
{
try { if (!pstr) return L""; return (pstr->Data () ? pstr->Data () : L""); }
catch (...) {} return L"";
}
#define PlatformGetStringValue(mpObj, _prop_) \
([&] () -> std::wstring { \
auto strptr = (mpObj)->_prop_; \
return WinRTStringToStdString (strptr); \
}) ()
void SidToAccountName (const std::wstring &sidString, std::wstring &stringSid)
{
PSID sid = nullptr;
raii lrel ([&sid] () {
if (sid) LocalFree (sid);
sid = nullptr;
});
if (ConvertStringSidToSidW (sidString.c_str (), &sid))
{
DWORD nameCharCount = 0;
DWORD domainNameCharCount = 0;
SID_NAME_USE sidType;
LookupAccountSidW (nullptr, sid, nullptr, &nameCharCount, nullptr, &domainNameCharCount, &sidType);
std::vector <WCHAR> namebuf (nameCharCount + 1);
std::vector <WCHAR> domainNameBuf (domainNameCharCount + 1);
ZeroMemory (namebuf.data (), (nameCharCount + 1) * sizeof (WCHAR));
ZeroMemory (domainNameBuf.data (), (domainNameCharCount + 1) * sizeof (WCHAR));
if (LookupAccountSidW (nullptr, sid, namebuf.data (), &nameCharCount, domainNameBuf.data (), &domainNameCharCount, &sidType))
{
stringSid = domainNameBuf.data ();
stringSid += stringSid + L"\\" + namebuf.data ();
}
}
if (stringSid.length () == 0) stringSid = sidString;
}
struct pkg_info
{
struct identity
{
std::wstring name = L"";
std::wstring publisher = L"";
std::wstring fullname = L"";
std::wstring familyname = L"";
std::wstring resourceid = L"";
std::wstring publisherid = L"";
uint16_t architecture = -1;
Version version;
} id;
struct properities
{
std::wstring displayname = L"";
std::wstring description = L"";
std::wstring publisher = L"";
std::wstring logo = L"";
bool framework = false;
bool resource_package = false;
} prop;
bool bundle = false;
bool development_mode = false;
std::wstring installlocation = L"";
std::wstring users = L"";
std::wstring sids = L"";
std::vector <pkg_info> dependencies;
static pkg_info parse (Windows::ApplicationModel::Package ^pkg, Windows::Management::Deployment::PackageManager ^mgr)
{
pkg_info pi;
if (!pkg) throw ref new InvalidArgumentException ("No package found.");
#define WAPParseSetValue(_left_part_, _right_part_, _default_value_) \
do { try { _left_part_ = _right_part_; } catch (...) { _left_part_ = _default_value_; } } while (false)
#define WAPParseSetStringValue(_left_part_, _right_part_) \
WAPParseSetValue (_left_part_, WinRTStringToStdString (_right_part_), L"")
WAPParseSetStringValue (pi.id.name, pkg->Id->Name);
WAPParseSetStringValue (pi.id.publisher, pkg->Id->Publisher);
WAPParseSetStringValue (pi.id.fullname, pkg->Id->FullName);
WAPParseSetStringValue (pi.id.familyname, pkg->Id->FamilyName);
WAPParseSetStringValue (pi.id.publisherid, pkg->Id->PublisherId);
WAPParseSetStringValue (pi.id.resourceid, pkg->Id->ResourceId);
try { pi.id.version = version (pkg->Id->Version.Major, pkg->Id->Version.Minor, pkg->Id->Version.Build, pkg->Id->Version.Revision); } catch (...) {}
WAPParseSetValue (pi.id.architecture, (WORD)pkg->Id->Architecture, (WORD)-1);
WAPParseSetStringValue (pi.prop.displayname, pkg->DisplayName);
WAPParseSetStringValue (pi.prop.description, pkg->Description);
WAPParseSetStringValue (pi.prop.publisher, pkg->PublisherDisplayName);
WAPParseSetStringValue (pi.prop.logo, pkg->Logo->ToString ());
WAPParseSetValue (pi.prop.framework, pkg->IsFramework, false);
WAPParseSetValue (pi.prop.resource_package, pkg->IsResourcePackage, false);
WAPParseSetValue (pi.bundle, pkg->IsBundle, false);
WAPParseSetValue (pi.development_mode, pkg->IsDevelopmentMode, false);
WAPParseSetStringValue (pi.installlocation, pkg->InstalledLocation->Path);
try
{
size_t i = 0;
auto users = mgr->FindUsers (pkg->Id->FullName);
for (auto it : users)
{
{
std::wstring sid = L"";
SidToAccountName (it->UserSecurityId->Data (), sid);
if (i) pi.users += L';';
pi.users += sid;
}
{
std::wstring sid;
WAPParseSetStringValue (sid, it->UserSecurityId);
if (i) pi.sids += L';';
pi.users += sid;
}
i ++;
}
}
catch (...) {}
try
{
auto deps = pkg->Dependencies;
for (auto it : deps)
{
auto deppkg = pkg_info::parse (it, mgr);
deppkg.dependencies.clear ();
pi.dependencies.push_back (deppkg);
}
}
catch (...) {}
return pi;
#ifdef WAPParseSetStringValue
#undef WAPParseSetStringValue
#endif
#ifdef WAPParseSetValue
#undef WAPParseSetValue
#endif
}
// 返回的反而是缓冲区,因为是柔性结构体要动态申请。这个方法很常用
void to_c_struct (std::vector <BYTE> &bytesret) const
{
bytesret.clear ();
bytesret.resize (sizeof (FIND_PACKAGE_INFO) * (this->dependencies.size () + 1));
FIND_PACKAGE_INFO &fpi = *(FIND_PACKAGE_INFO *)bytesret.data ();
fpi.piIdentity.lpFamilyName = this->id.familyname.c_str ();
fpi.piIdentity.lpFullName = this->id.fullname.c_str ();
fpi.piIdentity.lpName = this->id.name.c_str ();
fpi.piIdentity.lpPublisher = this->id.publisher.c_str ();
fpi.piIdentity.lpPublisherId = this->id.publisherid.c_str ();
fpi.piIdentity.lpResourceId = this->id.resourceid.c_str ();
fpi.piIdentity.qwVersion = this->id.version.data ();
fpi.piIdentity.wProcessArchitecture = this->id.architecture;
fpi.piProperties.bIsBundle = this->bundle;
fpi.piProperties.bIsDevelopmentMode = this->development_mode;
fpi.piProperties.bIsFramework = this->prop.framework;
fpi.piProperties.bIsResourcePackage = this->prop.resource_package;
fpi.piProperties.lpDescription = this->prop.description.c_str ();
fpi.piProperties.lpDisplayName = this->prop.displayname.c_str ();
fpi.piProperties.lpLogoUri = this->prop.logo.c_str ();
fpi.piProperties.lpPublisher = this->prop.publisher.c_str ();
fpi.dwDependencesSize = this->dependencies.size ();
fpi.lpInstallLocation = this->installlocation.c_str ();
fpi.lpUsers = this->users.c_str ();
FIND_PACKAGE_INFO *deps = (FIND_PACKAGE_INFO *)&fpi.ullBuffer;
for (size_t i = 0; i < this->dependencies.size (); i ++)
{
std::vector <BYTE> depbytes;
this->dependencies [i].to_c_struct (depbytes);
deps [i] = *(FIND_PACKAGE_INFO *)depbytes.data ();
}
}
};
[STAThread]
HRESULT FindAppxPackageByCallback (std::function <void (pkg_info &)> pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
auto pkgmgr = ref new PackageManager ();
auto pkgarr = pkgmgr->FindPackages ();
for (auto pkg : pkgarr)
{
auto pkginfo = pkg_info::parse (pkg, pkgmgr);
if (pfCallback) pfCallback (pkginfo);
}
return S_OK;
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return FindAppxPackageByCallback ([&pCustom, &pfCallback] (pkg_info &pi) {
std::vector <BYTE> bytes;
pi.to_c_struct (bytes);
if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
}, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT RemoveAppxPackage (LPCWSTR lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
return pkgmgr->RemovePackageAsync (ref new String (lpPkgFullName));
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT CleanupAppxPackage (LPCWSTR lpPkgName, LPCWSTR lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
return pkgmgr->CleanupPackageForUserAsync (ref new String (lpPkgName), ref new String (lpUserSID));
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT RegisterAppxPackageByUri (LPCWSTR lpManifestUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
auto depuris = ref new Platform::Collections::Vector <Uri ^> ();
if (alpDependencyUriList)
{
for (size_t i = 0; i < alpDependencyUriList->dwSize; i ++)
{
auto &pstr = alpDependencyUriList->alpDepUris [i];
try
{
if (pstr && *pstr)
{
auto depuristr = ref new String (pstr);
Uri ^duri = nullptr;
try { duri = ref new Uri (depuristr); }
catch (Exception ^e)
{
try
{
std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
duri = ref new Uri (ref new String (fullpath.c_str ()));
}
catch (Exception ^e) { continue; }
}
depuris->Append (duri);
}
}
catch (Exception ^e) { continue; }
}
}
if (depuris->Size > 0) depuris = nullptr;
return pkgmgr->RegisterPackageAsync (ref new Uri (ref new String (lpManifestUri)), depuris, (DeploymentOptions)dwDeployOption);
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT RegisterAppxPackageByPath (LPCWSTR lpManifestPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
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);
}
[MTAThread]
HRESULT RegisterAppxPackageByFullName (LPCWSTR lpPackageFullName, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
auto depuris = ref new Platform::Collections::Vector <String ^> ();
if (alpDepFullNameList)
{
for (size_t i = 0; i < alpDepFullNameList->dwSize; i ++)
{
auto &pstr = alpDepFullNameList->alpDepUris [i];
try { if (pstr && *pstr) depuris->Append (ref new String (pstr)); }
catch (Exception ^e) { continue; }
}
}
if (depuris->Size > 0) depuris = nullptr;
return pkgmgr->RegisterPackageByFullNameAsync (ref new String (lpPackageFullName), depuris, (DeploymentOptions)dwDeployOption);
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
template <typename TFunction> HRESULT ExecPackageManagerFunctionNoReturn (TFunction func, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
func ();
return S_OK;
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
HRESULT SetAppxPackageStatus (LPCWSTR lpPackageFullName, DWORD dwStatus, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return ExecPackageManagerFunctionNoReturn ([=] () {
auto pkgmgr = ref new PackageManager ();
pkgmgr->SetPackageState (ref new String (lpPackageFullName), (Windows::Management::Deployment::PackageState)dwStatus);
}, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT StageAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
auto depuris = ref new Platform::Collections::Vector <Uri ^> ();
if (alpDepUriList)
{
for (size_t i = 0; i < alpDepUriList->dwSize; i ++)
{
auto &pstr = alpDepUriList->alpDepUris [i];
try
{
if (pstr && *pstr)
{
auto depuristr = ref new String (pstr);
Uri ^duri = nullptr;
try { duri = ref new Uri (depuristr); }
catch (Exception ^e)
{
try
{
std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
duri = ref new Uri (ref new String (fullpath.c_str ()));
}
catch (Exception ^e) { continue; }
}
depuris->Append (duri);
}
}
catch (Exception ^e) { continue; }
}
}
if (depuris->Size > 0) depuris = nullptr;
return pkgmgr->StagePackageAsync (ref new Uri (ref new String (lpFileUri)), depuris, (DeploymentOptions)dwDeployOption);
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT StageAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
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);
}
[MTAThread]
HRESULT StageAppxUserData (LPCWSTR lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
return pkgmgr->StageUserDataAsync (ref new String (lpPackageFullName));
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT UpdateAppxPackageFromURI (LPCWSTR lpPkgFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
return RunPackageManagerOperation ([=] () {
auto pkgmgr = ref new PackageManager ();
auto depuris = ref new Platform::Collections::Vector <Uri ^> ();
if (alpDepUrlList)
{
for (size_t i = 0; i < alpDepUrlList->dwSize; i ++)
{
auto &pstr = alpDepUrlList->alpDepUris [i];
try
{
if (pstr && *pstr)
{
auto depuristr = ref new String (pstr);
Uri ^duri = nullptr;
try { duri = ref new Uri (depuristr); }
catch (Exception ^e)
{
try
{
std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
duri = ref new Uri (ref new String (fullpath.c_str ()));
}
catch (Exception ^e) { continue; }
}
depuris->Append (duri);
}
}
catch (Exception ^e) { continue; }
}
}
if (depuris->Size > 0) depuris = nullptr;
return pkgmgr->UpdatePackageAsync (ref new Uri (ref new String (lpPkgFileUri)), depuris, (DeploymentOptions)dwDeployOption);
}, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[MTAThread]
HRESULT UpdateAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L"");
if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L"";
return UpdateAppxPackageFromURI (fullpath.c_str (), alpDepUrlList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
}
[STAThread]
HRESULT FindAppxPackage (LPCWSTR lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
auto pkgmgr = ref new PackageManager ();
auto pkg = pkgmgr->FindPackage (ref new String (lpPackageFullName));
auto pkginfo = pkg_info::parse (pkg, pkgmgr);
std::vector <BYTE> bytes;
pkginfo.to_c_struct (bytes);
if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
return S_OK;
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
[STAThread]
LPCWSTR GetPackageManagerLastErrorCode () { return g_swExceptionCode.c_str (); }
[STAThread]
LPCWSTR GetPackageManagerLastErrorDetailMessage () { return g_swExceptionDetail.c_str (); }
+192
View File
@@ -0,0 +1,192 @@
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PKGMGR_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// PKGMGR_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef PKGMGR_EXPORTS
#define PKGMGR_API __declspec(dllexport)
#else
#define PKGMGR_API __declspec(dllimport)
#endif
// 这里的 API 常用“Appx”在函数名中,此举是为了防止与其他类似的函数名混淆。
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
#ifndef PKGMGR_EXPORTS
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
#else
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
#endif
#else
#define _DEFAULT_INIT_VALUE_(_init_value_)
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
#endif
// 进度回调。pCustom 可以传入自定义内容
typedef void (*PKGMRR_PROGRESSCALLBACK) (DWORD dwProgress, void *pCustom);
#define PKGMGR_RESULT_OK S_OK
#define PKGMGR_RESULT_ERROR E_FAIL
#define PKGMGR_RESULT_CANCEL E_ABORT
#define PKGMGR_RESULT_STARTED E_PENDING
typedef struct _REGISTER_PACKAGE_DEFENDENCIES
{
DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
LPWSTR alpDepUris [1];
} REGISTER_PACKAGE_DEFENDENCIES, *PREGISTER_PACKAGE_DEFENDENCIES;
typedef const REGISTER_PACKAGE_DEFENDENCIES CREGISTER_PACKAGE_DEFENDENCIES, *PCREGISTER_PACKAGE_DEFENDENCIES;
// 下面值与 Windows::Management::Deployment::DeploymentOptions 一一对应。由于需要写成 API,所以
// 只能如此。
// 可查阅文档 https://learn.microsoft.com/zh-cn/uwp/api/windows.management.deployment.deploymentoptions?view=winrt-26100
// 设置此选项时,应用将在开发模式下安装。 有关开发模式的信息,请参阅 备注。
// 使用此选项可启用关键应用开发方案。不能将此选项与捆绑包结合使用。
// 如果将此选项与捆绑包一起使用,调用将返回ERROR_INSTALL_FAILED。
#define DEPOLYOPTION_FORCE_APP_SHUTDOWN 0x00000001
// 如果当前正在使用此包或依赖于此包的任何包,则会强制关闭与该包关联的进程,以便可以继续注册。
#define DEPOLYOPTION_DEVELOPMENT_MODE 0x00000002
// 设置此选项时,将指示应用跳过资源适用性检查。 这会有效地暂存或注册用户传递给 命令的所有资源包,
// 这会强制对捆绑包中包含的所有包具有适用性。 如果用户传入捆绑包,则将注册所有包含的资源包。
// 仅限 Windows。
#define DEPOLYOPTION_INSTALL_ALL_RESOURCES 0x00000020
// 使用默认行为。
#define DEPOLYOPTION_NONE 0x00000000
// 安装一个 Appx/AppxBundle/Msix/MsixBundle 包
// 注意:传入的文件路径为 DOS/NT 风格。如:C:\Windows\...
// 该函数类似于 PowerShell 的 Add-AppxPackage
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 安装一个 Appx/AppxBundle/Msix/MsixBundle 包
// 注意:传入的文件路径为 URI。
// 该函数类似于 PowerShell 的 Add-AppxPackage
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT AddAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
typedef struct _FIND_PACKAGE_ID
{
UINT64 qwVersion _DEFAULT_INIT_VALUE_ (0);
// x86: 0
// x64: 9
// Arm: 5
// Neutral: 11
// Arm64: 12
// Unknown: 65535(-1)
WORD wProcessArchitecture _DEFAULT_INIT_VALUE_ ((WORD)-1);
WORD wPadding [3];
LPCWSTR lpName _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpFullName _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpFamilyName _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpPublisherId _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpResourceId _DEFAULT_INIT_VALUE_ (NULL);
} FIND_PACKAGE_ID, *PFIND_PACKAGE_ID;
typedef struct _FIND_PACKAGE_PROPERTIES
{
LPCWSTR lpDisplayName _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpDescription _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL);
LPCWSTR lpLogoUri _DEFAULT_INIT_VALUE_ (NULL);
BOOL bIsFramework _DEFAULT_INIT_VALUE_ (FALSE);
BOOL bIsResourcePackage _DEFAULT_INIT_VALUE_ (FALSE);
BOOL bIsBundle _DEFAULT_INIT_VALUE_ (FALSE);
BOOL bIsDevelopmentMode _DEFAULT_INIT_VALUE_ (FALSE);
} FIND_PACKAGE_PROPERTIES, *PFIND_PACKAGE_PROPERTIES;
typedef struct _FIND_PACKAGE_INFO
{
FIND_PACKAGE_ID piIdentity;
FIND_PACKAGE_PROPERTIES piProperties;
LPCWSTR lpInstallLocation _DEFAULT_INIT_VALUE_ (NULL);
// 多个用户由 ";" 分隔
LPCWSTR lpUsers _DEFAULT_INIT_VALUE_ (NULL);
// 多个用户由 ";" 分隔
LPCWSTR lpSIDs _DEFAULT_INIT_VALUE_ (NULL);
DWORD dwDependencesSize _DEFAULT_INIT_VALUE_ (0);
// 这个项无意义,仅用于内存对齐
DWORD dwPadding _DEFAULT_INIT_VALUE_ (0);
// 这个项无意义,除非之后我想通过动态内存方式写依赖项的数组。
UINT64 ullBuffer _DEFAULT_INIT_VALUE_ (0);
} FIND_PACKAGE_INFO, *PFIND_PACKAGE_INFO;
typedef const FIND_PACKAGE_INFO CFIND_PACKAGE_INFO, *LPCFIND_PACKAGE_INFO;
// 注:回调时的指针不要手动释放
typedef void (*PKGMGR_FINDENUMCALLBACK) (LPCFIND_PACKAGE_INFO pNowItem, void *pCustom);
// 通过回调来获取所有包的信息。回调函数允许传自定义内容。返回的值可以判断是否成功。
// 该函数类似于 PowerShell 的 Get-AppxPackage
// 注意:回调函数中包的信息无法修改,也不能擅自释放。且随着函数的执行完毕自动释放。这就要求在回调中自行拷贝一份。
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 移除一个已经安装到电脑上的应用。注意:传入的是包完整名。
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT RemoveAppxPackage (LPCWSTR lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 清理指定用户的指定 包 。 用于清除删除用户用户配置文件后为用户安装的包。
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT CleanupAppxPackage (LPCWSTR lpPkgName, LPCWSTR lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 注册应用包
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT RegisterAppxPackageByPath (LPCWSTR lpManifestPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 注册应用包
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT RegisterAppxPackageByUri (LPCWSTR lpManifestUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 注册应用包
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT RegisterAppxPackageByFullName (LPCWSTR lpPackageFullName, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 请查阅 https://learn.microsoft.com/zh-cn/uwp/api/windows.management.deployment.packagestate?view=winrt-26100
// 包可用。
#define PACKAGESTATUS_NORMAL 0
// 包的许可证无效。
#define PACKAGESTATUS_LICENSE_INVALID 1
// 包有效负载由未知源修改。
#define PACKAGESTATUS_MODIFIED 2
// 包有效负载被故意篡改。
#define PACKAGESTATUS_TAMPERED 3
// 例如,将 包的状态设置为“可用”、“已篡改”等。
// dwStatus 请使用 PACKAGESTATUS_* 常量
PKGMGR_API HRESULT SetAppxPackageStatus (LPCWSTR lpPackageFullName, DWORD dwStatus, LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 在不注册包的情况下将 包 暂存到系统。
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT StageAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 在不注册包的情况下将 包 暂存到系统。
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT StageAppxPackageFromPath (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 在不注册包的情况下将 包的 漫游数据暂存到系统。 在暂存包之后、为特定用户注册包之前调用此方法。
// dwDeployOption 接受 DEPOLYOPTION_* 常量
PKGMGR_API HRESULT StageAppxUserData (LPCWSTR lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 为当前用户汇报已安装的包或其依赖项包。
// 仅当更新包的版本高于已安装包的版本时,才能更新已安装的包。 如果不存在以前版本的包,则操作将失败。
// 注意:传入的文件路径为 DOS/NT 风格。如:C:\Windows\...
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT UpdateAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 为当前用户汇报已安装的包或其依赖项包。
// 仅当更新包的版本高于已安装包的版本时,才能更新已安装的包。 如果不存在以前版本的包,则操作将失败。
// 注意:传入的文件路径为 URI。
// dwDeployOption 接受 DEPOLYOPTION_* 常量
// 输出的错误信息别忘了用 free 释放
PKGMGR_API HRESULT UpdateAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 检索有关为任何用户安装的指定 包 的信息。
PKGMGR_API HRESULT FindAppxPackage (LPCWSTR lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 获取错误代码。错误代码不一定有,且更多有效信息来自错误详细信息。
PKGMGR_API LPCWSTR GetPackageManagerLastErrorCode ();
// 获取错误详细信息。这个是常用的
PKGMGR_API LPCWSTR GetPackageManagerLastErrorDetailMessage ();
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
#ifdef _DEFAULT_INIT_VALUE_FORFUNC_
#undef _DEFAULT_INIT_VALUE_FORFUNC_
#endif
#ifdef __cplusplus
}
#endif
+96
View File
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8EAC0230-4990-4E41-8E0F-D641D1561396}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pkgmgr</RootNamespace>
<ProjectName>pkgmgr</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
<CLRSupport>false</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
<CLRSupport>false</CLRSupport>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ReferencePath>$(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)</ReferencePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ReferencePath>$(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)</ReferencePath>
</PropertyGroup>
<!-- 关键:启用 WinRT 扩展 -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalOptions>/ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGMGR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAsWinRT>true</CompileAsWinRT>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalOptions>/ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGMGR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAsWinRT>true</CompileAsWinRT>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="pkgmgr.cpp" />
<ClCompile Include="stdafx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pkgmgr.h" />
<ClInclude Include="raii.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="version.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
+42
View File
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pkgmgr.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pkgmgr.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="raii.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="version.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
</Project>
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <functional>
struct raii
{
std::function <void ()> endtask = nullptr;
raii (std::function <void ()> pFunc = nullptr): endtask (pFunc) {}
~raii () { if (endtask) endtask (); }
};
+8
View File
@@ -0,0 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// pkgmgr.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
//而不是在此文件中引用
+30
View File
@@ -0,0 +1,30 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>
// TODO: 在此处引用程序需要的其他头文件
#using <Windows.winmd>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Management::Deployment;
#include <string>
#include <vector>
#include <objbase.h>
#include <iostream>
#include <functional>
#include <sddl.h>
#include <algorithm>
#include <collection.h>
#include <string>
#include <sddl.h>
+8
View File
@@ -0,0 +1,8 @@
#pragma once
// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
+125
View File
@@ -0,0 +1,125 @@
#pragma once
#include <vector>
#include <string>
#include <cstdint>
#include <sstream>
typedef uint64_t UINT64;
typedef int64_t INT64;
typedef uint16_t UINT16;
typedef struct version
{
UINT16 major = 0, minor = 0, build = 0, revision = 0;
version (UINT64 value):
major ((value >> 0x30) & 0xFFFF), minor ((value >> 0x20) & 0xFFFF),
build ((value >> 0x10) & 0xFFFF), revision ((value) & 0xFFFF) {}
version (UINT16 major, UINT16 minor, UINT16 build, UINT16 revision):
major (major), minor (minor), build (build), revision (revision) {}
version (const std::wstring &verstr) { this->interpret (verstr); }
version (const std::string &verstr) { this->interpret (verstr); }
version () {}
version (const version &other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
version (version &&other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
version &operator = (const version &other)
{
if (this != &other)
{
major = other.major;
minor = other.minor;
build = other.build;
revision = other.revision;
}
return *this;
}
version &operator = (version &&other)
{
if (this != &other)
{
major = other.major;
minor = other.minor;
build = other.build;
revision = other.revision;
}
return *this;
}
version &operator = (UINT64 value) { this->data (value); return *this; }
UINT64 data () const { return (((UINT64)major) << 48) | (((UINT64)minor) << 32) | (((UINT64)build) << 16) | ((UINT64)revision); }
UINT64 data (UINT64 value)
{
major = (value >> 48) & 0xFFFF;
minor = (value >> 32) & 0xFFFF;
build = (value >> 16) & 0xFFFF;
revision = value & 0xFFFF;
return value;
}
std::wstring stringifyw () const
{
std::wstringstream ss;
ss << major << L'.' << minor << L'.' << build << L'.' << revision;
return ss.str ();
}
std::string stringify () const
{
std::stringstream ss;
ss << major << '.' << minor << '.' << build << '.' << revision;
return ss.str ();
}
version &interpret (const std::wstring &verstr)
{
auto result = split (verstr);
if (result.size () > 0) this->major = _wtoi (result [0].c_str ());
if (result.size () > 1) this->minor = _wtoi (result [1].c_str ());
if (result.size () > 2) this->build = _wtoi (result [2].c_str ());
if (result.size () > 3) this->revision = _wtoi (result [3].c_str ());
return *this;
}
version &interpret (const std::string &verstr)
{
auto result = split (verstr);
if (result.size () > 0) this->major = atoi (result [0].c_str ());
if (result.size () > 1) this->minor = atoi (result [1].c_str ());
if (result.size () > 2) this->build = atoi (result [2].c_str ());
if (result.size () > 3) this->revision = atoi (result [3].c_str ());
return *this;
}
bool empty () const { return *(UINT64 *)this == 0; }
friend bool operator == (const version &l, const version &r) { return *(UINT64 *)&l == *(UINT64 *)&r; }
friend bool operator == (const version &l, const UINT64 &r) { return l.data () == r; }
friend bool operator == (const UINT64 &r, const version &l) { return l.data () == r; }
friend bool operator < (const version &l, const version &r) { return l.data () < r.data (); }
friend bool operator > (const version &l, const version &r) { return l.data () > r.data (); }
friend bool operator <= (const version &l, const version &r) { return l.data () <= r.data (); }
friend bool operator >= (const version &l, const version &r) { return l.data () >= r.data (); }
friend bool operator != (const version &l, const version &r) { return *(UINT64 *)&l != *(UINT64 *)&r; }
explicit operator bool () const { return !this->empty (); }
bool operator ! () { return this->empty (); }
friend std::ostream &operator << (std::ostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
friend std::wostream &operator << (std::wostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
bool equals (const version &r) const { return *this == r; }
INT64 compare (const version &r) const { return this->data () - r.data (); }
static version parse (const std::wstring &value) { return version (value); }
static version parse (const std::string &value) { return version (value); }
static std::wstring stringifyw (const version &v) { return v.stringifyw (); }
static std::string stringify (const version &v) { return v.stringify (); }
static bool equals (const version &l, const version &r) { return l == r; }
static INT64 compare (const version &l, const version &r) { return l.data () - r.data (); }
static version decode (UINT64 value) { return version (value); }
static UINT64 encode (const version &v) { return v.data (); }
protected:
template <typename StringType> std::vector <StringType> split (const StringType &str, typename StringType::value_type delimiter1 = '.', typename StringType::value_type delimiter2 = ',')
{
std::vector <StringType> result;
std::basic_stringstream<typename StringType::value_type> ss (str);
StringType segment;
while (std::getline (ss, segment, delimiter1))
{
size_t pos = 0;
while ((pos = segment.find (delimiter2)) != StringType::npos)
{
result.push_back (segment.substr (0, pos));
segment.erase (0, pos + 1);
}
if (!segment.empty ()) result.push_back (segment);
}
return result;
}
} Version;