mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-23 19:49:17 +08:00
[Setup] Use WiX bootstrapper instead of a custom one (#15050)
@dhowett gave approval on teams. Squash merging
This commit is contained in:
parent
244a3b936e
commit
3d59c797f9
23
.github/actions/spell-check/expect.txt
vendored
23
.github/actions/spell-check/expect.txt
vendored
@ -122,12 +122,16 @@ AWAYMODE
|
||||
AYUV
|
||||
backend
|
||||
backtracer
|
||||
BAEC
|
||||
BAF
|
||||
bak
|
||||
bbwe
|
||||
bck
|
||||
Bcl
|
||||
BEEE
|
||||
betadele
|
||||
betsegaw
|
||||
BFB
|
||||
BGR
|
||||
bgra
|
||||
BGSOUNDS
|
||||
@ -157,6 +161,7 @@ boolalpha
|
||||
Bools
|
||||
Boostrapper
|
||||
bootstrapper
|
||||
BOOTSTRAPPERINSTALLFOLDER
|
||||
Bopomofo
|
||||
BOTTOMALIGN
|
||||
BPBF
|
||||
@ -175,6 +180,7 @@ buf
|
||||
BUFSIZE
|
||||
bugreport
|
||||
Buid
|
||||
BUILDARCH
|
||||
buildtransitive
|
||||
BValue
|
||||
bytearray
|
||||
@ -195,6 +201,7 @@ CDeclaration
|
||||
CDEF
|
||||
cdpx
|
||||
CENTERALIGN
|
||||
CFDB
|
||||
cguid
|
||||
changecursor
|
||||
Changemove
|
||||
@ -352,6 +359,8 @@ Datavalue
|
||||
DATAW
|
||||
davidegiacometti
|
||||
Dayof
|
||||
DBCD
|
||||
DBDA
|
||||
dbg
|
||||
Dbghelp
|
||||
DBLCLKS
|
||||
@ -367,6 +376,7 @@ declspec
|
||||
decltype
|
||||
Dedup
|
||||
deduplicate
|
||||
DEFAULTBOOTSTRAPPERINSTALLFOLDER
|
||||
DEFAULTCOLOR
|
||||
DEFAULTFLAGS
|
||||
DEFAULTONLY
|
||||
@ -477,6 +487,9 @@ dwrite
|
||||
dxgi
|
||||
dxgiformat
|
||||
dxguid
|
||||
EAF
|
||||
EBA
|
||||
EBE
|
||||
ecount
|
||||
ededf
|
||||
EDITKEYBOARD
|
||||
@ -484,6 +497,8 @@ editkeyboardwindow
|
||||
editorconfig
|
||||
EDITSHORTCUTS
|
||||
editshortcutswindow
|
||||
EFBD
|
||||
efgh
|
||||
EFile
|
||||
egistry
|
||||
ekus
|
||||
@ -551,7 +566,10 @@ FANCYZONESDRAWLAYOUTTEST
|
||||
FANCYZONESEDITOR
|
||||
Farbraum
|
||||
FARPROC
|
||||
FBF
|
||||
FCCD
|
||||
fdw
|
||||
FEEBD
|
||||
feimage
|
||||
ffaa
|
||||
fff
|
||||
@ -850,6 +868,8 @@ INPUTTYPE
|
||||
INSTALLDESKTOPSHORTCUT
|
||||
INSTALLDIR
|
||||
INSTALLFOLDER
|
||||
INSTALLFOLDERTOBOOTSTRAPPERINSTALLFOLDER
|
||||
INSTALLFOLDERTOPREVIOUSINSTALLFOLDER
|
||||
INSTALLLOCATION
|
||||
INSTALLLOGATTRIBUTES
|
||||
INSTALLLOGMODE
|
||||
@ -1365,6 +1385,7 @@ outro
|
||||
outsettings
|
||||
OVERLAPPEDWINDOW
|
||||
overlaywindow
|
||||
Overridable
|
||||
OWNDC
|
||||
PACL
|
||||
PAINTSTRUCT
|
||||
@ -1463,6 +1484,7 @@ previewer
|
||||
PREVIEWHANDLERFRAMEINFO
|
||||
previewpane
|
||||
previouscamera
|
||||
PREVIOUSINSTALLFOLDER
|
||||
PREVIOUSVERSIONSINSTALLED
|
||||
prevpane
|
||||
prgms
|
||||
@ -2100,6 +2122,7 @@ wcsncmp
|
||||
wcsnicmp
|
||||
wdp
|
||||
wdupenv
|
||||
We'd
|
||||
weakme
|
||||
webcam
|
||||
webpage
|
||||
|
@ -4,7 +4,7 @@
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"!(ModernWpf)*.resources.dll",
|
||||
"*.resources.dll",
|
||||
|
||||
"PowerToysSetupCustomActions.dll",
|
||||
|
||||
|
5
.pipelines/build-installer-MSI.cmd
Normal file
5
.pipelines/build-installer-MSI.cmd
Normal file
@ -0,0 +1,5 @@
|
||||
cd /D "%~dp0"
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64 -winsdk=10.0.18362.0
|
||||
SET IsPipeline=1
|
||||
call msbuild ../installer/PowerToysSetup.sln /target:PowerToysInstaller /p:Configuration=Release /p:Platform=x64 /p:CIBuild=true || exit /b 1
|
@ -93,25 +93,6 @@ steps:
|
||||
msbuildArgs: ${{ parameters.additionalBuildArguments }}
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: Restore NuGet packages for PowerToysBootstrapper.sln
|
||||
inputs:
|
||||
command: restore
|
||||
feedsToUse: config
|
||||
configPath: NuGet.config
|
||||
restoreSolution: installer\PowerToysBootstrapper\PowerToysBootstrapper.sln
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\installer\PowerToysBootstrapper\packages'
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build PowerToysBootstrapper.sln'
|
||||
inputs:
|
||||
solution: '**\installer\PowerToysBootstrapper\PowerToysBootstrapper.sln'
|
||||
vsVersion: 16.0
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: ${{ parameters.additionalBuildArguments }}
|
||||
maximumCpuCount: true
|
||||
|
||||
# directly not doing WinAppDriver testing
|
||||
- task: VSTest@2
|
||||
displayName: 'MS Tests'
|
||||
|
@ -211,7 +211,7 @@ jobs:
|
||||
inputs:
|
||||
solution: '**/installer/PowerToysSetup.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
msbuildArgs: /p:CIBuild=true /target:PowerToysInstaller /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: true
|
||||
@ -231,7 +231,7 @@ jobs:
|
||||
- task: VSBuild@1
|
||||
displayName: Build Bootstrapper
|
||||
inputs:
|
||||
solution: '**/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln'
|
||||
solution: '**/installer/PowerToysSetup.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
@ -239,11 +239,53 @@ jobs:
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Insignia: Extract Engine from Bundle'
|
||||
inputs:
|
||||
script: '.\installer\packages\WiX.3.11.2\tools\insignia.exe -ib installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\engine.exe'
|
||||
|
||||
|
||||
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
||||
displayName: 'ESRP CodeSigning (Engine)'
|
||||
inputs:
|
||||
ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
|
||||
FolderPath: 'installer'
|
||||
Pattern: engine.exe
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: |
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"PageHash": "/NPH",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Insignia: Merge Engine into Bundle'
|
||||
inputs:
|
||||
script: '.\installer\packages\WiX.3.11.2\tools\insignia.exe -ab installer\engine.exe installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe'
|
||||
|
||||
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
||||
displayName: Sign Boostrapper
|
||||
inputs:
|
||||
ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
|
||||
FolderPath: 'installer/PowerToysBootstrapper/$(BuildPlatform)\$(BuildConfiguration)'
|
||||
FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
@ -6,4 +6,4 @@ We use the awesome [spdlog](https://github.com/gabime/spdlog) library for loggin
|
||||
<Import Project="..\..\..\deps\spdlog.props" />
|
||||
```
|
||||
It'll add the required include dirs and link the library binary itself.
|
||||
You can see many example usage of the library in its repository or in the [bootstrapper project](../../installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp).
|
||||
|
||||
|
@ -66,7 +66,6 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done
|
||||
2. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below)
|
||||
3. Compile `WebcamReportTool.sln` tool. Path from root: `tools\WebcamReportTool\WebcamReportTool.sln` (details listed below)
|
||||
4. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below)
|
||||
5. Compile `PowerToysBootstrapper.sln` Path from root: `installer\PowerToysBootstrapper\PowerToysBootstrapper.sln` (details listed below)
|
||||
|
||||
### Prerequisites for building the MSI installer
|
||||
|
||||
@ -85,7 +84,7 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done
|
||||
2. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release`
|
||||
3. From the `Build` menu, choose `Build Solution`.
|
||||
|
||||
### Locally compiling the .MSI installer
|
||||
### Locally compiling the installer
|
||||
|
||||
1. Open `installer\PowerToysSetup.sln`
|
||||
2. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release`
|
||||
@ -93,14 +92,6 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done
|
||||
|
||||
The resulting `PowerToysSetup.msi` installer will be available in the `installer\PowerToysSetup\x64\Release\` folder.
|
||||
|
||||
### Locally compiling the .EXE Bootstrapper installer
|
||||
|
||||
1. Open `installer\PowerToysBootstrapper\PowerToysBootstrapper.sln`
|
||||
2. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release`
|
||||
3. From the `Build` menu choose `Build Solution`.
|
||||
|
||||
The `PowerToysSetup-0.0.1-x64.exe` binary is created in the `installer\PowerToysBootstrapper\x64\Release\` folder.
|
||||
|
||||
#### Supported arguments for the .EXE Bootstrapper installer
|
||||
|
||||
Head over to the wiki to see the [full list of supported installer arguments][installerArgWiki].
|
||||
|
@ -1,43 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30320.27
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bootstrapper", "bootstrapper\bootstrapper.vcxproj", "{D194E3AA-F824-4CA9-9A58-034DD6B7D022}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\..\src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetttingsAPI", "..\..\src\common\SettingsAPI\SetttingsAPI.vcxproj", "{6955446D-23F7-4023-9BB3-8657F904AF99}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Debug|x64.Build.0 = Debug|x64
|
||||
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Release|x64.ActiveCfg = Release|x64
|
||||
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Release|x64.Build.0 = Release|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B288A538-1B79-4782-A737-14CD9CF07F58}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,90 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "DotnetInstallation.h"
|
||||
|
||||
#include <common/utils/exec.h>
|
||||
#include <common/utils/HttpClient.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace updating
|
||||
{
|
||||
constexpr size_t REQUIRED_MINIMAL_PATCH = 20;
|
||||
|
||||
bool dotnet_is_installed()
|
||||
{
|
||||
auto runtimes = exec_and_read_output(LR"(dotnet --list-runtimes)");
|
||||
if (!runtimes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::regex dotnet3_1_x{ R"(Microsoft\.WindowsDesktop\.App\s3\.1\.(\d+))" };
|
||||
|
||||
size_t latestPatchInstalled = 0;
|
||||
using rexit = std::sregex_iterator;
|
||||
for (auto it = rexit{ begin(*runtimes), end(*runtimes), dotnet3_1_x }; it != rexit{}; ++it)
|
||||
{
|
||||
if (!it->ready() || it->size() < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto patchNumberGroup = (*it)[1];
|
||||
if (!patchNumberGroup.matched)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto patchString = patchNumberGroup.str();
|
||||
size_t patch = 0;
|
||||
if (auto [_, ec] = std::from_chars(&*begin(patchString), &*end(patchString), patch); ec == std::errc())
|
||||
{
|
||||
latestPatchInstalled = std::max(patch, latestPatchInstalled);
|
||||
}
|
||||
}
|
||||
return latestPatchInstalled >= REQUIRED_MINIMAL_PATCH;
|
||||
}
|
||||
|
||||
std::optional<fs::path> download_dotnet()
|
||||
{
|
||||
const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/93c69a29-d379-4a5d-bb9e-3116cc14de41/907bbc52446d8bb7baa0c6faebde1d44/windowsdesktop-runtime-3.1.20-win-x64.exe";
|
||||
const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime.exe";
|
||||
|
||||
auto dotnet_download_path = fs::temp_directory_path() / DOTNET_DESKTOP_FILENAME;
|
||||
winrt::Windows::Foundation::Uri download_link{ DOTNET_DESKTOP_DOWNLOAD_LINK };
|
||||
|
||||
const size_t max_attempts = 3;
|
||||
bool download_success = false;
|
||||
for (size_t i = 0; i < max_attempts; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
http::HttpClient client;
|
||||
client.download(download_link, dotnet_download_path).wait();
|
||||
download_success = true;
|
||||
break;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// couldn't download
|
||||
}
|
||||
}
|
||||
return download_success ? std::make_optional(dotnet_download_path) : std::nullopt;
|
||||
}
|
||||
|
||||
bool install_dotnet(fs::path dotnet_download_path, const bool silent = false)
|
||||
{
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE };
|
||||
sei.lpFile = dotnet_download_path.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
std::wstring dotnet_flags = L"/install ";
|
||||
dotnet_flags += silent ? L"/quiet" : L"/passive";
|
||||
sei.lpParameters = dotnet_flags.c_str();
|
||||
if (ShellExecuteExW(&sei) != TRUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
CloseHandle(sei.hProcess);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
namespace updating
|
||||
{
|
||||
bool dotnet_is_installed();
|
||||
std::optional<fs::path> download_dotnet();
|
||||
bool install_dotnet(fs::path dotnet_download_path, const bool silent);
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="BOOTSTRAPPER_PROGRESS_TITLE" xml:space="preserve">
|
||||
<value>PowerToys Installer</value>
|
||||
</data>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE" xml:space="preserve">
|
||||
<value>Couldn't download .NET Core Desktop Runtime 3.1, please install it manually.</value>
|
||||
</data>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
|
||||
<value>PowerToys installation error</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
|
||||
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
|
||||
</data>
|
||||
<data name="INSTALLER_EXTRACT_ERROR" xml:space="preserve">
|
||||
<value>Couldn't extract MSI installer.</value>
|
||||
</data>
|
||||
<data name="EXTRACTING_INSTALLER" xml:space="preserve">
|
||||
<value>Extracting PowerToys MSI...</value>
|
||||
</data>
|
||||
<data name="UNINSTALL_PREVIOUS_VERSION_ERROR" xml:space="preserve">
|
||||
<value>Couldn't uninstall previous PowerToys version.</value>
|
||||
</data>
|
||||
<data name="DOWNLOADING_DOTNET" xml:space="preserve">
|
||||
<value>Downloading .NET Core...</value>
|
||||
</data>
|
||||
<data name="DOTNET_INSTALL_ERROR" xml:space="preserve">
|
||||
<value>Couldn't install .NET Core.</value>
|
||||
</data>
|
||||
<data name="NEW_VERSION_INSTALLATION_ERROR" xml:space="preserve">
|
||||
<value>Couldn't install new PowerToys version.</value>
|
||||
</data>
|
||||
<data name="NEWER_VERSION_ERROR" xml:space="preserve">
|
||||
<value>A newer version is already installed.</value>
|
||||
</data>
|
||||
<data name="OLD_WINDOWS_ERROR" xml:space="preserve">
|
||||
<value>PowerToys requires Windows 10 version 1903 (May 2019 Update) or newer to run.</value>
|
||||
</data>
|
||||
</root>
|
@ -1,41 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../src/common/version/version.h"
|
||||
|
||||
MAINICON ICON "../../../src/runner/svgs/icon.ico"
|
||||
IDR_BIN_ICON BIN "../../../src/runner/svgs/icon.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
|
||||
#include "Generated Files\installer_resource.rc"
|
@ -1,527 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
#include "RcResource.h"
|
||||
#include <common/version/helper.h>
|
||||
#include <common/version/version.h>
|
||||
#include <common/utils/appMutex.h>
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/MsiUtils.h>
|
||||
#include <common/utils/os-detect.h>
|
||||
#include <common/utils/processApi.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/window.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include "DotnetInstallation.h"
|
||||
#include "progressbar_window.h"
|
||||
|
||||
static bool g_Silent = false;
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
namespace // Strings in this namespace should not be localized
|
||||
{
|
||||
const wchar_t APPLICATION_ID[] = L"PowerToysInstaller";
|
||||
const char EXE_LOG_FILENAME[] = "powertoys-bootstrapper-exe-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log";
|
||||
const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log";
|
||||
}
|
||||
|
||||
#undef STR
|
||||
#undef STR_HELPER
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::optional<fs::path> ExtractEmbeddedInstaller(const fs::path extractPath)
|
||||
{
|
||||
auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN");
|
||||
if (!executableRes)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::wstring msiName(L"PowerToysSetup-" STRINGIZE(VERSION_MAJOR) "." STRINGIZE(VERSION_MINOR) "." STRINGIZE(VERSION_REVISION) L"-");
|
||||
msiName += get_architecture_string(get_current_architecture()) + std::wstring(L".msi");
|
||||
auto installerPath = extractPath / msiName;
|
||||
return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt;
|
||||
}
|
||||
|
||||
void SetupLogger(fs::path directory, const spdlog::level::level_enum severity)
|
||||
{
|
||||
std::shared_ptr<spdlog::logger> logger;
|
||||
auto nullLogger = spdlog::null_logger_mt("null");
|
||||
try
|
||||
{
|
||||
if (severity != spdlog::level::off)
|
||||
{
|
||||
logger = spdlog::basic_logger_mt("file", (directory / EXE_LOG_FILENAME).wstring());
|
||||
|
||||
std::error_code _;
|
||||
const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR;
|
||||
const auto msiLogPath = directory / MSI_LOG_FILENAME;
|
||||
MsiEnableLogW(msiSev, msiLogPath.c_str(), INSTALLLOGATTRIBUTES_APPEND);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger = nullLogger;
|
||||
}
|
||||
|
||||
logger->set_pattern("[%L][%d-%m-%C-%T] %v");
|
||||
logger->set_level(severity);
|
||||
spdlog::set_default_logger(std::move(logger));
|
||||
spdlog::set_level(severity);
|
||||
spdlog::flush_every(std::chrono::seconds(5));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
spdlog::set_default_logger(nullLogger);
|
||||
}
|
||||
}
|
||||
|
||||
void CleanupSettingsFromOlderVersions()
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto logSettingsFile = fs::path{ PTSettingsHelper::get_root_save_folder_location() } / PTSettingsHelper::log_settings_filename;
|
||||
if (fs::is_regular_file(logSettingsFile))
|
||||
{
|
||||
fs::remove(logSettingsFile);
|
||||
spdlog::info("Removed old log settings file");
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::info("Old log settings file wasn't found");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
spdlog::error("Failed to cleanup old log settings");
|
||||
}
|
||||
}
|
||||
|
||||
void ShowMessageBoxError(const wchar_t* message)
|
||||
{
|
||||
if (!g_Silent)
|
||||
{
|
||||
MessageBoxW(nullptr,
|
||||
message,
|
||||
GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(),
|
||||
MB_OK | MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowMessageBoxError(const UINT messageId)
|
||||
{
|
||||
ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str());
|
||||
}
|
||||
|
||||
bool uninstall_msi_version(const std::wstring& package_path)
|
||||
{
|
||||
const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL");
|
||||
return ERROR_SUCCESS == uninstall_result;
|
||||
}
|
||||
|
||||
struct InstalledVersionInfo
|
||||
{
|
||||
VersionHelper version;
|
||||
std::wstring install_folder;
|
||||
};
|
||||
std::optional<InstalledVersionInfo> get_installed_powertoys_version()
|
||||
{
|
||||
auto installed_path = GetMsiPackageInstalledPath();
|
||||
if (!installed_path)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
std::wstring executable_path = *installed_path + L"\\PowerToys.exe";
|
||||
|
||||
// Get the version information for the file requested
|
||||
const DWORD fvSize = GetFileVersionInfoSizeW(executable_path.c_str(), nullptr);
|
||||
if (!fvSize)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto pbVersionInfo = std::make_unique<BYTE[]>(fvSize);
|
||||
|
||||
if (!GetFileVersionInfoW(executable_path.c_str(), 0, fvSize, pbVersionInfo.get()))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
VS_FIXEDFILEINFO* fileInfo = nullptr;
|
||||
UINT fileInfoLen = 0;
|
||||
if (!VerQueryValueW(pbVersionInfo.get(), L"\\", reinterpret_cast<LPVOID*>(&fileInfo), &fileInfoLen))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return InstalledVersionInfo{
|
||||
.version = VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff,
|
||||
(fileInfo->dwFileVersionMS >> 0) & 0xffff,
|
||||
(fileInfo->dwFileVersionLS >> 16) & 0xffff },
|
||||
.install_folder = std::move(*installed_path)
|
||||
};
|
||||
}
|
||||
|
||||
void ReLaunchElevatedAndExit()
|
||||
{
|
||||
std::wstring params;
|
||||
int nCmdArgs = 0;
|
||||
LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs);
|
||||
for (int i = 1; i < nCmdArgs; ++i)
|
||||
{
|
||||
if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos)
|
||||
{
|
||||
params += L'"';
|
||||
params += argList[i];
|
||||
params += L'"';
|
||||
}
|
||||
else
|
||||
{
|
||||
params += argList[i];
|
||||
}
|
||||
|
||||
if (i != nCmdArgs - 1)
|
||||
{
|
||||
params += L' ';
|
||||
}
|
||||
}
|
||||
|
||||
const auto processHandle = run_elevated(argList[0], params.c_str());
|
||||
if (!processHandle)
|
||||
{
|
||||
spdlog::error("Couldn't restart elevated: ({})", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0)
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(processHandle, &exitCode);
|
||||
std::exit(exitCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("Elevated setup process timed out after 60m: ({})", GetLastError());
|
||||
TerminateProcess(processHandle, 0);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int Bootstrapper(HINSTANCE hInstance)
|
||||
{
|
||||
winrt::init_apartment();
|
||||
|
||||
fs::path logDir = PTSettingsHelper::get_root_save_folder_location();
|
||||
|
||||
cxxopts::Options options{ "PowerToysBootstrapper" };
|
||||
|
||||
// clang-format off
|
||||
options.add_options()
|
||||
("h,help", "Show help")
|
||||
("no_full_ui", "Use reduced UI for MSI")
|
||||
("s,silent", "Suppress all UI, notifications and does not start PowerToys")
|
||||
("no_start_pt", "Do not launch PowerToys after the installation is complete")
|
||||
("start_pt", "Always launch PowerToys after the installation is complete")
|
||||
("skip_dotnet_install", "Skip dotnet 3.X installation even if it's not detected")
|
||||
("log_level", "Log level. Possible values: off|debug|error", cxxopts::value<std::string>()->default_value("off"))
|
||||
("log_dir", "Log directory", cxxopts::value<std::string>()->default_value(logDir.string()))
|
||||
("install_dir", "Installation directory", cxxopts::value<std::string>()->default_value(""))
|
||||
("extract_msi", "Extract MSI to the working directory and exit. Use only if you must access MSI directly.");
|
||||
// clang-format on
|
||||
|
||||
cxxopts::ParseResult cmdArgs;
|
||||
bool showHelp = false;
|
||||
try
|
||||
{
|
||||
cmdArgs = options.parse(__argc, const_cast<const char**>(__argv));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
showHelp = true;
|
||||
}
|
||||
|
||||
showHelp = showHelp || cmdArgs["help"].as<bool>();
|
||||
if (showHelp)
|
||||
{
|
||||
std::ostringstream helpMsg;
|
||||
helpMsg << options.help();
|
||||
MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_Silent = cmdArgs["silent"].as<bool>();
|
||||
const bool noFullUI = cmdArgs["no_full_ui"].as<bool>();
|
||||
const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as<bool>();
|
||||
const bool noStartPT = cmdArgs["no_start_pt"].as<bool>();
|
||||
const bool startPT = cmdArgs["start_pt"].as<bool>();
|
||||
const auto logLevel = cmdArgs["log_level"].as<std::string>();
|
||||
const auto logDirArg = cmdArgs["log_dir"].as<std::string>();
|
||||
const auto installDirArg = cmdArgs["install_dir"].as<std::string>();
|
||||
const bool extractMsiOnly = cmdArgs["extract_msi"].as<bool>();
|
||||
|
||||
std::wstring installFolderProp;
|
||||
if (!installDirArg.empty())
|
||||
{
|
||||
std::string installDir;
|
||||
if (installDirArg.find(' ') != std::string::npos)
|
||||
{
|
||||
installDir = "\"" + installDirArg + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
installDir = installDirArg;
|
||||
}
|
||||
|
||||
installFolderProp = std::wstring(installDir.length(), L' ');
|
||||
std::copy(installDir.begin(), installDir.end(), installFolderProp.begin());
|
||||
installFolderProp = L"INSTALLFOLDER=\"" + installFolderProp + L"\"";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
fs::path logDirArgPath = logDirArg;
|
||||
if (fs::exists(logDirArgPath) && fs::is_directory(logDirArgPath))
|
||||
{
|
||||
logDir = logDirArgPath;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
spdlog::level::level_enum severity = spdlog::level::debug;
|
||||
if (logLevel == "error")
|
||||
{
|
||||
severity = spdlog::level::err;
|
||||
}
|
||||
|
||||
SetupLogger(logDir, severity);
|
||||
spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly);
|
||||
|
||||
// If a user requested an MSI -> extract it and exit
|
||||
if (extractMsiOnly)
|
||||
{
|
||||
if (const auto installerPath = ExtractEmbeddedInstaller(fs::current_path()))
|
||||
{
|
||||
spdlog::debug("MSI installer extracted to {}", installerPath->string());
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("MSI installer couldn't be extracted");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
|
||||
|
||||
// Do not support installing on Windows < 1903
|
||||
if (!Is19H1OrHigher())
|
||||
{
|
||||
ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR);
|
||||
spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check if there's a newer version installed
|
||||
const auto installedVersionInfo = get_installed_powertoys_version();
|
||||
if (installedVersionInfo)
|
||||
{
|
||||
if (installedVersionInfo->version >= myVersion)
|
||||
{
|
||||
spdlog::error(L"Detected a newer version {} vs {}", installedVersionInfo->version.toWstring(), myVersion.toWstring());
|
||||
ShowMessageBoxError(IDS_NEWER_VERSION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
// If we are good to go and install folder wasn't specified via cmd line, make sure to retain the previous
|
||||
// installation path
|
||||
else if (installFolderProp.empty())
|
||||
{
|
||||
installFolderProp = L"INSTALLFOLDER=\"" + installedVersionInfo->install_folder + L"\"";
|
||||
}
|
||||
}
|
||||
|
||||
// Always elevate bootstrapper process since it invokes msiexec multiple times,
|
||||
// so we can avoid multiple UAC confirmations
|
||||
if (!is_process_elevated())
|
||||
{
|
||||
ReLaunchElevatedAndExit();
|
||||
}
|
||||
|
||||
// Setup MSI UI visibility
|
||||
if (!noFullUI)
|
||||
{
|
||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr);
|
||||
}
|
||||
|
||||
if (g_Silent)
|
||||
{
|
||||
MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr);
|
||||
}
|
||||
|
||||
// Try killing PowerToys and prevent future processes launch by acquiring app mutex
|
||||
for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE))
|
||||
{
|
||||
TerminateProcess(handle.get(), 0);
|
||||
}
|
||||
|
||||
auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME);
|
||||
auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME);
|
||||
if (!instanceMutex)
|
||||
{
|
||||
spdlog::error("Couldn't acquire PowerToys global mutex. Setup couldn't terminate PowerToys.exe process");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spdlog::debug("Extracting embedded MSI installer");
|
||||
const auto installerPath = ExtractEmbeddedInstaller(fs::temp_directory_path());
|
||||
if (!installerPath)
|
||||
{
|
||||
ShowMessageBoxError(IDS_INSTALLER_EXTRACT_ERROR);
|
||||
spdlog::error("Couldn't install the MSI installer ({})", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto removeExtractedInstaller = wil::scope_exit([&] {
|
||||
std::error_code _;
|
||||
fs::remove(*installerPath, _);
|
||||
});
|
||||
|
||||
spdlog::debug("Acquiring existing MSI package path if exists");
|
||||
const auto package_path = GetMsiPackagePath();
|
||||
if (!package_path.empty())
|
||||
{
|
||||
spdlog::debug(L"Existing MSI package path found: {}", package_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::debug("Existing MSI package path not found");
|
||||
}
|
||||
|
||||
if (!package_path.empty() && !uninstall_msi_version(package_path))
|
||||
{
|
||||
spdlog::error("Couldn't uninstall the existing MSI package ({})", GetLastError());
|
||||
ShowMessageBoxError(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const bool installDotnet = !skipDotnetInstall;
|
||||
if (!g_Silent)
|
||||
{
|
||||
OpenProgressBarDialog(hInstance, 0, GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), GET_RESOURCE_STRING(IDS_DOWNLOADING_DOTNET).c_str());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (installDotnet)
|
||||
{
|
||||
spdlog::debug("Detecting if dotnet is installed");
|
||||
const bool dotnetInstalled = updating::dotnet_is_installed();
|
||||
spdlog::debug("Dotnet is already installed: {}", dotnetInstalled);
|
||||
if (!dotnetInstalled)
|
||||
{
|
||||
bool installedSuccessfully = false;
|
||||
if (const auto dotnet_installer_path = updating::download_dotnet())
|
||||
{
|
||||
// Dotnet installer has its own progress bar
|
||||
CloseProgressBarDialog();
|
||||
installedSuccessfully = updating::install_dotnet(*dotnet_installer_path, g_Silent);
|
||||
if (!installedSuccessfully)
|
||||
{
|
||||
spdlog::error("Couldn't install dotnet");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("Couldn't download dotnet");
|
||||
}
|
||||
|
||||
if (!installedSuccessfully)
|
||||
{
|
||||
ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
spdlog::error("Unknown exception during dotnet installation");
|
||||
ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR);
|
||||
}
|
||||
|
||||
// At this point, there's no reason to show progress bar window, since MSI installers have their own
|
||||
CloseProgressBarDialog();
|
||||
|
||||
const std::wstring msiProps = installFolderProp;
|
||||
spdlog::debug("Launching MSI installation for new package {}", installerPath->string());
|
||||
const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS;
|
||||
if (!installationDone)
|
||||
{
|
||||
spdlog::error("Couldn't install new MSI package ({})", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
spdlog::debug("Installation completed");
|
||||
|
||||
if ((!noStartPT && !g_Silent) || startPT)
|
||||
{
|
||||
spdlog::debug("Starting the newly installed PowerToys.exe");
|
||||
auto newPTPath = GetMsiPackageInstalledPath();
|
||||
if (!newPTPath)
|
||||
{
|
||||
spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
*newPTPath += L"\\PowerToys.exe";
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE };
|
||||
sei.lpFile = newPTPath->c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
ShellExecuteExW(&sei);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hi, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Bootstrapper(hi);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
std::string messageA{ "Unhandled std exception encountered\n" };
|
||||
messageA.append(ex.what());
|
||||
|
||||
spdlog::error(messageA.c_str());
|
||||
|
||||
std::wstring messageW{};
|
||||
std::copy(messageA.begin(), messageA.end(), messageW.begin());
|
||||
ShowMessageBoxError(messageW.c_str());
|
||||
}
|
||||
catch (winrt::hresult_error const& ex)
|
||||
{
|
||||
std::wstring message{ L"Unhandled winrt exception encountered\n" };
|
||||
message.append(ex.message().c_str());
|
||||
|
||||
spdlog::error(message.c_str());
|
||||
|
||||
ShowMessageBoxError(message.c_str());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
auto lastErrorMessage = get_last_error_message(GetLastError());
|
||||
std::wstring message{ L"Unknown exception encountered\n" };
|
||||
message.append(lastErrorMessage ? std::move(*lastErrorMessage) : L"");
|
||||
|
||||
spdlog::error(message.c_str());
|
||||
|
||||
ShowMessageBoxError(message.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\src\Version.props" />
|
||||
<Target Name="Generate Resource file" BeforeTargets="PrepareForBuild">
|
||||
<ItemGroup>
|
||||
<RCLines Include="IDR_BIN_MSIINSTALLER BIN "..\\PowerToysSetup\\$(PlatformShortName)\\$(Configuration)\\PowerToysSetup-$(Version)-$(PlatformShortName).msi"" />
|
||||
</ItemGroup>
|
||||
<WriteLinesToFile File="Generated Files\installer_resource.rc" Lines="@(RCLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
||||
</Target>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)..\..\tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h bootstrapper.base.rc bootstrapper.rc 105" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{D194E3AA-F824-4CA9-9A58-034DD6B7D022}</ProjectGuid>
|
||||
<RootNamespace>bootstrapper</RootNamespace>
|
||||
<OverrideWindowsTargetPlatformVersion>true</OverrideWindowsTargetPlatformVersion>
|
||||
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>bootstrapper</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="..\..\..\deps\spdlog.props" />
|
||||
<Import Project="..\..\..\deps\cxxopts.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup>
|
||||
<TargetName>PowerToysSetup-$(Version)-$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>../;$(IncludePath)</IncludePath>
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>../;$(IncludePath)</IncludePath>
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation Condition="'$(CIBuild)'!='true'">true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../../src/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalOptions>/await /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation Condition="'$(CIBuild)'!='true'">true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../../src/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalOptions>/await /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bootstrapper.cpp" />
|
||||
<ClCompile Include="DotnetInstallation.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="progressbar_window.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DotnetInstallation.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="progressbar_window.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="bootstrapper.base.rc" />
|
||||
<None Include="packages.config" />
|
||||
<ResourceCompile Include="Generated Files/bootstrapper.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\runner\svgs\icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\SettingsAPI\SetttingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\common\version\version.vcxproj">
|
||||
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\logging\logging.vcxproj">
|
||||
<Project>{7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.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.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
@ -1 +0,0 @@
|
||||
#include "pch.h"
|
@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include <charconv>
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
#include <wil/resource.h>
|
||||
#include <Msi.h>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <sstream>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
#include <spdlog/sinks/null_sink.h>
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
|
||||
#pragma warning(push, 0)
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <cxxopts.hpp>
|
@ -1,187 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <common/utils/window.h>
|
||||
|
||||
#include "progressbar_window.h"
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
const int labelHeight = 18;
|
||||
|
||||
const int progressBarHeight = 20;
|
||||
const int margin = 10;
|
||||
|
||||
const int windowWidth = 480;
|
||||
const int titleBarHeight = 32;
|
||||
const int windowHeight = margin * 4 + progressBarHeight + labelHeight + titleBarHeight;
|
||||
|
||||
int progressBarSteps = 0;
|
||||
|
||||
HWND hDialog = nullptr;
|
||||
HWND hLabel = nullptr;
|
||||
HWND hProgressBar = nullptr;
|
||||
HBRUSH hBrush = nullptr;
|
||||
|
||||
std::wstring labelText;
|
||||
std::mutex uiThreadIsRunning;
|
||||
|
||||
namespace nonlocalized
|
||||
{
|
||||
const wchar_t windowClass[] = L"PTBProgressBarWnd";
|
||||
const wchar_t labelClass[] = L"static";
|
||||
}
|
||||
|
||||
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (Msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
uiThreadIsRunning.lock();
|
||||
|
||||
hLabel = CreateWindowW(nonlocalized::labelClass,
|
||||
labelText.c_str(),
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
|
||||
margin,
|
||||
margin,
|
||||
windowWidth - (margin * 4),
|
||||
labelHeight,
|
||||
hWnd,
|
||||
(HMENU)(501),
|
||||
(HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE), nullptr);
|
||||
|
||||
hProgressBar = CreateWindowExW(0,
|
||||
PROGRESS_CLASS,
|
||||
nullptr,
|
||||
WS_VISIBLE | WS_CHILD | PBS_SMOOTH,
|
||||
margin,
|
||||
(margin * 2) + labelHeight,
|
||||
windowWidth - (margin * 4),
|
||||
progressBarHeight,
|
||||
hWnd,
|
||||
(HMENU)(IDR_PROGRESS_BAR),
|
||||
(HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE),
|
||||
nullptr);
|
||||
|
||||
bool filledOnStart = false;
|
||||
if (progressBarSteps == 0)
|
||||
{
|
||||
progressBarSteps = 1;
|
||||
filledOnStart = true;
|
||||
}
|
||||
|
||||
SendMessageW(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, progressBarSteps));
|
||||
SendMessageW(hProgressBar, PBM_SETSTEP, 1, 0);
|
||||
|
||||
if (filledOnStart)
|
||||
{
|
||||
SendMessageW(hProgressBar, PBM_STEPIT, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
if (lParam == (LPARAM)hLabel)
|
||||
{
|
||||
if (!hBrush)
|
||||
{
|
||||
HDC hdcStatic = (HDC)wParam;
|
||||
SetTextColor(hdcStatic, RGB(0, 0, 0));
|
||||
SetBkColor(hdcStatic, RGB(255, 255, 255));
|
||||
hBrush = CreateSolidBrush(RGB(255, 255, 255));
|
||||
}
|
||||
|
||||
return (LRESULT)hBrush;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE:
|
||||
{
|
||||
DestroyWindow(hWnd);
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return DefWindowProcW(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenProgressBarDialog(HINSTANCE hInstance, const int nProgressbarSteps, const wchar_t* title, const wchar_t* label)
|
||||
{
|
||||
labelText = label;
|
||||
progressBarSteps = nProgressbarSteps;
|
||||
std::wstring window_title{ title };
|
||||
std::thread{
|
||||
[hInstance, window_title = std::move(window_title)] {
|
||||
INITCOMMONCONTROLSEX iccex{.dwSize = sizeof(iccex), .dwICC = ICC_NATIVEFNTCTL_CLASS | ICC_PROGRESS_CLASS };
|
||||
InitCommonControlsEx(&iccex);
|
||||
|
||||
WNDCLASSEX wc{};
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIconW(hInstance, MAKEINTRESOURCE(IDR_BIN_ICON));
|
||||
wc.hIconSm = LoadIconW(hInstance, MAKEINTRESOURCE(IDR_BIN_ICON));
|
||||
wc.lpszClassName = nonlocalized::windowClass;
|
||||
|
||||
if (!RegisterClassExW(&wc))
|
||||
{
|
||||
spdlog::warn("Couldn't register main_window class for progress bar.");
|
||||
return;
|
||||
}
|
||||
|
||||
RECT rect{};
|
||||
GetClientRect(GetDesktopWindow(), &rect);
|
||||
rect.left = rect.right / 2 - windowWidth / 2;
|
||||
rect.top = rect.bottom / 4 - windowHeight / 2;
|
||||
hDialog = CreateWindowExW(WS_EX_CLIENTEDGE,
|
||||
nonlocalized::windowClass,
|
||||
window_title.c_str(),
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX,
|
||||
rect.left,
|
||||
rect.top,
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
nullptr,
|
||||
nullptr,
|
||||
hInstance,
|
||||
nullptr);
|
||||
|
||||
if (!hDialog)
|
||||
{
|
||||
spdlog::warn("Couldn't create progress bar main_window");
|
||||
return;
|
||||
}
|
||||
|
||||
ShowWindow(hDialog, SW_SHOW);
|
||||
UpdateWindow(hDialog);
|
||||
run_message_loop();
|
||||
uiThreadIsRunning.unlock();
|
||||
}
|
||||
}.detach();
|
||||
}
|
||||
|
||||
void UpdateProgressBarDialog(const wchar_t* label)
|
||||
{
|
||||
SetWindowTextW(hLabel, label);
|
||||
SendMessageW(hProgressBar, PBM_STEPIT, 0, 0);
|
||||
}
|
||||
|
||||
void CloseProgressBarDialog()
|
||||
{
|
||||
SendMessageW(hDialog, WM_CLOSE, {}, {});
|
||||
{
|
||||
std::unique_lock waitForUIToExit{ uiThreadIsRunning };
|
||||
}
|
||||
|
||||
// Return focus to the current process, since it was lost due to progress bar closing (?)
|
||||
INPUT i = {INPUT_MOUSE, {}};
|
||||
SendInput(1, &i, sizeof(i));
|
||||
SetForegroundWindow(GetActiveWindow());
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
void OpenProgressBarDialog(HINSTANCE hInstance, const int nProgressbarSteps, const wchar_t* title, const wchar_t* label);
|
||||
void UpdateProgressBarDialog(const wchar_t* label);
|
||||
void CloseProgressBarDialog();
|
@ -1,17 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by bootstrapper.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys Bootstrapper"
|
||||
#define INTERNAL_NAME "bootstrapper"
|
||||
#define ORIGINAL_FILENAME "bootstrapper.exe"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
|
||||
#define IDR_BIN_MSIINSTALLER 103
|
||||
#define IDR_BIN_ICON 104
|
||||
#define IDR_PROGRESS_BAR 105
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29215.179
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysSetup", "PowerToysSetup\PowerToysSetup.wixproj", "{022A9D30-7C4F-416D-A9DF-5FF2661CC0AD}"
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysInstaller", "PowerToysSetup\PowerToysInstaller.wixproj", "{022A9D30-7C4F-416D-A9DF-5FF2661CC0AD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToysSetupCustomActions", "PowerToysSetupCustomActions\PowerToysSetupCustomActions.vcxproj", "{32F3882B-F2D6-4586-B5ED-11E39E522BD3}"
|
||||
EndProject
|
||||
@ -11,6 +11,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\src\logging\lo
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "..\src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}"
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysBootstrapper", "PowerToysSetup\PowerToysBootstrapper.wixproj", "{31D72625-43C1-41B1-B784-BCE4A8DC5543}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{022A9D30-7C4F-416D-A9DF-5FF2661CC0AD} = {022A9D30-7C4F-416D-A9DF-5FF2661CC0AD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -33,6 +38,10 @@ Global
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
|
||||
{31D72625-43C1-41B1-B784-BCE4A8DC5543}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{31D72625-43C1-41B1-B784-BCE4A8DC5543}.Debug|x64.Build.0 = Debug|x64
|
||||
{31D72625-43C1-41B1-B784-BCE4A8DC5543}.Release|x64.ActiveCfg = Release|x64
|
||||
{31D72625-43C1-41B1-B784-BCE4A8DC5543}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
66
installer/PowerToysSetup/PowerToys.wxs
Normal file
66
installer/PowerToysSetup/PowerToys.wxs
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?define UpgradeCode="6341382d-c0a9-4238-9188-be9607e3fab2"?>
|
||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||
<?define BinX64Dir="$(var.RepoDir)x64\$(var.Configuration)\" ?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
|
||||
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
|
||||
<Bundle Name="PowerToys (Preview) $(sys.BUILDARCH)"
|
||||
Version="$(var.Version)"
|
||||
Manufacturer="Microsoft Corporation"
|
||||
IconSourceFile="$(var.BinX64Dir)svgs\icon.ico"
|
||||
UpgradeCode="$(var.UpgradeCode)">
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication
|
||||
LicenseFile="$(var.RepoDir)\installer\License.rtf"
|
||||
LogoFile="$(var.RepoDir)\installer\MSIX\Images\logo44.png"
|
||||
SuppressOptionsUI="no"
|
||||
SuppressRepair="yes" />
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<util:FileSearch Variable="HasDotnet3122" Path="[ProgramFiles64Folder]dotnet\shared\Microsoft.WindowsDesktop.App\3.1.22\System.Xaml.dll" Result="exists" />
|
||||
|
||||
<Variable Name="InstallFolder" Type="string" Value="[ProgramFiles64Folder]PowerToys" bal:Overridable="yes"/>
|
||||
|
||||
|
||||
<!-- Only install/upgrade if the version is greater or equal than the currently installed version of PowerToys, to handle the case in which PowerToys was installed from old MSI (before WiX bootstrapper was used) -->
|
||||
<!-- If the previous installation is a bundle installation, just let WiX run its logic. -->
|
||||
<Variable Name="DetectedPowerToysVersion" Type="version" Value="0.0.0.0"/>
|
||||
<Variable Name="TargetPowerToysVersion" Type="version" Value="$(var.Version)"/>
|
||||
<util:ProductSearch Id="SearchInstalledPowerToysVersion" Variable="DetectedPowerToysVersion" UpgradeCode="42B84BF7-5FBF-473B-9C8B-049DC16F7708" Result="version" />
|
||||
<bal:Condition Message="A later version of PowerToys is already installed." >TargetPowerToysVersion >= DetectedPowerToysVersion OR WixBundleInstalled</bal:Condition>
|
||||
|
||||
<Variable Name="DetectedWindowsBuildNumber" Type="version" Value="0"/>
|
||||
<util:RegistrySearch Id="SearchWindowsBuildNumber" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="CurrentBuildNumber" Result="value" Format="raw" Variable="DetectedWindowsBuildNumber" />
|
||||
<bal:Condition Message="This application is only supported on Windows 10 version 1903 (build 18362) or higher.">DetectedWindowsBuildNumber >= 18362 OR WixBundleInstalled</bal:Condition>
|
||||
|
||||
<Chain>
|
||||
<ExePackage
|
||||
Name="windowsdesktop-runtime-3.1.22-win-x64.exe"
|
||||
Compressed="no"
|
||||
Id="DotnetRuntime"
|
||||
DetectCondition="HasDotnet3122"
|
||||
DownloadUrl="https://download.visualstudio.microsoft.com/download/pr/1c14e24b-7f31-42dc-ba3c-83295a2d6f7e/41b93591162dfe556cc160ae44fbe75e/windowsdesktop-runtime-3.1.22-win-x64.exe"
|
||||
InstallCommand="/install /quiet"
|
||||
RepairCommand="/repair /passive"
|
||||
Permanent="yes"
|
||||
PerMachine="yes"
|
||||
UninstallCommand="/uninstall /quiet">
|
||||
<RemotePayload
|
||||
Description="Microsoft Windows Desktop Runtime - 3.1.22 (x64)"
|
||||
ProductName="Microsoft Windows Desktop Runtime - 3.1.22 (x64)"
|
||||
Size="54342024"
|
||||
Version="3.1.22.30721"
|
||||
Hash="08EF2F6CFDB33946061884B1CE13FA867EFBD576" />
|
||||
</ExePackage>
|
||||
<MsiPackage
|
||||
SourceFile="x64\Release\PowerToysSetup-$(var.Version)-x64.msi"
|
||||
Compressed="yes"
|
||||
DisplayInternalUI="no">
|
||||
<MsiProperty Name="BOOTSTRAPPERINSTALLFOLDER" Value="[InstallFolder]" />
|
||||
</MsiPackage>
|
||||
</Chain>
|
||||
</Bundle>
|
||||
</Wix>
|
67
installer/PowerToysSetup/PowerToysBootstrapper.wixproj
Normal file
67
installer/PowerToysSetup/PowerToysBootstrapper.wixproj
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureNuGetPackageBuildImports" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\WiX.3.11.2\build\wix.props" Condition="Exists('..\packages\WiX.3.11.2\build\wix.props')" />
|
||||
<Import Project="..\..\src\Version.props" />
|
||||
<PropertyGroup>
|
||||
<DefineConstants>Version=$(Version)</DefineConstants>
|
||||
<Name>PowerToysBootstrapper</Name>
|
||||
<ProjectGuid>{31d72625-43c1-41b1-b784-bce4a8dc5543}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x64</Platform>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>PowerToysSetup-$(Version)-$(Platform)</OutputName>
|
||||
<OutputType>Bundle</OutputType>
|
||||
<SuppressAclReset>True</SuppressAclReset>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<OutputPath>$(Platform)\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>$(Platform)\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="PowerToys.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixUtilExtension">
|
||||
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||
<Name>WixUtilExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixUIExtension">
|
||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||
<Name>WixUIExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixNetFxExtension">
|
||||
<HintPath>$(WixExtDir)\WixNetFxExtension.dll</HintPath>
|
||||
<Name>WixNetFxExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixNetFxExtension">
|
||||
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
|
||||
<Name>WixBalExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="CustomDialogs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
<Error Text="The WiX Toolset v3 build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||
</Target>
|
||||
<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\WiX.3.11.2\build\wix.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WiX.3.11.2\build\wix.props'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -4,6 +4,7 @@
|
||||
<Import Project="..\..\src\Version.props" />
|
||||
<PropertyGroup>
|
||||
<DefineConstants>Version=$(Version)</DefineConstants>
|
||||
<Name>PowerToysInstaller</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
@ -20,10 +21,14 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<OutputPath>$(Platform)\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
<SuppressIces>ICE91</SuppressIces>
|
||||
<SuppressValidation>True</SuppressValidation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>$(Platform)\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
<SuppressValidation>True</SuppressValidation>
|
||||
<SuppressIces>ICE91</SuppressIces>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CustomDialogs\PTInstallDirDlg.wxs" />
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "RcResource.h"
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
@ -10,8 +11,6 @@
|
||||
#include "../../src/common/updating/installer.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
|
||||
#include "../../installer/PowerToysBootstrapper/bootstrapper/RcResource.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
HINSTANCE DLL_HANDLE = nullptr;
|
||||
@ -76,7 +75,7 @@ UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder, false))
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder))
|
||||
{
|
||||
if (!changeSet.apply())
|
||||
{
|
||||
@ -105,7 +104,7 @@ UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder, false))
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder))
|
||||
{
|
||||
changeSet.unApply();
|
||||
}
|
||||
@ -748,12 +747,12 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
hr = WcaInitialize(hInstall, "DetectPrevInstallPathCA");
|
||||
|
||||
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", L"");
|
||||
try
|
||||
{
|
||||
if (auto install_path = GetMsiPackageInstalledPath())
|
||||
{
|
||||
MsiSetPropertyW(hInstall, L"INSTALLFOLDER", install_path->data());
|
||||
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", install_path->data());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
@ -16,6 +16,7 @@
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>PowerToysSetupCustomActions</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>PowerToysSetupCustomActions</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
@ -53,12 +54,12 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>inc;..\..\src\;telemetry;$(WIX)sdk\$(WixPlatformToolset)\inc;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>inc;..\..\src\;..\..\src\common\Telemetry;telemetry;$(WIX)sdk\$(WixPlatformToolset)\inc;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/await /Zc:twoPhase- /Wv:18 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;..\..\$(PlatformShortName)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>WindowsApp.lib;Newdev.lib;Crypt32.lib;msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>WindowsApp.lib;Newdev.lib;Crypt32.lib;msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -114,7 +115,7 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\PowerToysBootstrapper\bootstrapper\RcResource.h" />
|
||||
<ClInclude Include="RcResource.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="Telemetry\ProjectTelemetry.h" />
|
||||
|
@ -13,7 +13,7 @@
|
||||
<Filter>Telemetry</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="..\PowerToysBootstrapper\bootstrapper\RcResource.h" />
|
||||
<ClInclude Include="RcResource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CustomAction.def" />
|
||||
|
@ -148,22 +148,12 @@ bool InstallNewVersionStage2(std::wstring installer_path, std::wstring_view inst
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's not .msi, then it's our .exe installer
|
||||
// If it's not .msi, then it's a wix bootstrapper
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE };
|
||||
sei.lpFile = installer_path.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
std::wstring parameters = L"--no_full_ui";
|
||||
if (launch_powertoys)
|
||||
{
|
||||
// .exe installer launches the main app by default
|
||||
launch_powertoys = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters += L"--no_start_pt";
|
||||
}
|
||||
|
||||
std::wstring parameters = L"/passive";
|
||||
sei.lpParameters = parameters.c_str();
|
||||
|
||||
success = ShellExecuteExW(&sei) == TRUE;
|
||||
|
@ -106,13 +106,14 @@ inline registry::ChangeSet getGcodeThumbnailHandlerChangeSet(const std::wstring
|
||||
L".gcode");
|
||||
}
|
||||
|
||||
inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstring installationDir, const bool perUser)
|
||||
inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstring installationDir)
|
||||
{
|
||||
return { getSvgPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getMdPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getPdfPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getGcodePreviewHandlerChangeSet(installationDir, perUser),
|
||||
getSvgThumbnailHandlerChangeSet(installationDir, perUser),
|
||||
getPdfThumbnailHandlerChangeSet(installationDir, perUser),
|
||||
getGcodeThumbnailHandlerChangeSet(installationDir, perUser) };
|
||||
constexpr bool PER_USER = true;
|
||||
return { getSvgPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getMdPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getPdfPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodePreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getSvgThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getPdfThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER) };
|
||||
}
|
@ -25,7 +25,7 @@ PowerPreviewModule::PowerPreviewModule() :
|
||||
Logger::init(LogSettings::fileExplorerLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
|
||||
Logger::info("Initializing PowerPreviewModule");
|
||||
const bool installPerUser = false;
|
||||
const bool installPerUser = true;
|
||||
m_fileExplorerModules.push_back({ .settingName = L"svg-previewer-toggle-setting",
|
||||
.settingDescription = GET_RESOURCE_STRING(IDS_PREVPANE_SVG_SETTINGS_DESCRIPTION),
|
||||
.registryChanges = getSvgPreviewHandlerChangeSet(installationDir, installPerUser) });
|
||||
@ -49,7 +49,7 @@ PowerPreviewModule::PowerPreviewModule() :
|
||||
m_fileExplorerModules.push_back({ .settingName = L"pdf-thumbnail-toggle-setting",
|
||||
.settingDescription = GET_RESOURCE_STRING(IDS_PDF_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
|
||||
.registryChanges = getPdfThumbnailHandlerChangeSet(installationDir, installPerUser) });
|
||||
|
||||
|
||||
m_fileExplorerModules.push_back({ .settingName = L"gcode-thumbnail-toggle-setting",
|
||||
.settingDescription = GET_RESOURCE_STRING(IDS_GCODE_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
|
||||
.registryChanges = getGcodeThumbnailHandlerChangeSet(installationDir, installPerUser) });
|
||||
@ -144,21 +144,13 @@ void PowerPreviewModule::enable()
|
||||
// Disable active preview handlers.
|
||||
void PowerPreviewModule::disable()
|
||||
{
|
||||
// Check if the process is elevated in order to have permissions to modify HKLM registry
|
||||
if (is_process_elevated(false))
|
||||
for (auto& fileExplorerModule : m_fileExplorerModules)
|
||||
{
|
||||
for (auto& fileExplorerModule : m_fileExplorerModules)
|
||||
if (!fileExplorerModule.registryChanges.unApply())
|
||||
{
|
||||
if (!fileExplorerModule.registryChanges.unApply())
|
||||
{
|
||||
Logger::error(L"Couldn't disable file explorer module {} during module disable() call", fileExplorerModule.settingName);
|
||||
}
|
||||
Logger::error(L"Couldn't disable file explorer module {} during module disable() call", fileExplorerModule.settingName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
show_update_warning_message();
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
@ -197,9 +189,7 @@ void PowerPreviewModule::show_update_warning_message()
|
||||
|
||||
void PowerPreviewModule::apply_settings(const PowerToysSettings::PowerToyValues& settings)
|
||||
{
|
||||
const bool isElevated = is_process_elevated(false);
|
||||
bool notifyShell = false;
|
||||
bool updatesNeeded = false;
|
||||
|
||||
for (auto& fileExplorerModule : m_fileExplorerModules)
|
||||
{
|
||||
@ -210,11 +200,6 @@ void PowerPreviewModule::apply_settings(const PowerToysSettings::PowerToyValues&
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark that updates were to the registry were needed
|
||||
updatesNeeded = true;
|
||||
}
|
||||
|
||||
// (Un)Apply registry changes depending on the new setting value
|
||||
const bool updated = *toggle ? fileExplorerModule.registryChanges.apply() : fileExplorerModule.registryChanges.unApply();
|
||||
@ -230,10 +215,6 @@ void PowerPreviewModule::apply_settings(const PowerToysSettings::PowerToyValues&
|
||||
Trace::PowerPreviewSettingsUpdateFailed(fileExplorerModule.settingName.c_str(), !*toggle, *toggle, true);
|
||||
}
|
||||
}
|
||||
if (!isElevated && updatesNeeded)
|
||||
{
|
||||
show_update_warning_message();
|
||||
}
|
||||
if (notifyShell)
|
||||
{
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||
|
@ -1006,9 +1006,6 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<data name="FileExplorerPreview_RunAsAdminRequired.Title" xml:space="preserve">
|
||||
<value>You need to run as administrator to modify these settings.</value>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_AffectsAllUsers.Title" xml:space="preserve">
|
||||
<value>The settings on this page affect all users on the system</value>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_RebootRequired.Title" xml:space="preserve">
|
||||
<value>A reboot may be required for changes to these settings to take effect</value>
|
||||
</data>
|
||||
|
@ -20,25 +20,10 @@
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<muxc:InfoBar Severity="Warning"
|
||||
x:Uid="FileExplorerPreview_RunAsAdminRequired"
|
||||
IsOpen="True"
|
||||
IsTabStop="True"
|
||||
IsClosable="False"
|
||||
Visibility="{Binding Mode=OneWay, Path=IsElevated, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
|
||||
<muxc:InfoBar Severity="Informational"
|
||||
x:Uid="FileExplorerPreview_AffectsAllUsers"
|
||||
IsOpen="True"
|
||||
IsTabStop="True"
|
||||
IsClosable="False"
|
||||
/>
|
||||
|
||||
<controls:SettingsGroup x:Uid="FileExplorerPreview_PreviewPane">
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_SVG" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SVGRenderIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -46,7 +31,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_MD" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.MDRenderIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -54,7 +38,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_PDF" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.PDFRenderIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -62,7 +45,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_GCODE" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.GCODERenderIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -78,7 +60,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_SVG_Thumbnail" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SVGThumbnailIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -86,7 +67,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_PDF_Thumbnail" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.PDFThumbnailIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -94,7 +74,6 @@
|
||||
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_GCODE_Thumbnail" Icon="">
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.GCODEThumbnailIsEnabled}"
|
||||
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"
|
||||
x:Uid="ToggleSwitch"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
@ -107,4 +86,4 @@
|
||||
<controls:PageLink x:Uid="LearnMore_PowerPreview" Link="https://aka.ms/PowerToysOverview_FileExplorerAddOns"/>
|
||||
</controls:SettingsPageControl.PrimaryLinks>
|
||||
</controls:SettingsPageControl>
|
||||
</Page>
|
||||
</Page>
|
||||
|
Loading…
Reference in New Issue
Block a user