mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
MSIX: prompt and uninstall MSI PT version (#1248)
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include <common/common.h>
|
||||
#include <common/dpi_aware.h>
|
||||
|
||||
#include <common/msi_to_msix_upgrade_lib/msi_to_msix_upgrade.h>
|
||||
#include <common/winstore.h>
|
||||
#include <common/notifications.h>
|
||||
|
||||
@@ -22,6 +23,17 @@
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
namespace localized_strings
|
||||
{
|
||||
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
const wchar_t MSI_VERSION_MUTEX_NAME[] = L"Local\\PowerToyRunMutex";
|
||||
const wchar_t MSIX_VERSION_MUTEX_NAME[] = L"Local\\PowerToyMSIXRunMutex";
|
||||
}
|
||||
|
||||
void chdir_current_executable()
|
||||
{
|
||||
// Change current directory to the path of the executable.
|
||||
@@ -34,6 +46,47 @@ void chdir_current_executable()
|
||||
}
|
||||
}
|
||||
|
||||
wil::unique_mutex_nothrow create_runner_mutex(const bool msix_version)
|
||||
{
|
||||
wchar_t username[UNLEN + 1];
|
||||
DWORD username_length = UNLEN + 1;
|
||||
GetUserNameW(username, &username_length);
|
||||
wil::unique_mutex_nothrow result{ CreateMutexW(nullptr, TRUE, (std::wstring(msix_version ? MSIX_VERSION_MUTEX_NAME : MSI_VERSION_MUTEX_NAME) + username).c_str()) };
|
||||
|
||||
return GetLastError() == ERROR_ALREADY_EXISTS ? wil::unique_mutex_nothrow{} : std::move(result);
|
||||
}
|
||||
|
||||
bool start_msi_uninstallation_sequence()
|
||||
{
|
||||
const auto package_path = get_msi_package_path();
|
||||
|
||||
if (package_path.empty())
|
||||
{
|
||||
// No MSI version detected
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!offer_msi_uninstallation())
|
||||
{
|
||||
// User declined to uninstall or opted for "Don't show again"
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring action_runner_path{ winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path() };
|
||||
action_runner_path += L"\\action_runner.exe";
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS };
|
||||
sei.lpFile = action_runner_path.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = L"-uninstall_msi";
|
||||
ShellExecuteExW(&sei);
|
||||
WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
DWORD exit_code = 0;
|
||||
GetExitCodeProcess(sei.hProcess, &exit_code);
|
||||
CloseHandle(sei.hProcess);
|
||||
return exit_code == 0;
|
||||
}
|
||||
|
||||
int runner(bool isProcessElevated)
|
||||
{
|
||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||
@@ -44,15 +97,16 @@ int runner(bool isProcessElevated)
|
||||
//init_global_error_handlers();
|
||||
#endif
|
||||
Trace::RegisterProvider();
|
||||
winrt::init_apartment();
|
||||
start_tray_icon();
|
||||
if (winstore::running_as_packaged())
|
||||
{
|
||||
notifications::register_background_toast_handler();
|
||||
}
|
||||
int result;
|
||||
|
||||
int result = -1;
|
||||
try
|
||||
{
|
||||
if (winstore::running_as_packaged())
|
||||
{
|
||||
notifications::register_background_toast_handler();
|
||||
}
|
||||
|
||||
chdir_current_executable();
|
||||
// Load Powertyos DLLS
|
||||
// For now only load known DLLs
|
||||
@@ -95,18 +149,43 @@ int runner(bool isProcessElevated)
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
WCHAR username[UNLEN + 1];
|
||||
DWORD username_length = UNLEN + 1;
|
||||
GetUserNameW(username, &username_length);
|
||||
auto runner_mutex = CreateMutexW(nullptr, TRUE, (std::wstring(L"Local\\PowerToyRunMutex") + username).c_str());
|
||||
if (runner_mutex == nullptr || GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
auto msix_mutex = create_runner_mutex(true);
|
||||
const bool msix_mutex_failed_to_lock = !msix_mutex;
|
||||
if (msix_mutex_failed_to_lock)
|
||||
{
|
||||
// The app is already running
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto msi_mutex = create_runner_mutex(false);
|
||||
const bool msi_mutex_already_taken = !msi_mutex;
|
||||
if (msi_mutex_already_taken)
|
||||
{
|
||||
const bool declined_uninstall = !start_msi_uninstallation_sequence();
|
||||
|
||||
if (declined_uninstall)
|
||||
{
|
||||
// Warn and exit if msi version is already running
|
||||
notifications::show_toast(localized_strings::MSI_VERSION_IS_ALREADY_RUNNING);
|
||||
// Wait 1 second before exiting, since if we exit immediately, the toast notification becomes lost
|
||||
Sleep(1000);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
try
|
||||
{
|
||||
winrt::init_apartment();
|
||||
|
||||
if (winstore::running_as_packaged())
|
||||
{
|
||||
notifications::register_background_toast_handler();
|
||||
|
||||
std::thread{ [] {
|
||||
start_msi_uninstallation_sequence();
|
||||
} }.detach();
|
||||
}
|
||||
// Singletons initialization order needs to be preserved, first events and
|
||||
// then modules to guarantee the reverse destruction order.
|
||||
SystemMenuHelperInstace();
|
||||
@@ -134,8 +213,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
MessageBoxW(nullptr, std::wstring(err_what.begin(), err_what.end()).c_str(), GET_RESOURCE_STRING(IDS_ERROR).c_str(), MB_OK | MB_ICONERROR);
|
||||
result = -1;
|
||||
}
|
||||
ReleaseMutex(runner_mutex);
|
||||
CloseHandle(runner_mutex);
|
||||
|
||||
if (is_restart_scheduled())
|
||||
{
|
||||
if (restart_if_scheduled() == false)
|
||||
|
||||
4
src/runner/packages.config
Normal file
4
src/runner/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.190716.2" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -23,3 +23,8 @@
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include <wil/resource.h>
|
||||
@@ -18,7 +18,10 @@
|
||||
<ProjectName>runner</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
@@ -65,6 +68,7 @@
|
||||
<Link>
|
||||
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>Msi.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>false</EnableDpiAwareness>
|
||||
@@ -90,6 +94,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>Msi.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>false</EnableDpiAwareness>
|
||||
@@ -223,8 +228,20 @@
|
||||
<ProjectReference Include="..\common\common.vcxproj">
|
||||
<Project>{74485049-c722-400f-abe5-86ac52d929b3}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\msi_to_msix_upgrade_lib\msi_to_msix_upgrade_lib.vcxproj">
|
||||
<Project>{17da04df-e393-4397-9cf0-84dabe11032e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</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.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -136,4 +136,7 @@
|
||||
<Filter>svgs</Filter>
|
||||
</CopyFileToFolders>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user