mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
[CmdPal] [Install] do not install dependency if already satisfied. (#38531)
* do not install dependency if already satisfied. * self contain winappsdk
This commit is contained in:
@@ -40,7 +40,6 @@
|
|||||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
||||||
</RegistryKey>
|
</RegistryKey>
|
||||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" />
|
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" />
|
||||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.WindowsAppRuntime.1.6.msix" />
|
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<?else ?>
|
<?else ?>
|
||||||
@@ -50,7 +49,6 @@
|
|||||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
||||||
</RegistryKey>
|
</RegistryKey>
|
||||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.VCLibs.ARM64.14.00.Desktop.appx" />
|
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.VCLibs.ARM64.14.00.Desktop.appx" />
|
||||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.WindowsAppRuntime.1.6.msix" />
|
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<?endif ?>
|
<?endif ?>
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <appxpackaging.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
#include <winrt/Windows.ApplicationModel.h>
|
#include <winrt/Windows.ApplicationModel.h>
|
||||||
#include <winrt/Windows.Foundation.h>
|
#include <winrt/Windows.Foundation.h>
|
||||||
@@ -15,11 +18,12 @@
|
|||||||
#include "../logger/logger.h"
|
#include "../logger/logger.h"
|
||||||
#include "../version/version.h"
|
#include "../version/version.h"
|
||||||
|
|
||||||
namespace package {
|
namespace package
|
||||||
|
{
|
||||||
using namespace winrt::Windows::Foundation;
|
using namespace winrt::Windows::Foundation;
|
||||||
using namespace winrt::Windows::ApplicationModel;
|
using namespace winrt::Windows::ApplicationModel;
|
||||||
using namespace winrt::Windows::Management::Deployment;
|
using namespace winrt::Windows::Management::Deployment;
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
inline BOOL IsWin11OrGreater()
|
inline BOOL IsWin11OrGreater()
|
||||||
{
|
{
|
||||||
@@ -46,6 +50,118 @@ namespace package {
|
|||||||
dwlConditionMask);
|
dwlConditionMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PACKAGE_VERSION
|
||||||
|
{
|
||||||
|
UINT16 Major;
|
||||||
|
UINT16 Minor;
|
||||||
|
UINT16 Build;
|
||||||
|
UINT16 Revision;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ComInitializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ComInitializer(DWORD coInitFlags = COINIT_MULTITHREADED) :
|
||||||
|
_initialized(false)
|
||||||
|
{
|
||||||
|
const HRESULT hr = CoInitializeEx(nullptr, coInitFlags);
|
||||||
|
_initialized = SUCCEEDED(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ComInitializer()
|
||||||
|
{
|
||||||
|
if (_initialized)
|
||||||
|
{
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Succeeded() const { return _initialized; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool GetPackageNameAndVersionFromAppx(
|
||||||
|
const std::wstring& appxPath,
|
||||||
|
std::wstring& outName,
|
||||||
|
PACKAGE_VERSION& outVersion)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ComInitializer comInit;
|
||||||
|
if (!comInit.Succeeded())
|
||||||
|
{
|
||||||
|
Logger::error(L"COM initialization failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IAppxFactory> factory;
|
||||||
|
ComPtr<IStream> stream;
|
||||||
|
ComPtr<IAppxPackageReader> reader;
|
||||||
|
ComPtr<IAppxManifestReader> manifest;
|
||||||
|
ComPtr<IAppxManifestPackageId> packageId;
|
||||||
|
|
||||||
|
HRESULT hr = CoCreateInstance(__uuidof(AppxFactory), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hr = SHCreateStreamOnFileEx(appxPath.c_str(), STGM_READ | STGM_SHARE_DENY_WRITE, FILE_ATTRIBUTE_NORMAL, FALSE, nullptr, &stream);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hr = factory->CreatePackageReader(stream.Get(), &reader);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hr = reader->GetManifest(&manifest);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hr = manifest->GetPackageId(&packageId);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LPWSTR name = nullptr;
|
||||||
|
hr = packageId->GetName(&name);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UINT64 version = 0;
|
||||||
|
hr = packageId->GetVersion(&version);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outName = std::wstring(name);
|
||||||
|
CoTaskMemFree(name);
|
||||||
|
|
||||||
|
outVersion.Major = static_cast<UINT16>((version >> 48) & 0xFFFF);
|
||||||
|
outVersion.Minor = static_cast<UINT16>((version >> 32) & 0xFFFF);
|
||||||
|
outVersion.Build = static_cast<UINT16>((version >> 16) & 0xFFFF);
|
||||||
|
outVersion.Revision = static_cast<UINT16>(version & 0xFFFF);
|
||||||
|
|
||||||
|
Logger::info(L"Package name: {}, version: {}.{}.{}.{}, appxPath: {}",
|
||||||
|
outName,
|
||||||
|
outVersion.Major,
|
||||||
|
outVersion.Minor,
|
||||||
|
outVersion.Build,
|
||||||
|
outVersion.Revision,
|
||||||
|
appxPath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex)
|
||||||
|
{
|
||||||
|
Logger::error(L"Standard exception: {}", winrt::to_hstring(ex.what()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::error(L"Unknown or non-standard exception occurred.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline std::optional<Package> GetRegisteredPackage(std::wstring packageDisplayName, bool checkVersion)
|
inline std::optional<Package> GetRegisteredPackage(std::wstring packageDisplayName, bool checkVersion)
|
||||||
{
|
{
|
||||||
PackageManager packageManager;
|
PackageManager packageManager;
|
||||||
@@ -229,6 +345,59 @@ namespace package {
|
|||||||
return matchedFiles;
|
return matchedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsPackageSatisfied(const std::wstring& appxPath)
|
||||||
|
{
|
||||||
|
std::wstring targetName;
|
||||||
|
PACKAGE_VERSION targetVersion{};
|
||||||
|
|
||||||
|
if (!GetPackageNameAndVersionFromAppx(appxPath, targetName, targetVersion))
|
||||||
|
{
|
||||||
|
Logger::error(L"Failed to get package name and version from appx: " + appxPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageManager pm;
|
||||||
|
|
||||||
|
for (const auto& package : pm.FindPackagesForUser({}))
|
||||||
|
{
|
||||||
|
const auto& id = package.Id();
|
||||||
|
if (std::wstring(id.Name()) == targetName)
|
||||||
|
{
|
||||||
|
const auto& version = id.Version();
|
||||||
|
|
||||||
|
if (version.Major > targetVersion.Major ||
|
||||||
|
(version.Major == targetVersion.Major && version.Minor > targetVersion.Minor) ||
|
||||||
|
(version.Major == targetVersion.Major && version.Minor == targetVersion.Minor && version.Build > targetVersion.Build) ||
|
||||||
|
(version.Major == targetVersion.Major && version.Minor == targetVersion.Minor && version.Build == targetVersion.Build && version.Revision >= targetVersion.Revision))
|
||||||
|
{
|
||||||
|
Logger::info(
|
||||||
|
L"Package {} is already satisfied with version {}.{}.{}.{}; target version {}.{}.{}.{}; appxPath: {}",
|
||||||
|
id.Name(),
|
||||||
|
version.Major,
|
||||||
|
version.Minor,
|
||||||
|
version.Build,
|
||||||
|
version.Revision,
|
||||||
|
targetVersion.Major,
|
||||||
|
targetVersion.Minor,
|
||||||
|
targetVersion.Build,
|
||||||
|
targetVersion.Revision,
|
||||||
|
appxPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info(
|
||||||
|
L"Package {} is not satisfied. Target version: {}.{}.{}.{}; appxPath: {}",
|
||||||
|
targetName,
|
||||||
|
targetVersion.Major,
|
||||||
|
targetVersion.Minor,
|
||||||
|
targetVersion.Build,
|
||||||
|
targetVersion.Revision,
|
||||||
|
appxPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool RegisterPackage(std::wstring pkgPath, std::vector<std::wstring> dependencies)
|
inline bool RegisterPackage(std::wstring pkgPath, std::vector<std::wstring> dependencies)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -247,7 +416,14 @@ namespace package {
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uris.Append(Uri(dependency));
|
if (IsPackageSatisfied(dependency))
|
||||||
|
{
|
||||||
|
Logger::info(L"Dependency already satisfied: {}", dependency);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uris.Append(Uri(dependency));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const winrt::hresult_error& ex)
|
catch (const winrt::hresult_error& ex)
|
||||||
{
|
{
|
||||||
@@ -282,7 +458,6 @@ namespace package {
|
|||||||
{
|
{
|
||||||
Logger::debug(L"Register {} package started.", pkgPath);
|
Logger::debug(L"Register {} package started.", pkgPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<EnableMsixTooling>true</EnableMsixTooling>
|
<EnableMsixTooling>true</EnableMsixTooling>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||||
|
|
||||||
<Version>$(CmdPalVersion)</Version>
|
<Version>$(CmdPalVersion)</Version>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user