Skip to content

Commit

Permalink
Autoupdate: implement updating bootstrapper utility (#5204)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyoyuppe committed Jul 27, 2020
1 parent 5a48376 commit 3796a5e
Show file tree
Hide file tree
Showing 34 changed files with 1,016 additions and 296 deletions.
10 changes: 10 additions & 0 deletions .pipelines/build-bootstrapper.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
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
pushd .
cd ..
set SolutionDir=%cd%
popd
SET IsPipeline=1
call msbuild ../src/bootstrapper/bootstrapper.vcxproj /p:Configuration=Release /p:Platform=x64 /p:CIBuild=true /p:BuildProjectReferences=false /p:SolutionDir=%SolutionDir%\ || exit /b 1

11 changes: 11 additions & 0 deletions .pipelines/pipeline.user.windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ build:
- 'PowerToysSetup-*.msi'
signing_options:
sign_inline: true # This does signing a soon as this command completes
- !!buildcommand
name: 'Build Power Toys Bootstrapper'
command: '.pipelines\build-bootstrapper.cmd'
artifacts:
- from: 'x64/Release'
to: 'Build_Installer_Output'
include:
- 'PowerToysSetup-*.exe'
signing_options:
sign_inline: true # This does signing a soon as this command completes


#package:
# commands:
Expand Down
4 changes: 4 additions & 0 deletions PowerToys.sln
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPickerUI", "src\module
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "colorpicker", "colorpicker", "{1D78B84B-CA39-406C-98F4-71F7EC266CC0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bootstrapper", "src\bootstrapper\bootstrapper.vcxproj", "{D194E3AA-F824-4CA9-9A58-034DD6B7D022}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Expand Down Expand Up @@ -521,6 +523,8 @@ Global
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.Build.0 = Debug|x64
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.ActiveCfg = Release|x64
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.Build.0 = Release|x64
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Debug|x64.ActiveCfg = Debug|x64
{D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
51 changes: 3 additions & 48 deletions installer/PowerToysSetupCustomActions/CustomAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <ProjectTelemetry.h>

#include "../../src/common/updating/updating.h"

using namespace std;

TRACELOGGING_DEFINE_PROVIDER(
Expand All @@ -14,7 +16,6 @@ TRACELOGGING_DEFINE_PROVIDER(
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'

static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";

// Creates a Scheduled Task to run at logon for the current user.
Expand Down Expand Up @@ -563,52 +564,6 @@ UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall)
return WcaFinalize(er);
}

std::optional<std::wstring> getMsiPackageInstalledPath(const wchar_t* product_upgrade_code, const wchar_t* file_component)
{
constexpr size_t guid_length = 39;
wchar_t product_ID[guid_length];
if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(product_upgrade_code, 0, 0, product_ID); !found)
{
return std::nullopt;
}

if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(product_ID); !installed)
{
return std::nullopt;
}

DWORD buf_size = MAX_PATH;
wchar_t buf[MAX_PATH];
if (ERROR_SUCCESS == MsiGetProductInfoW(product_ID, INSTALLPROPERTY_INSTALLLOCATION, buf, &buf_size) && buf_size)
{
return buf;
}

DWORD package_path_size = 0;

if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size))
{
return std::nullopt;
}
std::wstring package_path(++package_path_size, L'\0');

if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size))
{
return std::nullopt;
}
package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW

wchar_t path[256];
DWORD path_size = 256;
MsiGetComponentPathW(product_ID, file_component, path, &path_size);
if (!path_size)
{
return std::nullopt;
}
PathCchRemoveFileSpec(path, path_size);
return path;
}

UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
Expand All @@ -617,7 +572,7 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)

try
{
if (auto install_path = getMsiPackageInstalledPath(POWERTOYS_UPGRADE_CODE, POWERTOYS_EXE_COMPONENT))
if (auto install_path = updating::get_msi_package_installed_path())
{
MsiSetPropertyW(hInstall, L"INSTALLFOLDER", install_path->data());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand All @@ -82,7 +82,7 @@
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand All @@ -93,12 +93,12 @@
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile>
</ItemDefinitionGroup>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CustomAction.cpp" />
<ClCompile Include="stdafx.cpp">
Expand Down
64 changes: 11 additions & 53 deletions src/action_runner/action_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <common/common.h>
#include <common/updating/updating.h>
#include <common/updating/http_client.h>
#include <common/updating/dotnet_installation.h>

#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Storage.h>
Expand Down Expand Up @@ -114,6 +115,7 @@ bool install_new_version_stage_2(std::wstring installer_path, std::wstring_view
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;
sei.lpParameters = L"-silent";

success = ShellExecuteExW(&sei) == TRUE;
// Wait for the install completion
Expand Down Expand Up @@ -146,57 +148,6 @@ bool install_new_version_stage_2(std::wstring installer_path, std::wstring_view
return true;
}

bool dotnet_is_installed()
{
auto runtimes = exec_and_read_output(LR"(dotnet --list-runtimes)");
if (!runtimes)
{
return false;
}
const char DESKTOP_DOTNET_RUNTIME_STRING[] = "Microsoft.WindowsDesktop.App 3.1.";
return runtimes->find(DESKTOP_DOTNET_RUNTIME_STRING) != std::string::npos;
}

bool install_dotnet()
{
const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/d8cf1fe3-21c2-4baf-988f-f0152996135e/0c00b94713ee93e7ad5b4f82e2b86607/windowsdesktop-runtime-3.1.4-win-x64.exe";
const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime-3.1.4-win-x64.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
}
}
if (!download_success)
{
MessageBoxW(nullptr,
GET_RESOURCE_STRING(IDS_DOTNET_CORE_DOWNLOAD_FAILURE).c_str(),
GET_RESOURCE_STRING(IDS_DOTNET_CORE_DOWNLOAD_FAILURE_TITLE).c_str(),
MB_OK | MB_ICONERROR);
return false;
}
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOASYNC };
sei.lpFile = dotnet_download_path.c_str();
sei.nShow = SW_SHOWNORMAL;
sei.lpParameters = L"/install /passive";
return ShellExecuteExW(&sei) == TRUE;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
int nArgs = 0;
Expand Down Expand Up @@ -270,11 +221,18 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
}
else if (action == L"-install_dotnet")
{
if (dotnet_is_installed())
if (updating::dotnet_is_installed())
{
return 0;
}
return !install_dotnet();
const bool success = updating::install_dotnet();

MessageBoxW(nullptr,
GET_RESOURCE_STRING(IDS_DOTNET_CORE_DOWNLOAD_FAILURE).c_str(),
GET_RESOURCE_STRING(IDS_DOTNET_CORE_DOWNLOAD_FAILURE_TITLE).c_str(),
MB_OK | MB_ICONERROR);

return !success;
}
else if (action == L"-uninstall_msi")
{
Expand Down
27 changes: 0 additions & 27 deletions src/action_runner/service_runner.vcxproj.filters

This file was deleted.

0 comments on commit 3796a5e

Please sign in to comment.