mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
Switch to named pipes
Unregister package on uninstall Remove unneeded files Cleanup
This commit is contained in:
@@ -221,8 +221,11 @@
|
||||
<Custom Action="UnApplyModulesRegistryChangeSets" Before="RemoveFiles">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>-->
|
||||
@@ -369,8 +372,16 @@
|
||||
DllEntry="UnApplyModulesRegistryChangeSetsCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="UnRegisterContextMenuPackages"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UnRegisterContextMenuPackagesCA"
|
||||
/>
|
||||
|
||||
<!-- Close 'PowerToys.exe' before uninstall-->
|
||||
|
||||
<!-- Close 'PowerToys.exe' before uninstall-->
|
||||
<Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
|
||||
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />
|
||||
<util:CloseApplication CloseMessage="yes" Target="PowerToys.exe" ElevatedCloseMessage="yes" RebootPrompt="no" TerminateProcess="0" />
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "../../src/common/updating/installer.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
HINSTANCE DLL_HANDLE = nullptr;
|
||||
@@ -912,7 +916,7 @@ LExit:
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
PMSIHANDLE hRecord = MsiCreateRecord(0);
|
||||
MsiRecordSetString(hRecord, 0, TEXT("Filed to iminstall virtual camera driver"));
|
||||
MsiRecordSetString(hRecord, 0, TEXT("Failed to uninstall virtual camera driver"));
|
||||
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||
}
|
||||
|
||||
@@ -920,6 +924,78 @@ LExit:
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UnRegisterContextMenuPackagesCA"); // original func name is too long
|
||||
|
||||
try
|
||||
{
|
||||
// Packages to unregister
|
||||
const std::vector<std::wstring> packagesToRemoveDisplayName{ { L"PowerRenameContextMenu" } };
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
for (auto const& package : packageManager.FindPackages())
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
|
||||
for (const auto& packageToRemove : packagesToRemoveDisplayName)
|
||||
{
|
||||
if (packageFullName.contains(packageToRemove))
|
||||
{
|
||||
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);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
Logger::error(L"Unregister {} package canceled.", packageFullName);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
Logger::info(L"Unregister {} package completed.", packageFullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug(L"Unregister {} package started.", packageFullName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
std::string errorMessage{ "Exception thrown while trying to unregister sparse packages: " };
|
||||
errorMessage += e.what();
|
||||
Logger::error(errorMessage);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
|
||||
er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
|
||||
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
@@ -14,10 +14,10 @@ EXPORTS
|
||||
TelemetryLogRepairCancelCA
|
||||
TelemetryLogRepairFailCA
|
||||
TerminateProcessesCA
|
||||
TerminateProcessesCA
|
||||
CertifyVirtualCameraDriverCA
|
||||
InstallVirtualCameraDriverCA
|
||||
InstallEmbeddedMSIXCA
|
||||
UnApplyModulesRegistryChangeSetsCA
|
||||
UninstallVirtualCameraDriverCA
|
||||
UnRegisterContextMenuPackagesCA
|
||||
UninstallEmbeddedMSIXCA
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\wix.props"
|
||||
Condition="Exists('..\wix.props')" />
|
||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Import Project="..\wix.props" Condition="Exists('..\wix.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{32f3882b-f2d6-4586-b5ed-11e39e522bd3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
@@ -43,7 +43,6 @@
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>..\..\src\common\Telemetry;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>inc;..\..\src\;..\..\src\common\Telemetry;telemetry;$(WixSdkPath)VS2017\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@@ -56,7 +55,6 @@
|
||||
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
@@ -65,7 +63,6 @@
|
||||
<AdditionalLibraryDirectories>$(WixSdkPath)VS2017\lib\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
@@ -127,5 +124,14 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>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}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -37,6 +37,12 @@
|
||||
<Extensions>
|
||||
<desktop4:Extension Category="windows.fileExplorerContextMenus">
|
||||
<desktop4:FileExplorerContextMenus>
|
||||
<desktop5:ItemType Type="Directory">
|
||||
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="Directory\Background">
|
||||
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="*">
|
||||
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
|
||||
</desktop5:ItemType>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// PowerRenameContextMenu.cpp : Defines the exported functions for the DLL.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
#include "framework.h"
|
||||
#include "PowerRenameContextMenu.h"
|
||||
|
||||
|
||||
// This is an example of an exported variable
|
||||
POWERRENAMECONTEXTMENU_API int nPowerRenameContextMenu=0;
|
||||
|
||||
// This is an example of an exported function.
|
||||
POWERRENAMECONTEXTMENU_API int fnPowerRenameContextMenu(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is the constructor of a class that has been exported.
|
||||
CPowerRenameContextMenu::CPowerRenameContextMenu()
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// The following ifdef block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the POWERRENAMECONTEXTMENU_EXPORTS
|
||||
// symbol defined on the command line. This symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// POWERRENAMECONTEXTMENU_API functions as being imported from a DLL, whereas this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
#ifdef POWERRENAMECONTEXTMENU_EXPORTS
|
||||
#define POWERRENAMECONTEXTMENU_API __declspec(dllexport)
|
||||
#else
|
||||
#define POWERRENAMECONTEXTMENU_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
// This class is exported from the dll
|
||||
class POWERRENAMECONTEXTMENU_API CPowerRenameContextMenu {
|
||||
public:
|
||||
CPowerRenameContextMenu(void);
|
||||
// TODO: add your methods here.
|
||||
};
|
||||
|
||||
extern POWERRENAMECONTEXTMENU_API int nPowerRenameContextMenu;
|
||||
|
||||
POWERRENAMECONTEXTMENU_API int fnPowerRenameContextMenu(void);
|
||||
@@ -84,7 +84,6 @@ MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Comma
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="PowerRenameContextMenu.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -92,7 +91,6 @@ MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Comma
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerRenameContextMenu.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerRenameContextMenu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -29,9 +26,6 @@
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="PowerRenameContextMenu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -41,6 +35,177 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="PowerRenameUI.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PowerRenameContextMenu.rc">
|
||||
@@ -48,9 +213,6 @@
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="PowerRenameUI.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\BadgeLogo.scale-125.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
@@ -543,12 +705,6 @@
|
||||
<Image Include="Assets\*.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\*.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\BadgeLogo.scale-100.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Assets\BadgeLogo.scale-125.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
|
||||
@@ -22,12 +22,15 @@
|
||||
#include <trace.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <shellapi.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
HINSTANCE g_hInst = 0;
|
||||
|
||||
#define BUFSIZE 4096 * 4
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
@@ -94,34 +97,11 @@ public:
|
||||
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
|
||||
try
|
||||
{
|
||||
HWND parent = nullptr;
|
||||
if (m_site)
|
||||
{
|
||||
ComPtr<IOleWindow> oleWindow;
|
||||
RETURN_IF_FAILED(m_site.As(&oleWindow));
|
||||
RETURN_IF_FAILED(oleWindow->GetWindow(&parent));
|
||||
}
|
||||
|
||||
std::wostringstream title;
|
||||
title << Title();
|
||||
|
||||
if (selection)
|
||||
{
|
||||
DWORD count;
|
||||
RETURN_IF_FAILED(selection->GetCount(&count));
|
||||
title << L" (" << count << L" selected items)";
|
||||
RunPowerRename(selection);
|
||||
}
|
||||
else
|
||||
{
|
||||
title << L"(no selected items)";
|
||||
}
|
||||
std::filesystem::path modulePath{ wil::GetModuleFileNameW<std::wstring>() };
|
||||
std::wstring path = get_module_folderpath(g_hInst);
|
||||
path = path + L"\\PowerToys.PowerRename.exe";
|
||||
std::wstring iconResourcePath = get_module_filename();
|
||||
|
||||
MessageBox(parent, iconResourcePath.c_str(), iconResourcePath.c_str(), MB_OK);
|
||||
RunPowerRename(selection);
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
@@ -149,111 +129,110 @@ protected:
|
||||
ComPtr<IUnknown> m_site;
|
||||
|
||||
private:
|
||||
HRESULT RunPowerRename(IShellItemArray* psiItemArray)
|
||||
|
||||
HRESULT StartNamedPipeServerAndSendData(std::wstring pipe_name, IShellItemArray* psiItemArray)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
HWND parent = nullptr;
|
||||
if (m_site)
|
||||
hPipe = CreateNamedPipe(
|
||||
pipe_name.c_str(),
|
||||
PIPE_ACCESS_DUPLEX |
|
||||
WRITE_DAC,
|
||||
PIPE_TYPE_MESSAGE |
|
||||
PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES,
|
||||
BUFSIZE,
|
||||
BUFSIZE,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (hPipe == NULL || hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ComPtr<IOleWindow> oleWindow;
|
||||
RETURN_IF_FAILED(m_site.As(&oleWindow));
|
||||
RETURN_IF_FAILED(oleWindow->GetWindow(&parent));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// This call blocks until a client process connects to the pipe
|
||||
BOOL connected = ConnectNamedPipe(hPipe, NULL);
|
||||
if (!connected)
|
||||
{
|
||||
if (GetLastError() == ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT RunPowerRename(IShellItemArray* psiItemArray)
|
||||
{
|
||||
if (CSettingsInstance().GetEnabled())
|
||||
{
|
||||
Trace::Invoked();
|
||||
// Set the application path based on the location of the dll
|
||||
std::wstring path = get_module_folderpath(g_hInst);
|
||||
path = path + L"\\PowerToys.PowerRename.exe";
|
||||
LPTSTR lpApplicationName = (LPTSTR)path.c_str();
|
||||
// Create an anonymous pipe to stream filenames
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
HANDLE hReadPipe;
|
||||
HANDLE hWritePipe;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
|
||||
|
||||
std::wstring pipe_name(L"\\\\.\\pipe\\powertoys_powerrenameinput_");
|
||||
UUID temp_uuid;
|
||||
wchar_t* uuid_chars = nullptr;
|
||||
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
auto val = get_last_error_message(GetLastError());
|
||||
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L"");
|
||||
}
|
||||
if (!SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT, 0))
|
||||
else if (UuidToString(&temp_uuid, (RPC_WSTR*)&uuid_chars) != RPC_S_OK)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
CAtlFile writePipe(hWritePipe);
|
||||
|
||||
CString commandLine;
|
||||
commandLine.Format(_T("\"%s\""), lpApplicationName);
|
||||
int nSize = commandLine.GetLength() + 1;
|
||||
LPTSTR lpszCommandLine = new TCHAR[nSize];
|
||||
_tcscpy_s(lpszCommandLine, nSize, commandLine);
|
||||
|
||||
STARTUPINFO startupInfo;
|
||||
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
|
||||
startupInfo.cb = sizeof(STARTUPINFO);
|
||||
startupInfo.hStdInput = hReadPipe;
|
||||
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
startupInfo.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
PROCESS_INFORMATION processInformation;
|
||||
|
||||
// Start the resizer
|
||||
CreateProcess(
|
||||
NULL,
|
||||
lpszCommandLine,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInformation);
|
||||
|
||||
RunNonElevatedEx(path.c_str(), {}, get_module_folderpath(g_hInst));
|
||||
|
||||
delete[] lpszCommandLine;
|
||||
if (!CloseHandle(processInformation.hProcess))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
if (!CloseHandle(processInformation.hThread))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
auto val = get_last_error_message(GetLastError());
|
||||
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L"");
|
||||
}
|
||||
|
||||
//m_pdtobj will be NULL when invoked from the MSIX build as Initialize is never called (IShellExtInit functions aren't called in case of MSIX).
|
||||
DWORD fileCount = 0;
|
||||
// Gets the list of files currently selected using the IShellItemArray
|
||||
psiItemArray->GetCount(&fileCount);
|
||||
// Iterate over the list of files
|
||||
for (DWORD i = 0; i < fileCount; i++)
|
||||
if (uuid_chars != nullptr)
|
||||
{
|
||||
IShellItem* shellItem;
|
||||
psiItemArray->GetItemAt(i, &shellItem);
|
||||
LPWSTR itemName;
|
||||
// Retrieves the entire file system path of the file from its shell item
|
||||
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName);
|
||||
CString fileName(itemName);
|
||||
// File name can't contain '?'
|
||||
fileName.Append(_T("?"));
|
||||
// Write the file path into the input stream for image resizer
|
||||
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
|
||||
pipe_name += std::wstring(uuid_chars);
|
||||
RpcStringFree((RPC_WSTR*)&uuid_chars);
|
||||
uuid_chars = nullptr;
|
||||
}
|
||||
create_pipe_thread = std::thread(&PowerRenameContextMenuCommand::StartNamedPipeServerAndSendData, this, pipe_name, psiItemArray);
|
||||
RunNonElevatedEx(path.c_str(), pipe_name, get_module_folderpath(g_hInst));
|
||||
create_pipe_thread.join();
|
||||
|
||||
if (hPipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CAtlFile writePipe(hPipe);
|
||||
|
||||
DWORD fileCount = 0;
|
||||
// Gets the list of files currently selected using the IShellItemArray
|
||||
psiItemArray->GetCount(&fileCount);
|
||||
// Iterate over the list of files
|
||||
for (DWORD i = 0; i < fileCount; i++)
|
||||
{
|
||||
IShellItem* shellItem;
|
||||
psiItemArray->GetItemAt(i, &shellItem);
|
||||
LPWSTR itemName;
|
||||
// Retrieves the entire file system path of the file from its shell item
|
||||
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName);
|
||||
CString fileName(itemName);
|
||||
// File name can't contain '?'
|
||||
fileName.Append(_T("?"));
|
||||
// Write the file path into the input stream for image resizer
|
||||
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
|
||||
}
|
||||
writePipe.Close();
|
||||
}
|
||||
writePipe.Close();
|
||||
}
|
||||
Trace::InvokedRet(hr);
|
||||
Trace::InvokedRet(S_OK);
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
std::thread create_pipe_thread;
|
||||
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
std::wstring app_name = L"PowerRename";
|
||||
};
|
||||
|
||||
|
||||
@@ -53,15 +53,61 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
|
||||
{
|
||||
LoggerHelpers::init_logger(moduleName, L"", LogSettings::powerRenameLoggerName);
|
||||
|
||||
#define BUFSIZE 4096 * 4
|
||||
auto args = std::wstring{ GetCommandLine() };
|
||||
size_t pos{ args.rfind(' ') };
|
||||
|
||||
std::wstring pipe_name;
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
pipe_name = args.substr(pos + 1);
|
||||
}
|
||||
|
||||
|
||||
HANDLE hStdin;
|
||||
|
||||
if (pipe_name.size() > 0)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
hStdin = CreateFile(
|
||||
pipe_name.c_str(), // pipe name
|
||||
GENERIC_READ | GENERIC_WRITE, // read and write
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
// Break if the pipe handle is valid.
|
||||
if (hStdin != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
// Exit if an error other than ERROR_PIPE_BUSY occurs.
|
||||
auto error = GetLastError();
|
||||
if (error != ERROR_PIPE_BUSY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WaitNamedPipe(pipe_name.c_str(), 3))
|
||||
{
|
||||
printf("Could not open pipe: 20 second wait timed out.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
}
|
||||
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (hStdin == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Logger::error(L"Invalid input handle.");
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
#define BUFSIZE 4096 * 4
|
||||
|
||||
BOOL bSuccess;
|
||||
WCHAR chBuf[BUFSIZE];
|
||||
DWORD dwRead;
|
||||
@@ -86,6 +132,7 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
|
||||
if (!bSuccess)
|
||||
break;
|
||||
}
|
||||
CloseHandle(hStdin);
|
||||
|
||||
Logger::debug(L"Starting PowerRename with {} files selected", g_files.size());
|
||||
|
||||
|
||||
@@ -10,13 +10,103 @@
|
||||
#include <common/utils/resources.h>
|
||||
#include "Generated Files/resource.h"
|
||||
#include <atomic>
|
||||
#include <versionhelpers.h>
|
||||
#include <dll/PowerRenameConstants.h>
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
std::atomic<DWORD> g_dwModuleRefCount = 0;
|
||||
HINSTANCE g_hInst = 0;
|
||||
|
||||
#define STATUS_SUCCESS 0x00000000
|
||||
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
|
||||
namespace
|
||||
{
|
||||
RTL_OSVERSIONINFOW GetRealOSVersion()
|
||||
{
|
||||
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
|
||||
if (hMod)
|
||||
{
|
||||
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
|
||||
if (fxPtr != nullptr)
|
||||
{
|
||||
RTL_OSVERSIONINFOW info = { 0 };
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
if (STATUS_SUCCESS == fxPtr(&info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
RTL_OSVERSIONINFOW info = { 0 };
|
||||
return info;
|
||||
}
|
||||
|
||||
bool IsWindows11()
|
||||
{
|
||||
auto info = GetRealOSVersion();
|
||||
return info.dwMajorVersion >= 10 && info.dwBuildNumber >= 22000;
|
||||
}
|
||||
|
||||
|
||||
bool RegisterSparsePackage(std::wstring externalLocation, std::wstring sparsePkgPath)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
try
|
||||
{
|
||||
Uri externalUri{ externalLocation };
|
||||
Uri packageUri{ sparsePkgPath };
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
// Declare use of an external location
|
||||
AddPackageOptions options;
|
||||
options.ExternalLocationUri(externalUri);
|
||||
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> 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 PowerRenameContextMenu package failed. ErrorCode: {}, ErrorText: {}", std::to_wstring(errorCode), errorText);
|
||||
return false;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
Logger::error(L"Register PowerRenameContextMenu package canceled.");
|
||||
return false;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
Logger::info(L"Register PowerRenameContextMenu package completed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug(L"Register PowerRenameContextMenu package started.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
std::string errorMessage{ "Exception thrown while trying to register PowerRenameContextMenu package: " };
|
||||
errorMessage += e.what();
|
||||
Logger::error(errorMessage);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
class CPowerRenameClassFactory : public IClassFactory
|
||||
{
|
||||
public:
|
||||
@@ -164,64 +254,6 @@ private:
|
||||
std::wstring app_key;
|
||||
|
||||
public:
|
||||
bool registerSparsePackage(std::wstring externalLocation, std::wstring sparsePkgPath)
|
||||
{
|
||||
bool registration = false;
|
||||
try
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
Uri externalUri{ externalLocation };
|
||||
Uri packageUri{ sparsePkgPath };
|
||||
|
||||
// Console.WriteLine("exe Location {0}", externalLocation);
|
||||
// Console.WriteLine("msix Address {0}", sparsePkgPath);
|
||||
|
||||
// Console.WriteLine(" exe Uri {0}", externalUri);
|
||||
// Console.WriteLine(" msix Uri {0}", packageUri);
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
// Declare use of an external location
|
||||
AddPackageOptions options;
|
||||
options.ExternalLocationUri(externalUri);
|
||||
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);
|
||||
//IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
|
||||
deploymentOperation.get();
|
||||
|
||||
int returnValue = 0;
|
||||
// Check the status of the operation
|
||||
if (deploymentOperation.Status() == AsyncStatus::Error)
|
||||
{
|
||||
auto deploymentResult{ deploymentOperation.GetResults() };
|
||||
auto errorCode = deploymentOperation.ErrorCode();
|
||||
auto errorText = deploymentResult.ErrorText().c_str();
|
||||
returnValue = 1;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
returnValue = 1;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
returnValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = 1;
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
// Other progress and error-handling code omitted for brevity...
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Return the localized display name of the powertoy
|
||||
@@ -239,13 +271,16 @@ public:
|
||||
// Enable the powertoy
|
||||
virtual void enable()
|
||||
{
|
||||
std::wstring path = get_module_folderpath(g_hInst);
|
||||
std::wstring packageUri = path + L"\\PowerRenameContextMenuPackage.msix";
|
||||
//std::wstring externalLocation = L"C:\\Users\\stefan\\Projects\\PowerToys\\x64\\Debug\\modules\\PowerRename";
|
||||
//std::wstring packageUri = L"C:\\Users\\stefan\\Projects\\PowerToys\\src\\modules\\powerrename\\PowerRenameContextMenu\\MyPackage.msix";
|
||||
registerSparsePackage(path, packageUri);
|
||||
Logger::info(L"PowerRename enabled");
|
||||
m_enabled = true;
|
||||
|
||||
if (IsWindows11())
|
||||
{
|
||||
std::wstring path = get_module_folderpath(g_hInst);
|
||||
std::wstring packageUri = path + L"\\PowerRenameContextMenuPackage.msix";
|
||||
RegisterSparsePackage(path, packageUri);
|
||||
}
|
||||
|
||||
save_settings();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user