Skip to content

Commit b080a73

Browse files
vanzueyeelam-gordon
authored andcommitted
[CmdPal] [Install] do not install dependency if already satisfied. (#38531)
* do not install dependency if already satisfied. * self contain winappsdk
1 parent 8322a77 commit b080a73

File tree

3 files changed

+180
-6
lines changed

3 files changed

+180
-6
lines changed

installer/PowerToysSetup/CmdPal.wxs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
4141
</RegistryKey>
4242
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" />
43-
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.WindowsAppRuntime.1.6.msix" />
4443
</Component>
4544
</DirectoryRef>
4645
<?else ?>
@@ -50,7 +49,6 @@
5049
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
5150
</RegistryKey>
5251
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.VCLibs.ARM64.14.00.Desktop.appx" />
53-
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.WindowsAppRuntime.1.6.msix" />
5452
</Component>
5553
</DirectoryRef>
5654
<?endif ?>

src/common/utils/package.h

Lines changed: 179 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
#include <Windows.h>
44

5+
#include <appxpackaging.h>
56
#include <exception>
67
#include <filesystem>
78
#include <regex>
89
#include <string>
910
#include <optional>
11+
#include <Shlwapi.h>
12+
#include <wrl/client.h>
1013

1114
#include <winrt/Windows.ApplicationModel.h>
1215
#include <winrt/Windows.Foundation.h>
@@ -15,11 +18,12 @@
1518
#include "../logger/logger.h"
1619
#include "../version/version.h"
1720

18-
namespace package {
19-
21+
namespace package
22+
{
2023
using namespace winrt::Windows::Foundation;
2124
using namespace winrt::Windows::ApplicationModel;
2225
using namespace winrt::Windows::Management::Deployment;
26+
using Microsoft::WRL::ComPtr;
2327

2428
inline BOOL IsWin11OrGreater()
2529
{
@@ -46,6 +50,118 @@ namespace package {
4650
dwlConditionMask);
4751
}
4852

53+
struct PACKAGE_VERSION
54+
{
55+
UINT16 Major;
56+
UINT16 Minor;
57+
UINT16 Build;
58+
UINT16 Revision;
59+
};
60+
61+
class ComInitializer
62+
{
63+
public:
64+
explicit ComInitializer(DWORD coInitFlags = COINIT_MULTITHREADED) :
65+
_initialized(false)
66+
{
67+
const HRESULT hr = CoInitializeEx(nullptr, coInitFlags);
68+
_initialized = SUCCEEDED(hr);
69+
}
70+
71+
~ComInitializer()
72+
{
73+
if (_initialized)
74+
{
75+
CoUninitialize();
76+
}
77+
}
78+
79+
bool Succeeded() const { return _initialized; }
80+
81+
private:
82+
bool _initialized;
83+
};
84+
85+
inline bool GetPackageNameAndVersionFromAppx(
86+
const std::wstring& appxPath,
87+
std::wstring& outName,
88+
PACKAGE_VERSION& outVersion)
89+
{
90+
try
91+
{
92+
ComInitializer comInit;
93+
if (!comInit.Succeeded())
94+
{
95+
Logger::error(L"COM initialization failed.");
96+
return false;
97+
}
98+
99+
ComPtr<IAppxFactory> factory;
100+
ComPtr<IStream> stream;
101+
ComPtr<IAppxPackageReader> reader;
102+
ComPtr<IAppxManifestReader> manifest;
103+
ComPtr<IAppxManifestPackageId> packageId;
104+
105+
HRESULT hr = CoCreateInstance(__uuidof(AppxFactory), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));
106+
if (FAILED(hr))
107+
return false;
108+
109+
hr = SHCreateStreamOnFileEx(appxPath.c_str(), STGM_READ | STGM_SHARE_DENY_WRITE, FILE_ATTRIBUTE_NORMAL, FALSE, nullptr, &stream);
110+
if (FAILED(hr))
111+
return false;
112+
113+
hr = factory->CreatePackageReader(stream.Get(), &reader);
114+
if (FAILED(hr))
115+
return false;
116+
117+
hr = reader->GetManifest(&manifest);
118+
if (FAILED(hr))
119+
return false;
120+
121+
hr = manifest->GetPackageId(&packageId);
122+
if (FAILED(hr))
123+
return false;
124+
125+
LPWSTR name = nullptr;
126+
hr = packageId->GetName(&name);
127+
if (FAILED(hr))
128+
return false;
129+
130+
UINT64 version = 0;
131+
hr = packageId->GetVersion(&version);
132+
if (FAILED(hr))
133+
return false;
134+
135+
outName = std::wstring(name);
136+
CoTaskMemFree(name);
137+
138+
outVersion.Major = static_cast<UINT16>((version >> 48) & 0xFFFF);
139+
outVersion.Minor = static_cast<UINT16>((version >> 32) & 0xFFFF);
140+
outVersion.Build = static_cast<UINT16>((version >> 16) & 0xFFFF);
141+
outVersion.Revision = static_cast<UINT16>(version & 0xFFFF);
142+
143+
Logger::info(L"Package name: {}, version: {}.{}.{}.{}, appxPath: {}",
144+
outName,
145+
outVersion.Major,
146+
outVersion.Minor,
147+
outVersion.Build,
148+
outVersion.Revision,
149+
appxPath);
150+
151+
return true;
152+
}
153+
catch (const std::exception& ex)
154+
{
155+
Logger::error(L"Standard exception: {}", winrt::to_hstring(ex.what()));
156+
return false;
157+
}
158+
catch (...)
159+
{
160+
Logger::error(L"Unknown or non-standard exception occurred.");
161+
return false;
162+
}
163+
}
164+
49165
inline std::optional<Package> GetRegisteredPackage(std::wstring packageDisplayName, bool checkVersion)
50166
{
51167
PackageManager packageManager;
@@ -229,6 +345,59 @@ namespace package {
229345
return matchedFiles;
230346
}
231347

348+
inline bool IsPackageSatisfied(const std::wstring& appxPath)
349+
{
350+
std::wstring targetName;
351+
PACKAGE_VERSION targetVersion{};
352+
353+
if (!GetPackageNameAndVersionFromAppx(appxPath, targetName, targetVersion))
354+
{
355+
Logger::error(L"Failed to get package name and version from appx: " + appxPath);
356+
return false;
357+
}
358+
359+
PackageManager pm;
360+
361+
for (const auto& package : pm.FindPackagesForUser({}))
362+
{
363+
const auto& id = package.Id();
364+
if (std::wstring(id.Name()) == targetName)
365+
{
366+
const auto& version = id.Version();
367+
368+
if (version.Major > targetVersion.Major ||
369+
(version.Major == targetVersion.Major && version.Minor > targetVersion.Minor) ||
370+
(version.Major == targetVersion.Major && version.Minor == targetVersion.Minor && version.Build > targetVersion.Build) ||
371+
(version.Major == targetVersion.Major && version.Minor == targetVersion.Minor && version.Build == targetVersion.Build && version.Revision >= targetVersion.Revision))
372+
{
373+
Logger::info(
374+
L"Package {} is already satisfied with version {}.{}.{}.{}; target version {}.{}.{}.{}; appxPath: {}",
375+
id.Name(),
376+
version.Major,
377+
version.Minor,
378+
version.Build,
379+
version.Revision,
380+
targetVersion.Major,
381+
targetVersion.Minor,
382+
targetVersion.Build,
383+
targetVersion.Revision,
384+
appxPath);
385+
return true;
386+
}
387+
}
388+
}
389+
390+
Logger::info(
391+
L"Package {} is not satisfied. Target version: {}.{}.{}.{}; appxPath: {}",
392+
targetName,
393+
targetVersion.Major,
394+
targetVersion.Minor,
395+
targetVersion.Build,
396+
targetVersion.Revision,
397+
appxPath);
398+
return false;
399+
}
400+
232401
inline bool RegisterPackage(std::wstring pkgPath, std::vector<std::wstring> dependencies)
233402
{
234403
try
@@ -247,7 +416,14 @@ namespace package {
247416
{
248417
try
249418
{
250-
uris.Append(Uri(dependency));
419+
if (IsPackageSatisfied(dependency))
420+
{
421+
Logger::info(L"Dependency already satisfied: {}", dependency);
422+
}
423+
else
424+
{
425+
uris.Append(Uri(dependency));
426+
}
251427
}
252428
catch (const winrt::hresult_error& ex)
253429
{
@@ -282,7 +458,6 @@ namespace package {
282458
{
283459
Logger::debug(L"Register {} package started.", pkgPath);
284460
}
285-
286461
}
287462
catch (std::exception& e)
288463
{

src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<EnableMsixTooling>true</EnableMsixTooling>
1414
<ImplicitUsings>enable</ImplicitUsings>
1515
<Nullable>enable</Nullable>
16+
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
1617

1718
<Version>$(CmdPalVersion)</Version>
1819

0 commit comments

Comments
 (0)