Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

win,msi: change InstallScope to perMachine #25640

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/simple/simple.status
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test-fs-readfile-error : PASS,FLAKY
test-net-GH-5504 : PASS,FLAKY
test-stdin-script-child : PASS,FLAKY
test-util-debug : PASS,FLAKY
test-signal-unregister : PASS,FLAKY

[$system==macos]
test-fs-watch : PASS,FLAKY
Expand Down
52 changes: 51 additions & 1 deletion tools/msvs/msi/custom_actions.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,60 @@

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <msiquery.h>
#include <wcautil.h>

#define GUID_BUFFER_SIZE 39 // {8-4-4-4-12}\0


UINT WINAPI SetInstallScope(MSIHANDLE hInstall) {
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
TCHAR upgrade_code[GUID_BUFFER_SIZE];
DWORD upgrade_code_len = GUID_BUFFER_SIZE;
DWORD iProductIndex;
TCHAR product_code[GUID_BUFFER_SIZE];
TCHAR assignment_type[2];
DWORD assignment_type_len = 2;

hr = WcaInitialize(hInstall, "SetInstallScope");
ExitOnFailure(hr, "Failed to initialize");

er = MsiGetProperty(hInstall, TEXT("UpgradeCode"), upgrade_code,
&upgrade_code_len);
ExitOnWin32Error(er, hr, "Failed to get UpgradeCode property");

for (iProductIndex = 0;; iProductIndex++) {
er = MsiEnumRelatedProducts(upgrade_code, 0, iProductIndex, product_code);
if (er == ERROR_NO_MORE_ITEMS) break;
ExitOnWin32Error(er, hr, "Failed to get related product code");

er = MsiGetProductInfo(product_code, INSTALLPROPERTY_ASSIGNMENTTYPE,
assignment_type, &assignment_type_len);
ExitOnWin32Error(er, hr, "Failed to get the assignment type property "
"from related product");

// '0' = per-user; '1' = per-machine
if (assignment_type[0] == '0') {
/* When old versions which were installed as per-user are detected, the
* installation scope has to be set to per-user to be able to do an
* upgrade. If not, two versions will be installed side-by-side: one as
* per-user and the other as per-machine.
*
* If we wanted to disable backward compatibility, the installer should
* abort here, and request the previous version to be manually
* uninstalled before installing this one.
*/
er = MsiSetProperty(hInstall, TEXT("ALLUSERS"), TEXT(""));
ExitOnWin32Error(er, hr, "Failed to set the install scope to per-user");
break;
}
}

LExit:
return WcaFinalize(ERROR_SUCCESS);
}


UINT WINAPI BroadcastEnvironmentUpdate(MSIHANDLE hInstall) {
HRESULT hr = S_OK;
Expand Down
3 changes: 2 additions & 1 deletion tools/msvs/msi/custom_actions.def
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
LIBRARY "custom_actions"

EXPORTS
BroadcastEnvironmentUpdate
SetInstallScope
BroadcastEnvironmentUpdate
59 changes: 45 additions & 14 deletions tools/msvs/msi/product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Manufacturer="$(var.ProductAuthor)"
UpgradeCode="1d60944c-b9ce-4a71-a7c0-0384eb884baa">

<Package InstallerVersion="200" Compressed="yes"/>
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>

<Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/>

Expand All @@ -32,6 +32,14 @@

<Property Id="INSTALLDIR">
<RegistrySearch Id="InstallPathRegistry"
Type="raw"
Root="HKLM"
Key="$(var.RegistryKeyPath)"
Name="InstallPath"/>
<!-- Also need to search under HKCU to support upgrading from old
versions. If we wanted to disable backward compatibility, this
second search could be deleted. -->
<RegistrySearch Id="InstallPathRegistryCU"
Type="raw"
Root="HKCU"
Key="$(var.RegistryKeyPath)"
Expand All @@ -44,8 +52,9 @@
Description="Install the core Node.js runtime (node.exe)."
Absent="disallow">
<ComponentRef Id="NodeExecutable"/>
<ComponentRef Id="NodeRegistryEntries"/>
<ComponentRef Id="NodeVarsScript"/>
<ComponentRef Id="NodeStartMenuAndRegistryEntries"/>
<ComponentRef Id="NodeStartMenu"/>
<ComponentRef Id="AppData" />
<ComponentGroupRef Id="Product.Generated"/>

Expand Down Expand Up @@ -117,6 +126,20 @@
<File Id="node.exe" KeyPath="yes" Source="$(var.SourceDir)\node.exe"/>
</Component>

<Component Id="NodeRegistryEntries">
<RegistryValue Root="HKLM"
Key="$(var.RegistryKeyPath)"
Name="InstallPath"
Type="string"
Value="[INSTALLDIR]"
KeyPath="yes"/>
<RegistryValue Root="HKLM"
Key="$(var.RegistryKeyPath)"
Name="Version"
Type="string"
Value="$(var.ProductVersion)"/>
</Component>

<Component Id="NodeVarsScript">
<File Id="nodevars.bat" KeyPath="yes" Source="$(var.RepoDir)\tools\msvs\nodevars.bat"/>
</Component>
Expand All @@ -139,18 +162,15 @@
</DirectoryRef>

<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="NodeStartMenuAndRegistryEntries">
<Component Id="NodeStartMenu">
<!-- RegistryValue needed because every Component must have a KeyPath.
Because of ICE43, the Root must be HKCU. -->
<RegistryValue Root="HKCU"
Key="$(var.RegistryKeyPath)"
Name="InstallPath"
Type="string"
Value="[INSTALLDIR]"
Key="$(var.RegistryKeyPath)\Components"
Name="NodeStartMenuShortcuts"
Type="integer"
Value="1"
KeyPath="yes"/>
<RegistryValue Root="HKCU"
Key="$(var.RegistryKeyPath)"
Name="Version"
Type="string"
Value="$(var.ProductVersion)"/>
<Shortcut Id="NodeVarsScriptShortcut"
Name="Node.js command prompt"
Target="[%ComSpec]"
Expand Down Expand Up @@ -249,16 +269,27 @@
</Component>
</DirectoryRef>

<Binary Id='BroadcastEnvironmentUpdate'
<Binary Id='CustomActionsDLL'
SourceFile='$(var.custom_actions.TargetDir)$(var.custom_actions.TargetName).dll' />

<CustomAction Id="SetInstallScope"
BinaryKey="CustomActionsDLL"
DllEntry="SetInstallScope"
Execute="immediate"
Return="check" />

<CustomAction Id="BroadcastEnvironmentUpdate"
BinaryKey="BroadcastEnvironmentUpdate"
BinaryKey="CustomActionsDLL"
DllEntry="BroadcastEnvironmentUpdate"
Execute="immediate"
Return="check" />

<InstallUISequence>
<Custom Action='SetInstallScope' Before='FindRelatedProducts'/>
</InstallUISequence>

<InstallExecuteSequence>
<Custom Action='SetInstallScope' Before='FindRelatedProducts'/>
<Custom Action='BroadcastEnvironmentUpdate' After='InstallFinalize'/>
</InstallExecuteSequence>

Expand Down