diff --git a/PowerToys.sln b/PowerToys.sln index 1ba2940ec1..4af72870f9 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -638,8 +638,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI.ViewMod EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalModuleInterface", "src\modules\cmdpal\CmdPalModuleInterface\CmdPalModuleInterface.vcxproj", "{0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "src\modules\Workspaces\WorkspacesCsharpLibrary\WorkspacesCsharpLibrary.csproj", "{89D0E199-B17A-418C-B2F8-7375B6708357}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}" @@ -2427,14 +2425,6 @@ Global {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|ARM64.Build.0 = Release|ARM64 {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|x64.ActiveCfg = Release|x64 {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|x64.Build.0 = Release|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|ARM64.Build.0 = Debug|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|x64.ActiveCfg = Debug|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|x64.Build.0 = Debug|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|ARM64.ActiveCfg = Release|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|ARM64.Build.0 = Release|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|x64.ActiveCfg = Release|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|x64.Build.0 = Release|x64 {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.ActiveCfg = Debug|ARM64 {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.Build.0 = Debug|ARM64 {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x64.ActiveCfg = Debug|x64 @@ -3207,7 +3197,6 @@ Global {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90} = {7520A2FE-00A2-49B8-83ED-DB216E874C04} {C66020D1-CB10-4CF7-8715-84C97FD5E5E2} = {7520A2FE-00A2-49B8-83ED-DB216E874C04} {79775343-7A3D-445D-9104-3DD5B2893DF9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8} = {3846508C-77EB-4034-A702-F8BB263C4F79} {89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC} {453CBB73-A3CB-4D0B-8D24-6940B86FE21D} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} diff --git a/src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs b/src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs new file mode 100644 index 0000000000..b99570a427 --- /dev/null +++ b/src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.ApplicationModel; + +namespace RunnerV2.Extensions +{ + internal static class PackageVersionExtensions + { + public static Version ToVersion(this PackageVersion packageVersion) + { + return new Version(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision); + } + } +} diff --git a/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs b/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs new file mode 100644 index 0000000000..2c277b84ae --- /dev/null +++ b/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Runtime.InteropServices.Marshalling; +using System.Text.RegularExpressions; +using ManagedCommon; +using ManagedCsWin32; +using RunnerV2.Extensions; +using Windows.ApplicationModel; +using Windows.Foundation; +using Windows.Management.Deployment; + +namespace RunnerV2.Helpers +{ + /// + /// Provides helper methods for working with UWP packages. + /// + internal static partial class PackageHelper + { + /// + /// Gets the registered UWP package based on the display name and version check. + /// + /// The display name of the package. + /// If true, the package version will be checked against the executing assembly version. + /// If a package is found the corresponding object. If none is found null. + internal static Package? GetRegisteredPackage(string packageDisplayName, bool checkVersion) + { + PackageManager packageManager = new(); + foreach (var package in packageManager.FindPackagesForUser(null)) + { + if (package.Id.FullName.Contains(packageDisplayName) && (!checkVersion || package.Id.Version.ToVersion() == Assembly.GetExecutingAssembly().GetName().Version)) + { + return package; + } + } + + return null; + } + + internal static string[] FindMsixFiles(string directoryPath, bool recursive) + { + if (!Directory.Exists(directoryPath)) + { + Logger.LogError("Tried to search msix files in " + directoryPath + ", but it does not exist."); + return []; + } + + List matchedFiles = []; + + try + { + foreach (string file in Directory.GetFiles(directoryPath, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) + { + if (File.Exists(file) && msixPackagePattern().IsMatch(Path.GetFileName(file))) + { + matchedFiles.Add(file); + } + } + } + catch (Exception e) + { + Logger.LogError("An error occured while searching for MSIX files.", e); + } + + return [.. matchedFiles]; + } + + internal static bool RegisterPackage(string packagePath, string[] dependencies) + { + Logger.LogInfo("Starting package install of package \"" + packagePath + "\""); + PackageManager packageManager = new(); + List uris = []; + + foreach (string dependency in dependencies) + { + try + { + if (IsPackageSatisfied(dependency)) + { + Logger.LogInfo("Dependency \"" + dependency + "\" is already satisfied."); + continue; + } + else + { + uris.Add(new Uri(packagePath)); + } + } + catch (Exception ex) + { + Logger.LogError("Could not process dependency package at path \"" + dependency + "\"", ex); + } + } + + try + { + IAsyncOperationWithProgress deploymentOperation = packageManager.AddPackageAsync(new Uri(packagePath), uris, DeploymentOptions.ForceApplicationShutdown); + deploymentOperation.Get(); + + switch (deploymentOperation.Status) + { + case AsyncStatus.Error: + Logger.LogError($"Registering {packagePath} failed. ErrorCode: {deploymentOperation.ErrorCode}, ErrorText: {deploymentOperation.GetResults().ErrorText}"); + break; + case AsyncStatus.Canceled: + Logger.LogError($"Registering {packagePath} was canceled."); + break; + case AsyncStatus.Completed: + Logger.LogInfo($"Registering {packagePath} succeded."); + break; + default: + Logger.LogDebug($"Registering {packagePath} package started."); + break; + } + + return true; + } + catch (Exception e) + { + Logger.LogError($"Exception thrown while trying to register package: {packagePath}", e); + } + + return false; + } + + private static bool IsPackageSatisfied(string packagePath) + { + if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version)) + { + Logger.LogError("Could not get package name and version from dependency package at path \"" + packagePath + "\""); + return false; + } + + PackageManager packageManager = new(); + + foreach (var package in packageManager.FindPackagesForUser(null)) + { + if (package.Id.Name.Equals(name, StringComparison.OrdinalIgnoreCase) && + package.Id.Version.ToVersion() > version.ToVersion()) + { + Logger.LogInfo($@"Package ""{name}"" is already statisfied with version: {package.Id.Version}. Target version: {version}. PackagePath: {packagePath}"); + return true; + } + } + + Logger.LogInfo($@"Package ""{name}"" with version {version} is not satisfied. PackagePath: {packagePath}"); + return false; + } + + private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion) + { + // Todo: Implement this without interop if possible + return NativeMethods.GetPackageNameAndVersionFromAppx(packagePath, out name, out packageVersion); + } + + [GeneratedRegex("(^.+\\.(appx|msix|msixbundle)$)", RegexOptions.IgnoreCase)] + private static partial Regex msixPackagePattern(); + } +} diff --git a/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs b/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs new file mode 100644 index 0000000000..933c15c41b --- /dev/null +++ b/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Library; +using PowerToys.GPOWrapper; +using RunnerV2.Helpers; +using Windows.ApplicationModel; + +namespace RunnerV2.ModuleInterfaces +{ + internal sealed class CommandPaletteModuleInterface : IPowerToysModule + { + private const string PackageName = "Microsoft.CommandPalette" +#if DEBUG + + ".Dev" +#endif + ; + + public string Name => "CmdPal"; + + public bool Enabled => new SettingsUtils().GetSettingsOrDefault().Enabled.CmdPal; + + public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCmdPalEnabledValue(); + + public void Disable() + { + ProcessHelper.ScheudleProcessKill("Microsoft.CmdPal.UI"); + lock (_launchedLock) + { + _launched = false; + } + } + + public void Enable() + { + if (PackageHelper.GetRegisteredPackage(PackageName, false) is null) + { + try + { + string architectureString = RuntimeInformation.ProcessArchitecture == Architecture.X64 ? "x64" : "ARM64"; +#if DEBUG + string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\", false); + string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\Dependencies\\" + architectureString + "\\", true); +#else + string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\", false); + string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\Dependencies\\", true); +#endif + + if (msixFiles.Length > 0) + { + if (!PackageHelper.RegisterPackage(msixFiles[0], dependencies)) + { + Logger.LogError("Failed to register Command Palette package."); + } + } + } + catch (Exception ex) + { + Logger.LogError("Exception occurred while enabling Command Palette package.", ex); + } + } + + if (PackageHelper.GetRegisteredPackage(PackageName, false) is null) + { + Logger.LogError("Command Palette package is not registered after attempting to enable it."); + return; + } + + lock (_launchedLock) + { + if (_launched) + { + return; + } + } + + LaunchApp("explorer.exe", "x-cmdpal://background", false); + } + + private readonly object _launchedLock = new(); + private bool _launched; + + // TODO: Implement retry logic for launching the app + /*private static void TryLaunch(string path, string args) + { + int baseDelay = 1000; + int maxAttempts = 9; + int retryCount = 0; + + do + { + if (LaunchApp) + } + }*/ + + private bool LaunchApp(string path, string args, bool elevated) + { + try + { + Process? process = Process.Start(new ProcessStartInfo + { + FileName = path, + CreateNoWindow = true, + UseShellExecute = true, + Verb = elevated ? "runas" : "open", + Arguments = args, + }); + + if (process is null) + { + Logger.LogError($"Failed to start process for {path} with args {args}"); + } + } + catch (Exception ex) + { + Logger.LogError($"Exception occurred while launching app {path} with args {args}", ex); + return false; + } + + lock (_launchedLock) + { + _launched = true; + } + + return true; + } + } +} diff --git a/src/RunnerV2/RunnerV2/ModuleInterfaces/IPowerToysModule.cs b/src/RunnerV2/RunnerV2/ModuleInterfaces/IPowerToysModule.cs index e4498fa196..8363caeb35 100644 --- a/src/RunnerV2/RunnerV2/ModuleInterfaces/IPowerToysModule.cs +++ b/src/RunnerV2/RunnerV2/ModuleInterfaces/IPowerToysModule.cs @@ -13,22 +13,60 @@ namespace RunnerV2.ModuleInterfaces { public interface IPowerToysModule { + /// + /// Gets the short name of the module. The same used as the name of the folder containing its settings. + /// public string Name { get; } + /// + /// This function is called when the module is enabled. + /// public void Enable(); + /// + /// This function is called when the module is disabled. + /// public void Disable(); + /// + /// Gets a value indicating whether the module is enabled. + /// + /// + /// This value shall be read from the settings of the module in the module interface implementation. + /// public bool Enabled { get; } + /// + /// Gets the GPO rule configured state for the module. + /// + /// + /// This value shall be read from the GPO settings with the class. + /// public GpoRuleConfigured GpoRuleConfigured { get; } + /// + /// Gets a dictionary of hotkeys and their associated actions. Every hotkey must have an associated id. + /// + /// + /// If this property is not overridden, the module is considered to not have hotkeys. + /// public Dictionary Hotkeys { get => []; } + /// + /// Gets a list of shortcuts, that shall be registered in the keyboard hook, and their associated actions. + /// + /// + /// If this property is not overridden, the module is considered to not have shortcuts. + /// public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get => []; } public Dictionary CustomActions { get => []; } + /// + /// This function is called when the settings of the module or the general settings are changed. + /// + /// Value of or "general" indicating the type of change. + /// The json element with the new settings. public void OnSettingsChanged(string settingsKind, JsonElement jsonProperties) { } diff --git a/src/RunnerV2/RunnerV2/NativeMethods.cs b/src/RunnerV2/RunnerV2/NativeMethods.cs index d78a05933b..bbc0def459 100644 --- a/src/RunnerV2/RunnerV2/NativeMethods.cs +++ b/src/RunnerV2/RunnerV2/NativeMethods.cs @@ -5,7 +5,9 @@ using System; using System.Drawing; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using ManagedCommon; +using Windows.ApplicationModel; namespace RunnerV2 { @@ -230,5 +232,27 @@ namespace RunnerV2 [DllImport("user32.dll")] internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize); + + public const int COINIT_MULTITHREADED = 0x0; + + [LibraryImport("ole32.dll")] + public static partial int CoInitializeEx(IntPtr pvReserved, int dwCoInit); + + [LibraryImport("ole32.dll")] + public static partial void CoUninitialize(); + + [DllImport("Shlwapi.dll")] + public static extern IntPtr SHCreateStreamOnFileEx( + [MarshalAs(UnmanagedType.LPWStr)] string pszFile, + uint grfMode, + [MarshalAs(UnmanagedType.Bool)]bool fCreate, + IntPtr pstmTemplate, + out IStream stream); + + [DllImport("PowerToys.Interop.dll", CallingConvention = CallingConvention.Cdecl)] + internal static extern bool GetPackageNameAndVersionFromAppx( + [MarshalAs(UnmanagedType.LPWStr)] string appxPath, + [MarshalAs(UnmanagedType.LPWStr)] out string outName, + out PackageVersion outVersion); } } diff --git a/src/RunnerV2/RunnerV2/Runner.cs b/src/RunnerV2/RunnerV2/Runner.cs index 2c170fb869..a9ad773826 100644 --- a/src/RunnerV2/RunnerV2/Runner.cs +++ b/src/RunnerV2/RunnerV2/Runner.cs @@ -19,6 +19,7 @@ using ManagedCommon; using RunnerV2.Helpers; using RunnerV2.ModuleInterfaces; using Update; +using Windows.ApplicationModel; using static RunnerV2.NativeMethods; namespace RunnerV2 @@ -40,6 +41,7 @@ namespace RunnerV2 new AwakeModuleInterface(), new CmdNotFoundModuleInterface(), new ColorPickerModuleInterface(), + new CommandPaletteModuleInterface(), ]; internal static bool Run(Action afterInitializationAction) diff --git a/src/RunnerV2/RunnerV2/RunnerV2.csproj b/src/RunnerV2/RunnerV2/RunnerV2.csproj index 6776e6acc1..32a7eed81f 100644 --- a/src/RunnerV2/RunnerV2/RunnerV2.csproj +++ b/src/RunnerV2/RunnerV2/RunnerV2.csproj @@ -15,6 +15,7 @@ + diff --git a/src/common/interop/PowerToys.Interop.vcxproj b/src/common/interop/PowerToys.Interop.vcxproj index ca29e69cce..3378fba48c 100644 --- a/src/common/interop/PowerToys.Interop.vcxproj +++ b/src/common/interop/PowerToys.Interop.vcxproj @@ -93,6 +93,7 @@ + CommonManaged.idl diff --git a/src/common/interop/PowerToys.Interop.vcxproj.filters b/src/common/interop/PowerToys.Interop.vcxproj.filters index 6fa51a3275..3f48175818 100644 --- a/src/common/interop/PowerToys.Interop.vcxproj.filters +++ b/src/common/interop/PowerToys.Interop.vcxproj.filters @@ -54,6 +54,9 @@ Header Files + + Header Files + diff --git a/src/common/utils/package.h b/src/common/utils/package.h index 138f3b8e5b..73ba876dc4 100644 --- a/src/common/utils/package.h +++ b/src/common/utils/package.h @@ -4,469 +4,124 @@ #include #include -#include -#include #include -#include #include #include -#include -#include -#include #include "../logger/logger.h" -#include "../version/version.h" -namespace package +using namespace winrt::Windows::Foundation; +using Microsoft::WRL::ComPtr; + +struct PACKAGE_VERSION { - using namespace winrt::Windows::Foundation; - using namespace winrt::Windows::ApplicationModel; - using namespace winrt::Windows::Management::Deployment; - using Microsoft::WRL::ComPtr; + UINT16 Major; + UINT16 Minor; + UINT16 Build; + UINT16 Revision; +}; - inline BOOL IsWin11OrGreater() +class ComInitializer +{ +public: + explicit ComInitializer(DWORD coInitFlags = COINIT_MULTITHREADED) : + _initialized(false) { - OSVERSIONINFOEX osvi{}; - DWORDLONG dwlConditionMask = 0; - byte op = VER_GREATER_EQUAL; - - // Initialize the OSVERSIONINFOEX structure. - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_WINTHRESHOLD); - osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_WINTHRESHOLD); - // Windows 11 build number - osvi.dwBuildNumber = 22000; - - // Initialize the condition mask. - VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); - VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); - VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, op); - - // Perform the test. - return VerifyVersionInfo( - &osvi, - VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, - dwlConditionMask); + const HRESULT hr = CoInitializeEx(nullptr, coInitFlags); + _initialized = SUCCEEDED(hr); } - struct PACKAGE_VERSION + ~ComInitializer() { - UINT16 Major; - UINT16 Minor; - UINT16 Build; - UINT16 Revision; - }; + if (_initialized) + { + CoUninitialize(); + } + } - class ComInitializer + bool Succeeded() const { return _initialized; } + +private: + bool _initialized; +}; + +__declspec(dllexport) EXTERN_C bool GetPackageNameAndVersionFromAppx( + const std::wstring& appxPath, + std::wstring& outName, + PACKAGE_VERSION& outVersion) +{ + try { - public: - explicit ComInitializer(DWORD coInitFlags = COINIT_MULTITHREADED) : - _initialized(false) + ComInitializer comInit; + if (!comInit.Succeeded()) { - 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 factory; - ComPtr stream; - ComPtr reader; - ComPtr manifest; - ComPtr 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((version >> 48) & 0xFFFF); - outVersion.Minor = static_cast((version >> 32) & 0xFFFF); - outVersion.Build = static_cast((version >> 16) & 0xFFFF); - outVersion.Revision = static_cast(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())); + Logger::error(L"COM initialization failed."); return false; } - catch (...) - { - Logger::error(L"Unknown or non-standard exception occurred."); + + ComPtr factory; + ComPtr stream; + ComPtr reader; + ComPtr manifest; + ComPtr packageId; + + HRESULT hr = CoCreateInstance(__uuidof(AppxFactory), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)); + if (FAILED(hr)) return false; - } - } - - inline std::optional GetRegisteredPackage(std::wstring packageDisplayName, bool checkVersion) - { - PackageManager packageManager; - - for (const auto& package : packageManager.FindPackagesForUser({})) - { - const auto& packageFullName = std::wstring{ package.Id().FullName() }; - const auto& packageVersion = package.Id().Version(); - - if (packageFullName.contains(packageDisplayName)) - { - // If checkVersion is true, verify if the package has the same version as PowerToys. - if ((!checkVersion) || (packageVersion.Major == VERSION_MAJOR && packageVersion.Minor == VERSION_MINOR && packageVersion.Revision == VERSION_REVISION)) - { - return { package }; - } - } - } - - return {}; - } - - inline bool IsPackageRegisteredWithPowerToysVersion(std::wstring packageDisplayName) - { - return GetRegisteredPackage(packageDisplayName, true).has_value(); - } - - inline bool RegisterSparsePackage(const std::wstring& externalLocation, const std::wstring& sparsePkgPath) - { - try - { - Uri externalUri{ externalLocation }; - Uri packageUri{ sparsePkgPath }; - - PackageManager packageManager; - - // Declare use of an external location - AddPackageOptions options; - options.ExternalLocationUri(externalUri); - options.ForceUpdateFromAnyVersion(true); - - IAsyncOperationWithProgress deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options); - deploymentOperation.get(); - - // Check the status of the operation - if (deploymentOperation.Status() == AsyncStatus::Error) - { - auto deploymentResult{ deploymentOperation.GetResults() }; - auto errorCode = deploymentOperation.ErrorCode(); - auto errorText = deploymentResult.ErrorText(); - - Logger::error(L"Register {} package failed. ErrorCode: {}, ErrorText: {}", sparsePkgPath, std::to_wstring(errorCode), errorText); - return false; - } - else if (deploymentOperation.Status() == AsyncStatus::Canceled) - { - Logger::error(L"Register {} package canceled.", sparsePkgPath); - return false; - } - else if (deploymentOperation.Status() == AsyncStatus::Completed) - { - Logger::info(L"Register {} package completed.", sparsePkgPath); - } - else - { - Logger::debug(L"Register {} package started.", sparsePkgPath); - } - - return true; - } - catch (std::exception& e) - { - Logger::error("Exception thrown while trying to register package: {}", e.what()); + hr = SHCreateStreamOnFileEx(appxPath.c_str(), STGM_READ | STGM_SHARE_DENY_WRITE, FILE_ATTRIBUTE_NORMAL, FALSE, nullptr, &stream); + if (FAILED(hr)) return false; - } - } - inline bool UnRegisterPackage(const std::wstring& pkgDisplayName) - { - try - { - PackageManager packageManager; - const static auto packages = packageManager.FindPackagesForUser({}); - - for (auto const& package : packages) - { - const auto& packageFullName = std::wstring{ package.Id().FullName() }; - - if (packageFullName.contains(pkgDisplayName)) - { - auto deploymentOperation{ packageManager.RemovePackageAsync(packageFullName) }; - deploymentOperation.get(); - - // Check the status of the operation - if (deploymentOperation.Status() == AsyncStatus::Error) - { - auto deploymentResult{ deploymentOperation.GetResults() }; - auto errorCode = deploymentOperation.ErrorCode(); - auto errorText = deploymentResult.ErrorText(); - - Logger::error(L"Unregister {} package failed. ErrorCode: {}, ErrorText: {}", packageFullName, std::to_wstring(errorCode), errorText); - } - else if (deploymentOperation.Status() == AsyncStatus::Canceled) - { - Logger::error(L"Unregister {} package canceled.", packageFullName); - } - else if (deploymentOperation.Status() == AsyncStatus::Completed) - { - Logger::info(L"Unregister {} package completed.", packageFullName); - } - else - { - Logger::debug(L"Unregister {} package started.", packageFullName); - } - - break; - } - } - } - catch (std::exception& e) - { - Logger::error("Exception thrown while trying to unregister package: {}", e.what()); + 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((version >> 48) & 0xFFFF); + outVersion.Minor = static_cast((version >> 32) & 0xFFFF); + outVersion.Build = static_cast((version >> 16) & 0xFFFF); + outVersion.Revision = static_cast(version & 0xFFFF); + + Logger::info(L"Package name: {}, version: {}.{}.{}.{}, appxPath: {}", + outName, + outVersion.Major, + outVersion.Minor, + outVersion.Build, + outVersion.Revision, + appxPath); return true; } - - inline std::vector FindMsixFile(const std::wstring& directoryPath, bool recursive) + catch (const std::exception& ex) { - if (directoryPath.empty()) - { - return {}; - } - - if (!std::filesystem::exists(directoryPath)) - { - Logger::error(L"The directory '" + directoryPath + L"' does not exist."); - return {}; - } - - const std::regex pattern(R"(^.+\.(appx|msix|msixbundle)$)", std::regex_constants::icase); - std::vector matchedFiles; - - try - { - if (recursive) - { - for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) - { - if (entry.is_regular_file()) - { - const auto& fileName = entry.path().filename().string(); - if (std::regex_match(fileName, pattern)) - { - matchedFiles.push_back(entry.path()); - } - } - } - } - else - { - for (const auto& entry : std::filesystem::directory_iterator(directoryPath)) - { - if (entry.is_regular_file()) - { - const auto& fileName = entry.path().filename().string(); - if (std::regex_match(fileName, pattern)) - { - matchedFiles.push_back(entry.path()); - } - } - } - } - } - catch (const std::exception& ex) - { - Logger::error("An error occurred while searching for MSIX files: " + std::string(ex.what())); - } - - 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); + Logger::error(L"Standard exception: {}", winrt::to_hstring(ex.what())); return false; } - - inline bool RegisterPackage(std::wstring pkgPath, std::vector dependencies) + catch (...) { - try - { - Uri packageUri{ pkgPath }; - - PackageManager packageManager; - - // Declare use of an external location - DeploymentOptions options = DeploymentOptions::ForceTargetApplicationShutdown; - - Collections::IVector uris = winrt::single_threaded_vector(); - if (!dependencies.empty()) - { - for (const auto& dependency : dependencies) - { - try - { - if (IsPackageSatisfied(dependency)) - { - Logger::info(L"Dependency already satisfied: {}", dependency); - } - else - { - uris.Append(Uri(dependency)); - } - } - catch (const winrt::hresult_error& ex) - { - Logger::error(L"Error creating Uri for dependency: %s", ex.message().c_str()); - } - } - } - - IAsyncOperationWithProgress deploymentOperation = packageManager.AddPackageAsync(packageUri, uris, options); - deploymentOperation.get(); - - // Check the status of the operation - if (deploymentOperation.Status() == AsyncStatus::Error) - { - auto deploymentResult{ deploymentOperation.GetResults() }; - auto errorCode = deploymentOperation.ErrorCode(); - auto errorText = deploymentResult.ErrorText(); - - Logger::error(L"Register {} package failed. ErrorCode: {}, ErrorText: {}", pkgPath, std::to_wstring(errorCode), errorText); - return false; - } - else if (deploymentOperation.Status() == AsyncStatus::Canceled) - { - Logger::error(L"Register {} package canceled.", pkgPath); - return false; - } - else if (deploymentOperation.Status() == AsyncStatus::Completed) - { - Logger::info(L"Register {} package completed.", pkgPath); - } - else - { - Logger::debug(L"Register {} package started.", pkgPath); - } - } - catch (std::exception& e) - { - Logger::error("Exception thrown while trying to register package: {}", e.what()); - - return false; - } - - return true; + Logger::error(L"Unknown or non-standard exception occurred."); + return false; } } diff --git a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj deleted file mode 100644 index 433e7599d5..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - 17.0 - Win32Proj - {0adeb797-c8c7-4ffa-acd5-2af6cad7ecd8} - CmdPalModuleInterface - 10.0 - PowerToys.CmdPalModuleInterface - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - ..\..\..\..\$(Platform)\$(Configuration)\ - - - - {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} - - - {6955446d-23f7-4023-9bb3-8657f904af99} - - - - - - EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL; - %(PreprocessorDefinitions); - - - IS_DEV_BRANDING;%(PreprocessorDefinitions) - - ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories) - - - $(OutDir)$(TargetName)$(TargetExt) - - - - - - - - - - Create - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj.filters b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj.filters deleted file mode 100644 index 1b2723105d..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - - - Source Files - - - Source Files - - - - - - \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp deleted file mode 100644 index 7c6a7926db..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "pch.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -HINSTANCE g_hInst_cmdPal = 0; - -BOOL APIENTRY DllMain(HMODULE hInstance, - DWORD ul_reason_for_call, - LPVOID) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - g_hInst_cmdPal = hInstance; - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - -class CmdPal : public PowertoyModuleIface -{ -private: - std::wstring app_name; - - //contains the non localized key of the powertoy - std::wstring app_key; - - HANDLE m_hTerminateEvent; - - // Track if this is the first call to enable - bool firstEnableCall = true; - - static bool LaunchApp(const std::wstring& appPath, const std::wstring& commandLineArgs, bool elevated, bool silentFail) - { - std::wstring dir = std::filesystem::path(appPath).parent_path(); - - SHELLEXECUTEINFO sei = { 0 }; - sei.cbSize = sizeof(SHELLEXECUTEINFO); - sei.hwnd = nullptr; - sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE; - if (silentFail) - { - sei.fMask = sei.fMask | SEE_MASK_FLAG_NO_UI; - } - sei.lpVerb = elevated ? L"runas" : L"open"; - sei.lpFile = appPath.c_str(); - sei.lpParameters = commandLineArgs.c_str(); - sei.lpDirectory = dir.c_str(); - sei.nShow = SW_SHOWNORMAL; - - if (!ShellExecuteEx(&sei)) - { - std::wstring error = get_last_error_or_default(GetLastError()); - Logger::error(L"Failed to launch process. {}", error); - return false; - } - - m_launched.store(true); - return true; - } - - std::vector GetProcessesIdByName(const std::wstring& processName) - { - std::vector processIds; - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - - if (snapshot != INVALID_HANDLE_VALUE) - { - PROCESSENTRY32 processEntry; - processEntry.dwSize = sizeof(PROCESSENTRY32); - - if (Process32First(snapshot, &processEntry)) - { - do - { - if (_wcsicmp(processEntry.szExeFile, processName.c_str()) == 0) - { - processIds.push_back(processEntry.th32ProcessID); - } - } while (Process32Next(snapshot, &processEntry)); - } - - CloseHandle(snapshot); - } - - return processIds; - } - - void TerminateCmdPal() - { - auto processIds = GetProcessesIdByName(L"Microsoft.CmdPal.UI.exe"); - - if (processIds.size() == 0) - { - Logger::trace(L"Nothing To PROCESS_TERMINATE"); - return; - } - - for (DWORD pid : processIds) - { - HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid); - - if (hProcess != NULL) - { - SetEvent(m_hTerminateEvent); - - // Wait for 1.5 seconds for the process to end correctly, allowing time for ETW tracer and extensions to stop - if (WaitForSingleObject(hProcess, 1500) == WAIT_TIMEOUT) - { - TerminateProcess(hProcess, 0); - } - - CloseHandle(hProcess); - } - } - } - -public: - static std::atomic m_enabled; - static std::atomic m_launched; - - CmdPal() - { - app_name = L"CmdPal"; - app_key = L"CmdPal"; - LoggerHelpers::init_logger(app_key, L"ModuleInterface", "CmdPal"); - - m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::CMDPAL_EXIT_EVENT); - } - - ~CmdPal() - { - CmdPal::m_enabled.store(false); - } - - // Destroy the powertoy and free memory - virtual void destroy() override - { - Logger::trace("CmdPal::destroy()"); - TerminateCmdPal(); - delete this; - } - - // Return the localized display name of the powertoy - virtual const wchar_t* get_name() override - { - return app_name.c_str(); - } - - // Return the non localized key of the powertoy, this will be cached by the runner - virtual const wchar_t* get_key() override - { - return app_key.c_str(); - } - - // Return the configured status for the gpo policy for the module - virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override - { - return powertoys_gpo::getConfiguredCmdPalEnabledValue(); - } - - virtual bool get_config(wchar_t* buffer, int* buffer_size) override - { - HINSTANCE hinstance = reinterpret_cast(&__ImageBase); - - // Create a Settings object. - PowerToysSettings::Settings settings(hinstance, get_name()); - - return settings.serialize_to_buffer(buffer, buffer_size); - } - - virtual void call_custom_action(const wchar_t* /*action*/) override - { - } - - virtual void set_config(const wchar_t* config) override - { - try - { - // Parse the input JSON string. - PowerToysSettings::PowerToyValues values = - PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); - - // If you don't need to do any custom processing of the settings, proceed - // to persists the values calling: - values.save_to_settings_file(); - // Otherwise call a custom function to process the settings before saving them to disk: - // save_settings(); - } - catch (std::exception&) - { - // Improper JSON. - } - } - - virtual void enable() - { - Logger::trace("CmdPal::enable()"); - - CmdPal::m_enabled.store(true); - - std::wstring packageName = L"Microsoft.CommandPalette"; - // Launch CmdPal as normal user using explorer - std::wstring launchPath = L"explorer.exe"; - std::wstring launchArgs = L"x-cmdpal://background"; -#ifdef IS_DEV_BRANDING - packageName = L"Microsoft.CommandPalette.Dev"; -#endif - - if (!package::GetRegisteredPackage(packageName, false).has_value()) - { - try - { - Logger::info(L"CmdPal not installed. Installing..."); - - std::wstring installationFolder = get_module_folderpath(); -#ifdef _DEBUG - std::wstring archSubdir = L"x64"; -#ifdef _M_ARM64 - archSubdir = L"ARM64"; -#endif - auto msix = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\", false); - auto dependencies = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\Dependencies\\" + archSubdir + L"\\", true); -#else - auto msix = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\", false); - auto dependencies = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\Dependencies\\", true); -#endif - - if (!msix.empty()) - { - auto msixPath = msix[0]; - - if (!package::RegisterPackage(msixPath, dependencies)) - { - Logger::error(L"Failed to install CmdPal package"); - } - } - } - catch (std::exception& e) - { - std::string errorMessage{ "Exception thrown while trying to install CmdPal package: " }; - errorMessage += e.what(); - Logger::error(errorMessage); - } - } - - if (!package::GetRegisteredPackage(packageName, false).has_value()) - { - Logger::error("Cmdpal is not registered, quit.."); - return; - } - - if (!firstEnableCall) - { - Logger::trace("Not first attempt, try to launch"); - LaunchApp(launchPath, launchArgs, false /*no elevated*/, false /*error pop up*/); - } - else - { - // If first time enable, do retry launch. - Logger::trace("First attempt, try to launch"); - std::thread launchThread(&CmdPal::RetryLaunch, launchPath, launchArgs); - launchThread.detach(); - } - - firstEnableCall = false; - } - - virtual void disable() - { - Logger::trace("CmdPal::disable()"); - TerminateCmdPal(); - - CmdPal::m_enabled.store(false); - } - - static void RetryLaunch(std::wstring path, std::wstring cmdArgs) - { - const int base_delay_milliseconds = 1000; - int max_retry = 9; // 2**9 - 1 seconds. Control total wait time within 10 min. - int retry = 0; - do - { - auto launch_result = LaunchApp(path, cmdArgs, false, retry < max_retry); - if (launch_result) - { - Logger::info(L"CmdPal launched successfully after {} retries.", retry); - return; - } - else - { - Logger::error(L"Retry {} launch CmdPal launch failed.", retry); - } - - // When we got max retry, we don't need to wait for the next retry. - if (retry < max_retry) - { - int delay = base_delay_milliseconds * (1 << (retry)); - std::this_thread::sleep_for(std::chrono::milliseconds(delay)); - } - ++retry; - } while (retry <= max_retry && m_enabled.load() && !m_launched.load()); - - if (!m_enabled.load() || m_launched.load()) - { - Logger::error(L"Retry cancelled. CmdPal is disabled or already launched."); - } - else - { - Logger::error(L"CmdPal launch failed after {} attempts.", retry); - } - } - - virtual bool on_hotkey(size_t) override - { - return false; - } - - virtual size_t get_hotkeys(Hotkey*, size_t) override - { - return 0; - } - - virtual bool is_enabled() override - { - return CmdPal::m_enabled.load(); - } -}; - -std::atomic CmdPal::m_enabled{ false }; -std::atomic CmdPal::m_launched{ false }; - -extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() -{ - return new CmdPal(); -} diff --git a/src/modules/cmdpal/CmdPalModuleInterface/packages.config b/src/modules/cmdpal/CmdPalModuleInterface/packages.config deleted file mode 100644 index 09bfc449e2..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalModuleInterface/pch.cpp b/src/modules/cmdpal/CmdPalModuleInterface/pch.cpp deleted file mode 100644 index 64b7eef6d6..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/src/modules/cmdpal/CmdPalModuleInterface/pch.h b/src/modules/cmdpal/CmdPalModuleInterface/pch.h deleted file mode 100644 index 30600d2e25..0000000000 --- a/src/modules/cmdpal/CmdPalModuleInterface/pch.h +++ /dev/null @@ -1,16 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -#include - -#include -#include -#include - -#endif //PCH_H