diff --git a/tools/msvs/msi/custom_actions.cc b/tools/msvs/msi/custom_actions.cc
index 9a23d557476004..8a8417ea0b2929 100644
--- a/tools/msvs/msi/custom_actions.cc
+++ b/tools/msvs/msi/custom_actions.cc
@@ -1,10 +1,80 @@
-
 #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
+
+
+extern "C" UINT WINAPI SetInstallScope(MSIHANDLE hInstall) {
+  HRESULT hr = S_OK;
+  UINT er = ERROR_SUCCESS;
+  PMSIHANDLE hDB;
+  PMSIHANDLE hView;
+  PMSIHANDLE hRecord;
+
+  hr = WcaInitialize(hInstall, "SetInstallScope");
+  ExitOnFailure(hr, "Failed to initialize");
+
+  hDB = MsiGetActiveDatabase(hInstall);
+  ExitOnNull(hDB, hr, S_FALSE, "Failed to get active database");
+
+  LPCTSTR query = TEXT("SELECT DISTINCT UpgradeCode FROM Upgrade");
+  er = MsiDatabaseOpenView(hDB, query, &hView);
+  ExitOnWin32Error(er, hr, "Failed MsiDatabaseOpenView");
+
+  er = MsiViewExecute(hView, 0);
+  ExitOnWin32Error(er, hr, "Failed MsiViewExecute");
+
+  for (;;) {
+    er = MsiViewFetch(hView, &hRecord);
+    if (er == ERROR_NO_MORE_ITEMS) break;
+    ExitOnWin32Error(er, hr, "Failed MsiViewFetch");
+
+    TCHAR upgrade_code[GUID_BUFFER_SIZE];
+    DWORD upgrade_code_len = GUID_BUFFER_SIZE;
+    er = MsiRecordGetString(hRecord, 1, upgrade_code, &upgrade_code_len);
+    ExitOnWin32Error(er, hr, "Failed to read UpgradeCode");
+
+    DWORD iProductIndex;
+    for (iProductIndex = 0;; iProductIndex++) {
+      TCHAR product_code[GUID_BUFFER_SIZE];
+      er = MsiEnumRelatedProducts(upgrade_code, 0, iProductIndex,
+                                  product_code);
+      if (er == ERROR_NO_MORE_ITEMS) break;
+      ExitOnWin32Error(er, hr, "Failed to get related product code");
+
+      TCHAR assignment_type[2];
+      DWORD assignment_type_len = 2;
+      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");
+        goto LExit;
+      }
+    }
+  }
+
+LExit:
+  // Always succeed. This should not block the installation.
+  return WcaFinalize(ERROR_SUCCESS);
+}
+
 
 extern "C" UINT WINAPI BroadcastEnvironmentUpdate(MSIHANDLE hInstall) {
   HRESULT hr = S_OK;
diff --git a/tools/msvs/msi/custom_actions.def b/tools/msvs/msi/custom_actions.def
index 29e0933e379a78..5f6b25fc423492 100644
--- a/tools/msvs/msi/custom_actions.def
+++ b/tools/msvs/msi/custom_actions.def
@@ -1,4 +1,5 @@
 LIBRARY "custom_actions"
 
 EXPORTS
-BroadcastEnvironmentUpdate
\ No newline at end of file
+SetInstallScope
+BroadcastEnvironmentUpdate
diff --git a/tools/msvs/msi/product.wxs b/tools/msvs/msi/product.wxs
index 21246fed38e2d3..172399ca5c8703 100755
--- a/tools/msvs/msi/product.wxs
+++ b/tools/msvs/msi/product.wxs
@@ -18,7 +18,10 @@
            Manufacturer="$(var.ProductAuthor)"
            UpgradeCode="47c07a3a-42ef-4213-a85d-8f5a59077c28">
 
-    <Package Languages="!(loc.LocaleId)" InstallerVersion="200" Compressed="yes"/>
+    <Package Languages="!(loc.LocaleId)"
+             InstallerVersion="200"
+             Compressed="yes"
+             InstallScope="perMachine"/>
 
     <Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/>
 
@@ -41,6 +44,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)"
@@ -53,8 +64,9 @@
              Description="!(loc.NodeRuntime_Description)"
              Absent="disallow">
       <ComponentRef Id="NodeExecutable"/>
+      <ComponentRef Id="NodeRegistryEntries"/>
       <ComponentRef Id="NodeVarsScript"/>
-      <ComponentRef Id="NodeStartMenuAndRegistryEntries"/>
+      <ComponentRef Id="NodeStartMenu"/>
       <ComponentRef Id="AppData" />
       <ComponentGroupRef Id="Product.Generated"/>
 
@@ -126,6 +138,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>
@@ -148,18 +174,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]"
@@ -258,16 +281,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>