summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
Diffstat (limited to 'Tools')
-rw-r--r--Tools/msi/build.bat8
-rw-r--r--Tools/msi/bundle/Default.thm13
-rw-r--r--Tools/msi/bundle/Default.wxl14
-rw-r--r--Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp357
-rw-r--r--Tools/msi/bundle/bootstrap/pythonba.vcxproj2
-rw-r--r--Tools/msi/bundle/bundle.wxs40
-rw-r--r--Tools/msi/bundle/packagegroups/core.wxs6
-rw-r--r--Tools/msi/bundle/packagegroups/dev.wxs4
-rw-r--r--Tools/msi/bundle/packagegroups/doc.wxs2
-rw-r--r--Tools/msi/bundle/packagegroups/exe.wxs6
-rw-r--r--Tools/msi/bundle/packagegroups/lib.wxs6
-rw-r--r--Tools/msi/bundle/packagegroups/postinstall.wxs4
-rw-r--r--Tools/msi/bundle/packagegroups/tcltk.wxs6
-rw-r--r--Tools/msi/bundle/packagegroups/test.wxs6
-rw-r--r--Tools/msi/bundle/packagegroups/tools.wxs2
-rw-r--r--Tools/msi/common.wxs9
-rw-r--r--Tools/msi/core/core_d.wxs1
-rw-r--r--Tools/msi/core/core_pdb.wxs1
-rw-r--r--Tools/msi/dev/dev.wxs1
-rw-r--r--Tools/msi/doc/doc.wxs5
-rw-r--r--Tools/msi/exe/exe.wxs2
-rw-r--r--Tools/msi/exe/exe_files.wxs1
-rw-r--r--Tools/msi/launcher/launcher_files.wxs5
-rw-r--r--Tools/msi/launcher/launcher_reg.wxs2
-rw-r--r--Tools/msi/lib/lib.wxs1
-rw-r--r--Tools/msi/msi.props6
-rw-r--r--Tools/msi/path/path.wxs8
-rw-r--r--Tools/msi/pip/pip.wxs4
-rw-r--r--Tools/msi/tcltk/tcltk.wxs1
-rw-r--r--Tools/msi/test/test.wxs1
-rw-r--r--Tools/msi/tools/tools.wxs1
31 files changed, 402 insertions, 123 deletions
diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat
index 1dc05c3..c135b63 100644
--- a/Tools/msi/build.bat
+++ b/Tools/msi/build.bat
@@ -8,10 +8,10 @@ set BUILDX64=
set BUILDDOC=
:CheckOpts
-if "%1" EQU "-h" goto Help
-if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts
-if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts
-if "%1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts
+if "%~1" EQU "-h" goto Help
+if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts
+if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts
+if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts
if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1)
diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm
index d5e1969..0c79dd5 100644
--- a/Tools/msi/bundle/Default.thm
+++ b/Tools/msi/bundle/Default.thm
@@ -21,13 +21,24 @@
<Text X="185" Y="50" Width="-11" Height="50" FontId="3" TabStop="yes">#(loc.InstallMessage)</Text>
- <Button Name="InstallJustForMeButton" X="175" Y="101" Width="-11" Height="129" TabStop="yes" FontId="3" HexStyle="0xE">#(loc.InstallJustForMeButton)</Button>
+ <Button Name="InstallButton" X="175" Y="101" Width="-11" Height="129" TabStop="yes" FontId="3" HexStyle="0xE">#(loc.InstallButton)</Button>
<Button Name="InstallCustomButton" X="175" Y="241" Width="-11" Height="59" TabStop="yes" FontId="3" HexStyle="0xE">#(loc.InstallCustomButton)</Button>
<Checkbox Name="PrependPath" X="185" Y="-13" Width="-100" Height="20" TabStop="yes" FontId="3">#(loc.ShortPrependPathLabel)</Checkbox>
<Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.CancelButton)</Button>
</Page>
+ <Page Name="Upgrade">
+ <Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.InstallUpgradeHeader)</Text>
+ <Image X="0" Y="0" Width="162" Height="352" ImageFile="SideBar.png"/>
+
+ <Text X="185" Y="50" Width="-11" Height="50" FontId="3" TabStop="yes">#(loc.InstallUpgradeMessage)</Text>
+
+ <Button Name="InstallUpgradeButton" X="175" Y="101" Width="-11" Height="129" TabStop="yes" FontId="3" HexStyle="0xE">#(loc.InstallUpgradeButton)</Button>
+ <Button Name="InstallUpgradeCustomButton" X="175" Y="241" Width="-11" Height="59" TabStop="yes" FontId="3" HexStyle="0xE">#(loc.InstallUpgradeCustomButton)</Button>
+
+ <Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.CancelButton)</Button>
+ </Page>
<Page Name="SimpleInstall">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.InstallHeader)</Text>
<Image X="0" Y="0" Width="162" Height="352" ImageFile="SideBar.png"/>
diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl
index 3ecb2fa..19ba7eb 100644
--- a/Tools/msi/bundle/Default.wxl
+++ b/Tools/msi/bundle/Default.wxl
@@ -21,6 +21,8 @@ Continue?</String>
<String Id="InstallHeader">Install [WixBundleName]</String>
<String Id="InstallMessage">Select Install Now to install Python with default settings, or choose Customize to enable or disable features.</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
+ <String Id="InstallUpgradeHeader">Upgrade to [WixBundleName]</String>
+ <String Id="InstallUpgradeMessage">Select Upgrade Now to keep your current settings, or choose Customize to enable or disable features.</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String>
<String Id="HelpHeader">Setup Help</String>
@@ -40,8 +42,8 @@ Continue?</String>
Logs to a specific file. By default, log files are created in %TEMP%.</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
- <String Id="InstallJustForMeButton">&amp;Install Now</String>
- <String Id="InstallJustForMeButtonNote">[DefaultJustForMeTargetDir]
+ <String Id="InstallButton">&amp;Install Now</String>
+ <String Id="InstallButtonNote">[DefaultJustForMeTargetDir]
Includes IDLE, pip and documentation
Creates shortcuts and file associations</String>
@@ -49,6 +51,13 @@ Creates shortcuts and file associations</String>
<String Id="InstallCustomButtonNote">Choose location and features</String>
<String Id="InstallSimpleButton">&amp;Install</String>
<String Id="InstallSimpleButtonNote">Uses setting preselected by your administrator</String>
+ <String Id="InstallUpgradeButton">&amp;Upgrade Now</String>
+ <String Id="InstallUpgradeButtonNote">[TargetDir]
+
+Replaces your existing installation without changing settings.
+Select Customize to review current options.</String>
+ <String Id="InstallUpgradeCustomButton">C&amp;ustomize installation</String>
+ <String Id="InstallUpgradeCustomButtonNote">Choose location and features</String>
<String Id="Custom1Header">Optional Features</String>
<String Id="Custom2Header">Advanced Options</String>
<String Id="CustomLocationLabel">Customize install location</String>
@@ -107,4 +116,5 @@ Feel free to email &lt;a href="mailto:python-list@python.org"&gt;python-list@pyt
<String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
+ <String Id="FailureExistingInstall">Unable to install [WixBundleName] due to an existing install. Use Programs and Features to modify, repair or remove [WixBundleName].</String>
</WixLocalization>
diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp
index 585f66c..7283559 100644
--- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp
+++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp
@@ -47,6 +47,7 @@ enum PAGE {
PAGE_LOADING,
PAGE_HELP,
PAGE_INSTALL,
+ PAGE_UPGRADE,
PAGE_SIMPLE_INSTALL,
PAGE_CUSTOM1,
PAGE_CUSTOM2,
@@ -63,6 +64,7 @@ static LPCWSTR PAGE_NAMES[] = {
L"Loading",
L"Help",
L"Install",
+ L"Upgrade",
L"SimpleInstall",
L"Custom1",
L"Custom2",
@@ -79,10 +81,11 @@ enum CONTROL_ID {
ID_MINIMIZE_BUTTON,
// Welcome page
- ID_INSTALL_ALL_USERS_BUTTON,
- ID_INSTALL_JUST_FOR_ME_BUTTON,
+ ID_INSTALL_BUTTON,
ID_INSTALL_CUSTOM_BUTTON,
ID_INSTALL_SIMPLE_BUTTON,
+ ID_INSTALL_UPGRADE_BUTTON,
+ ID_INSTALL_UPGRADE_CUSTOM_BUTTON,
ID_INSTALL_CANCEL_BUTTON,
// Customize Page
@@ -141,10 +144,11 @@ static THEME_ASSIGN_CONTROL_ID CONTROL_ID_NAMES[] = {
{ ID_CLOSE_BUTTON, L"CloseButton" },
{ ID_MINIMIZE_BUTTON, L"MinimizeButton" },
- { ID_INSTALL_ALL_USERS_BUTTON, L"InstallAllUsersButton" },
- { ID_INSTALL_JUST_FOR_ME_BUTTON, L"InstallJustForMeButton" },
+ { ID_INSTALL_BUTTON, L"InstallButton" },
{ ID_INSTALL_CUSTOM_BUTTON, L"InstallCustomButton" },
{ ID_INSTALL_SIMPLE_BUTTON, L"InstallSimpleButton" },
+ { ID_INSTALL_UPGRADE_BUTTON, L"InstallUpgradeButton" },
+ { ID_INSTALL_UPGRADE_CUSTOM_BUTTON, L"InstallUpgradeCustomButton" },
{ ID_INSTALL_CANCEL_BUTTON, L"InstallCancelButton" },
{ ID_TARGETDIR_EDITBOX, L"TargetDir" },
@@ -191,13 +195,35 @@ static THEME_ASSIGN_CONTROL_ID CONTROL_ID_NAMES[] = {
{ ID_FAILURE_CANCEL_BUTTON, L"FailureCancelButton" },
};
+static struct { LPCWSTR regName; LPCWSTR variableName; } OPTIONAL_FEATURES[] = {
+ { L"core_d", L"Include_debug" },
+ { L"core_pdb", L"Include_symbols" },
+ { L"dev", L"Include_dev" },
+ { L"doc", L"Include_doc" },
+ { L"exe", L"Include_exe" },
+ { L"lib", L"Include_lib" },
+ { L"path", L"PrependPath" },
+ { L"pip", L"Include_pip" },
+ { L"tcltk", L"Include_tcltk" },
+ { L"test", L"Include_test" },
+ { L"tools", L"Include_tools" },
+ { L"Shortcuts", L"Shortcuts" },
+ // Include_launcher and AssociateFiles are handled separately and so do
+ // not need to be included in this list.
+ { nullptr, nullptr }
+};
+
+
+
class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
void ShowPage(DWORD newPageId) {
// Process each control for special handling in the new page.
ProcessPageControls(ThemeGetPage(_theme, newPageId));
// Enable disable controls per-page.
- if (_pageIds[PAGE_INSTALL] == newPageId || _pageIds[PAGE_SIMPLE_INSTALL] == newPageId) {
+ if (_pageIds[PAGE_INSTALL] == newPageId ||
+ _pageIds[PAGE_SIMPLE_INSTALL] == newPageId ||
+ _pageIds[PAGE_UPGRADE] == newPageId) {
InstallPage_Show();
} else if (_pageIds[PAGE_CUSTOM1] == newPageId) {
Custom1Page_Show();
@@ -222,7 +248,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
// On the install page set the focus to the install button or
// the next enabled control if install is disabled
if (_pageIds[PAGE_INSTALL] == newPageId) {
- ThemeSetFocus(_theme, ID_INSTALL_ALL_USERS_BUTTON);
+ ThemeSetFocus(_theme, ID_INSTALL_BUTTON);
} else if (_pageIds[PAGE_SIMPLE_INSTALL] == newPageId) {
ThemeSetFocus(_theme, ID_INSTALL_SIMPLE_BUTTON);
}
@@ -234,7 +260,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
void OnCommand(CONTROL_ID id) {
LPWSTR defaultDir = nullptr;
LPWSTR targetDir = nullptr;
- LONGLONG elevated, crtInstalled;
+ LONGLONG elevated, crtInstalled, installAllUsers;
BOOL checked;
WCHAR wzPath[MAX_PATH] = { };
BROWSEINFOW browseInfo = { };
@@ -247,87 +273,42 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
break;
// Install commands
- case ID_INSTALL_SIMPLE_BUTTON:
- hr = BalGetStringVariable(L"TargetDir", &targetDir);
- if (FAILED(hr) || !targetDir || !*targetDir) {
- LONGLONG installAll;
- if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) {
- hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir);
- BalExitOnFailure(hr, "Failed to get the default all users install directory");
- } else {
- hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir);
- BalExitOnFailure(hr, "Failed to get the default per-user install directory");
- }
-
- if (!defaultDir || !*defaultDir) {
- BalLogError(E_INVALIDARG, "Default install directory is blank");
- }
-
- hr = BalFormatString(defaultDir, &targetDir);
- BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir);
-
- hr = _engine->SetVariableString(L"TargetDir", targetDir);
- ReleaseStr(targetDir);
- BalExitOnFailure(hr, "Failed to set install target directory");
- } else {
- ReleaseStr(targetDir);
- }
-
- OnPlan(BOOTSTRAPPER_ACTION_INSTALL);
- break;
-
- case ID_INSTALL_ALL_USERS_BUTTON:
- SavePageSettings();
-
- hr = _engine->SetVariableNumeric(L"InstallAllUsers", 1);
- ExitOnFailure(hr, L"Failed to set install scope");
-
- hr = _engine->SetVariableNumeric(L"CompileAll", 1);
- ExitOnFailure(hr, L"Failed to set compile all setting");
-
- hr = BalGetStringVariable(L"DefaultAllUsersTargetDir", &defaultDir);
- BalExitOnFailure(hr, "Failed to get the default all users install directory");
-
- if (!defaultDir || !*defaultDir) {
- BalLogError(E_INVALIDARG, "Default install directory is blank");
- }
-
- hr = BalFormatString(defaultDir, &targetDir);
- BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir);
-
- hr = _engine->SetVariableString(L"TargetDir", targetDir);
- ReleaseStr(targetDir);
- BalExitOnFailure(hr, "Failed to set install target directory");
-
- OnPlan(BOOTSTRAPPER_ACTION_INSTALL);
- break;
-
- case ID_INSTALL_JUST_FOR_ME_BUTTON:
+ case ID_INSTALL_SIMPLE_BUTTON: __fallthrough;
+ case ID_INSTALL_UPGRADE_BUTTON: __fallthrough;
+ case ID_INSTALL_BUTTON:
SavePageSettings();
if (!QueryElevateForCrtInstall()) {
break;
}
- hr = _engine->SetVariableNumeric(L"InstallAllUsers", 0);
- ExitOnFailure(hr, L"Failed to set install scope");
+ hr = BalGetNumericVariable(L"InstallAllUsers", &installAllUsers);
+ ExitOnFailure(hr, L"Failed to get install scope");
- hr = _engine->SetVariableNumeric(L"CompileAll", 0);
- ExitOnFailure(hr, L"Failed to unset CompileAll");
+ hr = _engine->SetVariableNumeric(L"CompileAll", installAllUsers);
+ ExitOnFailure(hr, L"Failed to update CompileAll");
- hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir);
- BalExitOnFailure(hr, "Failed to get the default per-user install directory");
+ hr = BalGetStringVariable(L"TargetDir", &targetDir);
+ if (FAILED(hr) || !targetDir || !targetDir[0]) {
+ ReleaseStr(targetDir);
- if (!defaultDir || !*defaultDir) {
- BalLogError(E_INVALIDARG, "Default install directory is blank");
- }
+ hr = BalGetStringVariable(
+ installAllUsers ? L"DefaultAllUsersTargetDir" : L"DefaultJustForMeTargetDir",
+ &defaultDir
+ );
+ BalExitOnFailure(hr, "Failed to get the default install directory");
- hr = BalFormatString(defaultDir, &targetDir);
- BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir);
+ if (!defaultDir || !defaultDir[0]) {
+ BalLogError(E_INVALIDARG, "Default install directory is blank");
+ }
- hr = _engine->SetVariableString(L"TargetDir", targetDir);
+ hr = BalFormatString(defaultDir, &targetDir);
+ BalExitOnFailure1(hr, "Failed to format '%ls'", defaultDir);
+
+ hr = _engine->SetVariableString(L"TargetDir", targetDir);
+ BalExitOnFailure(hr, "Failed to set install target directory");
+ }
ReleaseStr(targetDir);
- BalExitOnFailure(hr, "Failed to set install target directory");
OnPlan(BOOTSTRAPPER_ACTION_INSTALL);
break;
@@ -342,6 +323,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
break;
case ID_INSTALL_CUSTOM_BUTTON: __fallthrough;
+ case ID_INSTALL_UPGRADE_CUSTOM_BUTTON: __fallthrough;
case ID_CUSTOM2_BACK_BUTTON:
SavePageSettings();
GoToPage(PAGE_CUSTOM1);
@@ -460,10 +442,11 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
elevated = 0;
}
- ThemeControlElevates(_theme, ID_INSTALL_ALL_USERS_BUTTON, !elevated);
- if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll) {
- ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, !elevated);
+ if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll)) && installAll && !elevated) {
+ ThemeControlElevates(_theme, ID_INSTALL_BUTTON, TRUE);
+ ThemeControlElevates(_theme, ID_INSTALL_SIMPLE_BUTTON, TRUE);
+ ThemeControlElevates(_theme, ID_INSTALL_UPGRADE_BUTTON, TRUE);
}
}
@@ -667,7 +650,34 @@ public: // IBootstrapperApplication
// Remember when our bundle would cause a downgrade.
if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) {
- _downgrading = TRUE;
+ _downgradingOtherVersion = TRUE;
+ } else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) {
+ _upgradingOldVersion = TRUE;
+
+ // Assume we don't want the launcher or file associations, and if
+ // they have already been installed then loading the state will
+ // reactivate these settings.
+ _engine->SetVariableNumeric(L"Include_launcher", 0);
+ _engine->SetVariableNumeric(L"AssociateFiles", 0);
+ auto hr = LoadLauncherStateFromKey(_engine, HKEY_CURRENT_USER);
+ if (hr == S_FALSE) {
+ hr = LoadLauncherStateFromKey(_engine, HKEY_LOCAL_MACHINE);
+ }
+ } else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == operation) {
+ if (_command.action == BOOTSTRAPPER_ACTION_INSTALL) {
+ LOC_STRING *pLocString = nullptr;
+ if (SUCCEEDED(LocGetString(_wixLoc, L"#(loc.FailureExistingInstall)", &pLocString)) && pLocString) {
+ BalFormatString(pLocString->wzText, &_failedMessage);
+ } else {
+ BalFormatString(L"Cannot install [WixBundleName] because it is already installed.", &_failedMessage);
+ }
+ BalLog(
+ BOOTSTRAPPER_LOG_LEVEL_ERROR,
+ "Related bundle %ls is preventing install",
+ wzBundleId
+ );
+ SetState(PYBA_STATE_FAILED, E_WIXSTDBA_CONDITION_FAILED);
+ }
}
return CheckCanceled() ? IDCANCEL : IDOK;
@@ -1969,7 +1979,7 @@ private:
BalExitOnFailure(hr, "Failed to update strings");
// If we are going to apply a downgrade, bail.
- if (_downgrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) {
+ if (_downgradingOtherVersion && BOOTSTRAPPER_ACTION_UNINSTALL < action) {
if (_suppressDowngradeFailure) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing...");
} else {
@@ -2354,7 +2364,9 @@ private:
if (_installPage == PAGE_LOADING) {
switch (_command.action) {
case BOOTSTRAPPER_ACTION_INSTALL:
- if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) {
+ if (_upgradingOldVersion) {
+ _installPage = PAGE_UPGRADE;
+ } else if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) {
_installPage = PAGE_SIMPLE_INSTALL;
} else {
_installPage = PAGE_INSTALL;
@@ -2608,6 +2620,179 @@ private:
}
}
+ static bool IsTargetPlatformx64(__in IBootstrapperEngine* pEngine) {
+ WCHAR platform[8];
+ DWORD platformLen = 8;
+
+ if (FAILED(pEngine->GetVariableString(L"TargetPlatform", platform, &platformLen))) {
+ return S_FALSE;
+ }
+
+ return ::CompareStringW(LOCALE_NEUTRAL, 0, platform, -1, L"x64", -1) == CSTR_EQUAL;
+ }
+
+ static HRESULT LoadOptionalFeatureStatesFromKey(
+ __in IBootstrapperEngine* pEngine,
+ __in HKEY hkHive,
+ __in LPCWSTR subkey
+ ) {
+ HKEY hKey;
+ LRESULT res;
+
+ if (IsTargetPlatformx64(pEngine)) {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+ } else {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
+ }
+ if (res == ERROR_FILE_NOT_FOUND) {
+ return S_FALSE;
+ }
+ if (res != ERROR_SUCCESS) {
+ return HRESULT_FROM_WIN32(res);
+ }
+
+ for (auto p = OPTIONAL_FEATURES; p->regName; ++p) {
+ res = RegQueryValueExW(hKey, p->regName, nullptr, nullptr, nullptr, nullptr);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ pEngine->SetVariableNumeric(p->variableName, 0);
+ } else if (res == ERROR_SUCCESS) {
+ pEngine->SetVariableNumeric(p->variableName, 1);
+ } else {
+ RegCloseKey(hKey);
+ return HRESULT_FROM_WIN32(res);
+ }
+ }
+
+ RegCloseKey(hKey);
+ return S_OK;
+ }
+
+ static HRESULT LoadTargetDirFromKey(
+ __in IBootstrapperEngine* pEngine,
+ __in HKEY hkHive,
+ __in LPCWSTR subkey
+ ) {
+ HKEY hKey;
+ LRESULT res;
+ DWORD dataType;
+ BYTE buffer[1024];
+ DWORD bufferLen = sizeof(buffer);
+
+ if (IsTargetPlatformx64(pEngine)) {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+ } else {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
+ }
+ if (res == ERROR_FILE_NOT_FOUND) {
+ return S_FALSE;
+ }
+ if (res != ERROR_SUCCESS) {
+ return HRESULT_FROM_WIN32(res);
+ }
+
+ res = RegQueryValueExW(hKey, nullptr, nullptr, &dataType, buffer, &bufferLen);
+ if (res == ERROR_SUCCESS && dataType == REG_SZ && bufferLen < sizeof(buffer)) {
+ pEngine->SetVariableString(L"TargetDir", reinterpret_cast<wchar_t*>(buffer));
+ }
+ RegCloseKey(hKey);
+ return HRESULT_FROM_WIN32(res);
+ }
+
+ static HRESULT LoadLauncherStateFromKey(
+ __in IBootstrapperEngine* pEngine,
+ __in HKEY hkHive
+ ) {
+ const LPCWSTR subkey = L"Software\\Python\\PyLauncher";
+ HKEY hKey;
+ LRESULT res;
+
+ if (IsTargetPlatformx64(pEngine)) {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+ } else {
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
+ }
+
+ if (res == ERROR_FILE_NOT_FOUND) {
+ return S_FALSE;
+ }
+ if (res != ERROR_SUCCESS) {
+ return HRESULT_FROM_WIN32(res);
+ }
+
+ res = RegQueryValueExW(hKey, nullptr, nullptr, nullptr, nullptr, nullptr);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ pEngine->SetVariableNumeric(L"Include_launcher", 0);
+ } else if (res == ERROR_SUCCESS) {
+ pEngine->SetVariableNumeric(L"Include_launcher", 1);
+ }
+
+ res = RegQueryValueExW(hKey, L"AssociateFiles", nullptr, nullptr, nullptr, nullptr);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ pEngine->SetVariableNumeric(L"AssociateFiles", 0);
+ } else if (res == ERROR_SUCCESS) {
+ pEngine->SetVariableNumeric(L"AssociateFiles", 1);
+ }
+
+ RegCloseKey(hKey);
+ return S_OK;
+ }
+
+ static void LoadOptionalFeatureStates(__in IBootstrapperEngine* pEngine) {
+ WCHAR subkeyFmt[256];
+ WCHAR subkey[256];
+ DWORD subkeyLen;
+ HRESULT hr;
+ HKEY hkHive;
+
+ // The launcher installation is separate from the Python install, so we
+ // check its state later. This also checks the file association option.
+
+ // Get the registry key from the bundle, to save having to duplicate it
+ // in multiple places.
+ subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]);
+ hr = pEngine->GetVariableString(L"OptionalFeaturesRegistryKey", subkeyFmt, &subkeyLen);
+ BalExitOnFailure(hr, "Failed to locate registry key");
+ subkeyLen = sizeof(subkey) / sizeof(subkey[0]);
+ hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen);
+ BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt);
+
+ // Check the current user's registry for existing features
+ hkHive = HKEY_CURRENT_USER;
+ hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey);
+ BalExitOnFailure1(hr, "Failed to read from HKCU\\%ls", subkey);
+ if (hr == S_FALSE) {
+ // Now check the local machine registry
+ hkHive = HKEY_LOCAL_MACHINE;
+ hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey);
+ BalExitOnFailure1(hr, "Failed to read from HKLM\\%ls", subkey);
+ if (hr == S_OK) {
+ // Found a system-wide install, so enable these settings.
+ pEngine->SetVariableNumeric(L"InstallAllUsers", 1);
+ pEngine->SetVariableNumeric(L"CompileAll", 1);
+ }
+ }
+
+ if (hr == S_OK) {
+ // Cannot change InstallAllUsersState when upgrading. While there's
+ // no good reason to not allow installing a per-user and an all-user
+ // version simultaneously, Burn can't handle the state management
+ // and will need to uninstall the old one.
+ pEngine->SetVariableString(L"InstallAllUsersState", L"disable");
+
+ // Get the previous install directory. This can be changed by the
+ // user.
+ subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]);
+ hr = pEngine->GetVariableString(L"TargetDirRegistryKey", subkeyFmt, &subkeyLen);
+ BalExitOnFailure(hr, "Failed to locate registry key");
+ subkeyLen = sizeof(subkey) / sizeof(subkey[0]);
+ hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen);
+ BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt);
+ LoadTargetDirFromKey(pEngine, hkHive, subkey);
+ }
+
+ LExit:
+ return;
+ }
public:
//
@@ -2667,7 +2852,8 @@ public:
_installPage = PAGE_LOADING;
_hrFinal = hrHostInitialization;
- _downgrading = FALSE;
+ _downgradingOtherVersion = FALSE;
+ _upgradingOldVersion = FALSE;
_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
_restartRequired = FALSE;
_allowRestart = FALSE;
@@ -2690,6 +2876,8 @@ public:
_hBAFModule = nullptr;
_baFunction = nullptr;
+
+ LoadOptionalFeatureStates(pEngine);
}
@@ -2748,7 +2936,8 @@ private:
DWORD _calculatedCacheProgress;
DWORD _calculatedExecuteProgress;
- BOOL _downgrading;
+ BOOL _downgradingOtherVersion;
+ BOOL _upgradingOldVersion;
BOOTSTRAPPER_APPLY_RESTART _restartResult;
BOOL _restartRequired;
BOOL _allowRestart;
diff --git a/Tools/msi/bundle/bootstrap/pythonba.vcxproj b/Tools/msi/bundle/bootstrap/pythonba.vcxproj
index 5d8337c..be12957 100644
--- a/Tools/msi/bundle/bootstrap/pythonba.vcxproj
+++ b/Tools/msi/bundle/bootstrap/pythonba.vcxproj
@@ -31,7 +31,7 @@
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <IntDir>$(ProjectDir)..\..\obj\$(Configuration)_Bootstrap\</IntDir>
+ <IntDir>$(PySourcePath)PCBuild\obj\$(Configuration)_$(Platform)_Setup\Bootstrap\</IntDir>
<OutDir>$(IntDir)</OutDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs
index 76e87ab..678dac4 100644
--- a/Tools/msi/bundle/bundle.wxs
+++ b/Tools/msi/bundle/bundle.wxs
@@ -23,14 +23,18 @@
<Variable Name="ShortVersion" Value="$(var.MajorVersionNumber).$(var.MinorVersionNumber)" />
<Variable Name="ShortVersionNoDot" Value="$(var.MajorVersionNumber)$(var.MinorVersionNumber)" />
- <Variable Name="InstallAllUsers" Value="0" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="TargetDir" Value="" Persisted="yes" bal:Overridable="yes" />
+ <Variable Name="InstallAllUsers" Value="0" bal:Overridable="yes" />
+ <Variable Name="TargetDir" Value="" bal:Overridable="yes" />
<?if $(var.Platform)~="x64" ?>
<Variable Name="DefaultAllUsersTargetDir" Value="[ProgramFiles64Folder]Python [ShortVersion]" bal:Overridable="yes" />
+ <Variable Name="TargetPlatform" Value="x64" />
<?else ?>
<Variable Name="DefaultAllUsersTargetDir" Value="[ProgramFilesFolder]Python [ShortVersion]" bal:Overridable="yes" />
+ <Variable Name="TargetPlatform" Value="x86" />
<?endif ?>
<Variable Name="DefaultJustForMeTargetDir" Value="[LocalAppDataFolder]Programs\Python\Python[ShortVersionNoDot]$(var.Suffix32)" bal:Overridable="yes" />
+ <Variable Name="OptionalFeaturesRegistryKey" Value="Software\$(var.TestPrefix)Python\PythonCore\[ShortVersion]$(var.Suffix32)\InstalledFeatures" />
+ <Variable Name="TargetDirRegistryKey" Value="Software\$(var.TestPrefix)Python\PythonCore\[ShortVersion]$(var.Suffix32)\InstallPath" />
<!--
An empty string will use the other defaults based on InstallAllUsers
@@ -44,23 +48,23 @@
<Variable Name="TargetDirState" Value="enabled" />
<Variable Name="CustomBrowseButtonState" Value="enabled" />
- <Variable Name="Include_core" Value="1" Persisted="yes" />
- <Variable Name="Include_exe" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_dev" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_lib" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_test" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_doc" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_tools" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_tcltk" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_pip" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_launcher" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_symbols" Value="0" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Include_debug" Value="0" Persisted="yes" bal:Overridable="yes" />
+ <Variable Name="Include_core" Value="1" />
+ <Variable Name="Include_exe" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_dev" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_lib" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_test" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_doc" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_tools" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_tcltk" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_pip" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_launcher" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_symbols" Value="0" bal:Overridable="yes" />
+ <Variable Name="Include_debug" Value="0" bal:Overridable="yes" />
- <Variable Name="AssociateFiles" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="Shortcuts" Value="1" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="PrependPath" Value="0" Persisted="yes" bal:Overridable="yes" />
- <Variable Name="CompileAll" Value="0" Persisted="yes" bal:Overridable="yes" />
+ <Variable Name="AssociateFiles" Value="1" bal:Overridable="yes" />
+ <Variable Name="Shortcuts" Value="1" bal:Overridable="yes" />
+ <Variable Name="PrependPath" Value="0" bal:Overridable="yes" />
+ <Variable Name="CompileAll" Value="0" bal:Overridable="yes" />
<Variable Name="SimpleInstall" Value="0" bal:Overridable="yes" />
diff --git a/Tools/msi/bundle/packagegroups/core.wxs b/Tools/msi/bundle/packagegroups/core.wxs
index 9df6b79..a789585 100644
--- a/Tools/msi/bundle/packagegroups/core.wxs
+++ b/Tools/msi/bundle/packagegroups/core.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="core_AllUsers_pdb"
SourceFile="core_pdb.msi"
@@ -17,6 +18,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="core_AllUsers_d"
SourceFile="core_d.msi"
@@ -25,6 +27,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="core_JustForMe"
@@ -34,6 +37,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip)">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="core_JustForMe_pdb"
SourceFile="core_pdb.msi"
@@ -42,6 +46,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="core_JustForMe_d"
SourceFile="core_d.msi"
@@ -50,6 +55,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and (Include_core or Include_exe or Include_launcher or Include_pip) and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/dev.wxs b/Tools/msi/bundle/packagegroups/dev.wxs
index f2ea29b..f7f5025 100644
--- a/Tools/msi/bundle/packagegroups/dev.wxs
+++ b/Tools/msi/bundle/packagegroups/dev.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_dev">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="dev_AllUsers_d"
SourceFile="dev_d.msi"
@@ -17,6 +18,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_dev and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="dev_JustForMe"
@@ -26,6 +28,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_dev">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="dev_JustForMe_d"
SourceFile="dev_d.msi"
@@ -34,6 +37,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_dev and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/doc.wxs b/Tools/msi/bundle/packagegroups/doc.wxs
index 7843f44..2f11e27 100644
--- a/Tools/msi/bundle/packagegroups/doc.wxs
+++ b/Tools/msi/bundle/packagegroups/doc.wxs
@@ -10,6 +10,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_doc">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="doc_JustForMe"
@@ -20,6 +21,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_doc">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/exe.wxs b/Tools/msi/bundle/packagegroups/exe.wxs
index 50346d9..03d6f62 100644
--- a/Tools/msi/bundle/packagegroups/exe.wxs
+++ b/Tools/msi/bundle/packagegroups/exe.wxs
@@ -10,6 +10,7 @@
EnableFeatureSelection="yes"
InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip)">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="exe_AllUsers_pdb"
SourceFile="exe_pdb.msi"
@@ -18,6 +19,7 @@
DownloadUrl="$(var.DownloadUrl)"
InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="exe_AllUsers_d"
SourceFile="exe_d.msi"
@@ -26,6 +28,7 @@
DownloadUrl="$(var.DownloadUrl)"
InstallCondition="InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="exe_JustForMe"
@@ -36,6 +39,7 @@
EnableFeatureSelection="yes"
InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip)">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="exe_JustForMe_pdb"
SourceFile="exe_pdb.msi"
@@ -44,6 +48,7 @@
DownloadUrl="$(var.DownloadUrl)"
InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="exe_JustForMe_d"
SourceFile="exe_d.msi"
@@ -52,6 +57,7 @@
DownloadUrl="$(var.DownloadUrl)"
InstallCondition="not InstallAllUsers and (Include_exe or Include_launcher or Include_pip) and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/lib.wxs b/Tools/msi/bundle/packagegroups/lib.wxs
index 47a97f1..f7c57c8 100644
--- a/Tools/msi/bundle/packagegroups/lib.wxs
+++ b/Tools/msi/bundle/packagegroups/lib.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_lib">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="lib_AllUsers_pdb"
SourceFile="lib_pdb.msi"
@@ -17,6 +18,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_lib and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="lib_AllUsers_d"
SourceFile="lib_d.msi"
@@ -25,6 +27,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_lib and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="lib_JustForMe"
@@ -34,6 +37,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_lib">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="lib_JustForMe_pdb"
SourceFile="lib_pdb.msi"
@@ -42,6 +46,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_lib and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="lib_JustForMe_d"
SourceFile="lib_d.msi"
@@ -50,6 +55,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_lib and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs
index 35978cc..4c50001 100644
--- a/Tools/msi/bundle/packagegroups/postinstall.wxs
+++ b/Tools/msi/bundle/packagegroups/postinstall.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_pip">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="pip_JustForMe"
SourceFile="pip.msi"
@@ -17,6 +18,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_pip">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="path_AllUsers"
@@ -26,6 +28,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and PrependPath">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="path_JustForMe"
SourceFile="path.msi"
@@ -34,6 +37,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and PrependPath">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<?define CompileAllCommand=-$(var.ShortVersion)$(var.Suffix32) -E -s -Wi "[TargetDir]\Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py2_|lib2to3\\tests|venv\\scripts" "[TargetDir]\Lib"?>
diff --git a/Tools/msi/bundle/packagegroups/tcltk.wxs b/Tools/msi/bundle/packagegroups/tcltk.wxs
index e0e3958..92f41cb 100644
--- a/Tools/msi/bundle/packagegroups/tcltk.wxs
+++ b/Tools/msi/bundle/packagegroups/tcltk.wxs
@@ -10,6 +10,7 @@
EnableFeatureSelection="yes"
InstallCondition="InstallAllUsers and Include_tcltk">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tcltk_AllUsers_pdb"
SourceFile="tcltk_pdb.msi"
@@ -19,6 +20,7 @@
EnableFeatureSelection="yes"
InstallCondition="InstallAllUsers and Include_tcltk and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tcltk_AllUsers_d"
SourceFile="tcltk_d.msi"
@@ -28,6 +30,7 @@
EnableFeatureSelection="yes"
InstallCondition="InstallAllUsers and Include_tcltk and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tcltk_JustForMe"
@@ -38,6 +41,7 @@
EnableFeatureSelection="yes"
InstallCondition="not InstallAllUsers and Include_tcltk">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tcltk_JustForMe_pdb"
SourceFile="tcltk_pdb.msi"
@@ -47,6 +51,7 @@
EnableFeatureSelection="yes"
InstallCondition="not InstallAllUsers and Include_tcltk and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tcltk_JustForMe_d"
SourceFile="tcltk_d.msi"
@@ -56,6 +61,7 @@
EnableFeatureSelection="yes"
InstallCondition="not InstallAllUsers and Include_tcltk and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/test.wxs b/Tools/msi/bundle/packagegroups/test.wxs
index b64e8ff..b3e0f3e 100644
--- a/Tools/msi/bundle/packagegroups/test.wxs
+++ b/Tools/msi/bundle/packagegroups/test.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_test">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="test_AllUsers_pdb"
SourceFile="test_pdb.msi"
@@ -17,6 +18,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_test and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="test_AllUsers_d"
SourceFile="test_d.msi"
@@ -25,6 +27,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_test and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="test_JustForMe"
@@ -34,6 +37,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_test">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="test_JustForMe_pdb"
SourceFile="test_pdb.msi"
@@ -42,6 +46,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_test and Include_symbols">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="test_JustForMe_d"
SourceFile="test_d.msi"
@@ -50,6 +55,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_test and Include_debug">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/bundle/packagegroups/tools.wxs b/Tools/msi/bundle/packagegroups/tools.wxs
index 06af5b5..c92f27b 100644
--- a/Tools/msi/bundle/packagegroups/tools.wxs
+++ b/Tools/msi/bundle/packagegroups/tools.wxs
@@ -9,6 +9,7 @@
ForcePerMachine="yes"
InstallCondition="InstallAllUsers and Include_tools">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
<MsiPackage Id="tools_JustForMe"
@@ -18,6 +19,7 @@
ForcePerMachine="no"
InstallCondition="not InstallAllUsers and Include_tools">
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
+ <MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
</MsiPackage>
</PackageGroup>
</Fragment>
diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs
index 7529aab..cc39540 100644
--- a/Tools/msi/common.wxs
+++ b/Tools/msi/common.wxs
@@ -5,6 +5,15 @@
</Fragment>
<Fragment>
+ <Component Id="OptionalFeature" Guid="*" Directory="InstallDirectory">
+ <Condition>OPTIONALFEATURESREGISTRYKEY</Condition>
+ <RegistryKey Root="HKMU" Key="[OPTIONALFEATURESREGISTRYKEY]">
+ <RegistryValue Type="string" Name="$(var.OptionalFeatureName)" Value="$(var.Version)" KeyPath="yes" />
+ </RegistryKey>
+ </Component>
+ </Fragment>
+
+ <Fragment>
<Property Id="UpgradeTable" Value="1" />
<Upgrade Id="$(var.UpgradeCode)">
diff --git a/Tools/msi/core/core_d.wxs b/Tools/msi/core/core_d.wxs
index 8422117..bb35f99 100644
--- a/Tools/msi/core/core_d.wxs
+++ b/Tools/msi/core/core_d.wxs
@@ -8,6 +8,7 @@
<Feature Id="DebugBinaries" AllowAdvertise="no" Title="!(loc.Title_d)" Description="!(loc.Description_d)">
<ComponentGroupRef Id="core_dll_d" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>
diff --git a/Tools/msi/core/core_pdb.wxs b/Tools/msi/core/core_pdb.wxs
index c9a558d..ba72d95 100644
--- a/Tools/msi/core/core_pdb.wxs
+++ b/Tools/msi/core/core_pdb.wxs
@@ -8,6 +8,7 @@
<Feature Id="Symbols" AllowAdvertise="no" Title="!(loc.TitlePdb)" Description="!(loc.DescriptionPdb)">
<ComponentGroupRef Id="core_symbols" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>
diff --git a/Tools/msi/dev/dev.wxs b/Tools/msi/dev/dev.wxs
index f8af9aa..a09e139 100644
--- a/Tools/msi/dev/dev.wxs
+++ b/Tools/msi/dev/dev.wxs
@@ -13,6 +13,7 @@
<?ifdef IncludeMinGWLib ?>
<ComponentGroupRef Id="dev_mingw" />
<?endif ?>
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>
diff --git a/Tools/msi/doc/doc.wxs b/Tools/msi/doc/doc.wxs
index 22b0213..bbe30a1 100644
--- a/Tools/msi/doc/doc.wxs
+++ b/Tools/msi/doc/doc.wxs
@@ -9,13 +9,16 @@
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<ComponentGroupRef Id="doc" Primary="yes" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
<Feature Id="Shortcuts" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<ComponentGroupRef Id="doc" />
<?ifdef DocFilename ?>
<Component Id="doc_shortcut" Directory="MenuDir" Guid="*">
- <RegistryValue Root="HKMU" Key="[REGISTRYKEY]\DocShortcuts" Type="integer" Value="1" KeyPath="yes" />
+ <RegistryKey Root="HKMU" Key="[OPTIONALFEATURESREGISTRYKEY]">
+ <RegistryValue Name="$(var.OptionalFeatureName)_shortcut" Type="string" Value="$(var.Version)" KeyPath="yes" />
+ </RegistryKey>
<Shortcut Id="python.chm"
Target="[#python.chm]"
Name="!(loc.ShortcutName)"
diff --git a/Tools/msi/exe/exe.wxs b/Tools/msi/exe/exe.wxs
index d8b05e0..dcbf646 100644
--- a/Tools/msi/exe/exe.wxs
+++ b/Tools/msi/exe/exe.wxs
@@ -11,6 +11,7 @@
<ComponentGroupRef Id="exe_python" Primary="yes" />
<ComponentGroupRef Id="exe_txt" />
<ComponentGroupRef Id="exe_icons" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
<Feature Id="Shortcuts" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
@@ -23,6 +24,7 @@
<RemoveFolder Id="Remove_MenuDir" Directory="MenuDir" On="uninstall" />
<RegistryKey Root="HKMU" Key="[REGISTRYKEY]">
<RegistryValue Key="InstallPath\InstallGroup" Type="string" Value="!(loc.ProductName)" KeyPath="yes" />
+ <RegistryValue Key="InstalledFeatures" Name="Shortcuts" Type="string" Value="$(var.Version)" />
</RegistryKey>
</Component>
</Feature>
diff --git a/Tools/msi/exe/exe_files.wxs b/Tools/msi/exe/exe_files.wxs
index 6422372..3b5fce4 100644
--- a/Tools/msi/exe/exe_files.wxs
+++ b/Tools/msi/exe/exe_files.wxs
@@ -23,6 +23,7 @@
<RegistryKey Root="HKMU" Key="[REGISTRYKEY]">
<RegistryValue Key="InstallPath" Type="string" Value="[InstallDirectory]" KeyPath="no" />
+ <RegistryValue Key="InstallPath" Name="ExecutablePath" Type="string" Value="[#python.exe]" KeyPath="no" />
</RegistryKey>
</Component>
<Component Id="pythonw.exe" Directory="InstallDirectory" Guid="$(var.PythonwExeComponentGuid)">
diff --git a/Tools/msi/launcher/launcher_files.wxs b/Tools/msi/launcher/launcher_files.wxs
index 9606dc6..589dee5 100644
--- a/Tools/msi/launcher/launcher_files.wxs
+++ b/Tools/msi/launcher/launcher_files.wxs
@@ -4,6 +4,7 @@
<ComponentGroup Id="launcher_exe">
<Component Id="py.exe" Directory="LauncherInstallDirectory" Guid="{B5107402-6958-461B-8B0A-4037D3327160}">
<File Id="py.exe" Name="py.exe" Source="py.exe" KeyPath="yes" />
+ <RegistryValue Root="HKMU" Key="Software\Python\PyLauncher" Value="[#py.exe]" Type="string" />
</Component>
<Component Id="pyw.exe" Directory="LauncherInstallDirectory" Guid="{8E52B8CD-48BB-4D74-84CD-6238BCD11F20}">
<File Id="pyw.exe" Name="pyw.exe" Source="pyw.exe" KeyPath="yes" />
@@ -12,12 +13,12 @@
<Component Id="launcher_path_cu" Directory="LauncherInstallDirectory" Guid="{95AEB930-367C-475C-A17E-A89BFCD4C670}">
<Condition>NOT ALLUSERS=1</Condition>
- <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher\InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
+ <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher" Name="InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
<Environment Id="PATH_CU" Action="set" Name="PATH" Part="first" Value="[LauncherInstallDirectory]" />
</Component>
<Component Id="launcher_path_lm" Directory="LauncherInstallDirectory" Guid="{4A41C365-4E27-4D38-A6D1-4A01B4A6500C}">
<Condition>ALLUSERS=1</Condition>
- <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher\InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
+ <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher" Name="InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
</Component>
</ComponentGroup>
</Fragment>
diff --git a/Tools/msi/launcher/launcher_reg.wxs b/Tools/msi/launcher/launcher_reg.wxs
index 204b4ed..eef71c8 100644
--- a/Tools/msi/launcher/launcher_reg.wxs
+++ b/Tools/msi/launcher/launcher_reg.wxs
@@ -3,7 +3,7 @@
<Fragment>
<ComponentGroup Id="launcher_reg">
<Component Id="file_association" Directory="LauncherInstallDirectory" Guid="{5AF84D9A-D820-456B-B230-6E0105A50276}">
- <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher\AssociateFiles" Value="1" Type="integer" />
+ <RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher" Name="AssociateFiles" Value="1" Type="integer" />
<ProgId Id="$(var.TestPrefix)Python.File" Description="!(loc.PythonFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
<Extension Id="$(var.FileExtension)" ContentType="text/plain">
diff --git a/Tools/msi/lib/lib.wxs b/Tools/msi/lib/lib.wxs
index b1aec75..2b04bcb 100644
--- a/Tools/msi/lib/lib.wxs
+++ b/Tools/msi/lib/lib.wxs
@@ -11,6 +11,7 @@
<ComponentGroupRef Id="lib_py" />
<ComponentGroupRef Id="lib_files" />
<ComponentGroupRef Id="lib_extensions" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>
diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props
index bd22345..1d9f0f0 100644
--- a/Tools/msi/msi.props
+++ b/Tools/msi/msi.props
@@ -43,7 +43,7 @@
</ItemGroup>
<PropertyGroup>
- <IntermediateOutputPath>$(MSBuildThisFileDirectory)\obj\$(Configuration)_$(Platform)\$(OutputName)</IntermediateOutputPath>
+ <IntermediateOutputPath>$(PySourcePath)PCBuild\obj\$(Configuration)_$(Platform)_Setup\$(OutputName)</IntermediateOutputPath>
<IntermediateOutputPath Condition="'$(OutputSuffix)' != ''">$(IntermediateOutputPath)_$(OutputSuffix)</IntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)' == ''">$(BuildPath)</OutputPath>
<OutputPath Condition="!HasTrailingSlash($(OutputPath))">$(OutputPath)\</OutputPath>
@@ -71,6 +71,7 @@
NextMajorVersionNumber=$(MajorVersionNumber).$([msbuild]::Add($(MinorVersionNumber), 1)).0.0;
Bitness=$(Bitness);
PyDebugExt=$(PyDebugExt);
+ OptionalFeatureName=$(OutputName);
</DefineConstants>
<DefineConstants Condition="'$(CRTRedist)' != ''">
$(DefineConstants);CRTRedist=$(CRTRedist);
@@ -112,9 +113,6 @@
<LinkerBindInputPaths Include="$(CRTRedist)" Condition="'$(CRTRedist)' != ''">
<BindName>redist</BindName>
</LinkerBindInputPaths>
- <LinkerBindInputPaths Include="$(CRTRedist)\$(Platform)" Condition="'$(CRTRedist)' != ''">
- <BindName>crt</BindName>
- </LinkerBindInputPaths>
</ItemGroup>
<Target Name="_ValidateMsiProps" BeforeTargets="PrepareForBuild">
diff --git a/Tools/msi/path/path.wxs b/Tools/msi/path/path.wxs
index 7e462e2..8b37936 100644
--- a/Tools/msi/path/path.wxs
+++ b/Tools/msi/path/path.wxs
@@ -9,7 +9,9 @@
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<Component Id="PrependPath_CU" Directory="InstallDirectory" Guid="*">
<Condition>NOT ALLUSERS=1</Condition>
- <RegistryValue KeyPath="yes" Root="HKCU" Key="[REGISTRYKEY]\PrependPath" Value="1" Type="integer" />
+ <RegistryKey Root="HKCU" Key="[REGISTRYKEY]">
+ <RegistryValue KeyPath="yes" Key="InstalledFeatures" Name="$(var.OptionalFeatureName)" Value="$(var.Version)" Type="string" />
+ </RegistryKey>
<CreateFolder Directory="Scripts" />
<RemoveFolder Id="Remove_Scripts_CU" Directory="Scripts" On="uninstall" />
@@ -19,7 +21,9 @@
</Component>
<Component Id="PrependPath_LM" Directory="InstallDirectory" Guid="*">
<Condition>ALLUSERS=1</Condition>
- <RegistryValue KeyPath="yes" Root="HKLM" Key="[REGISTRYKEY]\PrependPath" Value="1" Type="integer" />
+ <RegistryKey Root="HKLM" Key="[REGISTRYKEY]">
+ <RegistryValue KeyPath="yes" Key="InstalledFeatures" Name="$(var.OptionalFeatureName)" Value="$(var.Version)" Type="string" />
+ </RegistryKey>
<CreateFolder Directory="Scripts" />
<RemoveFolder Id="Remove_Scripts_LM" Directory="Scripts" On="uninstall" />
diff --git a/Tools/msi/pip/pip.wxs b/Tools/msi/pip/pip.wxs
index c46a868..19e9f5f 100644
--- a/Tools/msi/pip/pip.wxs
+++ b/Tools/msi/pip/pip.wxs
@@ -15,9 +15,7 @@
<Condition Message="!(loc.NoPython)">PYTHON_EXE</Condition>
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
- <Component Id="pip" Guid="*" Directory="InstallDirectory">
- <RegistryValue KeyPath="yes" Root="HKMU" Key="[REGISTRYKEY]\EnsurePipRun" Value="1" Type="integer" />
- </Component>
+ <ComponentRef Id="OptionalFeature" />
</Feature>
<?if $(var.Platform)~="x64" ?>
diff --git a/Tools/msi/tcltk/tcltk.wxs b/Tools/msi/tcltk/tcltk.wxs
index 5def5ed..0b83c5c 100644
--- a/Tools/msi/tcltk/tcltk.wxs
+++ b/Tools/msi/tcltk/tcltk.wxs
@@ -30,6 +30,7 @@
<Component Id="idle_reg" Directory="InstallDirectory">
<RegistryValue KeyPath="yes" Root="HKMU" Key="[REGISTRYKEY]\Idle" Type="string" Value="[#Lib_idlelib_idle.pyw]" />
</Component>
+ <ComponentRef Id="OptionalFeature" />
</Feature>
<Feature Id="AssociateFiles" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<ComponentGroupRef Id="tkinter_lib" />
diff --git a/Tools/msi/test/test.wxs b/Tools/msi/test/test.wxs
index de47785..f2ed64f 100644
--- a/Tools/msi/test/test.wxs
+++ b/Tools/msi/test/test.wxs
@@ -10,6 +10,7 @@
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<ComponentGroupRef Id="test_py" />
<ComponentGroupRef Id="test_extensions" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>
diff --git a/Tools/msi/tools/tools.wxs b/Tools/msi/tools/tools.wxs
index 366d4c6..8f8418a 100644
--- a/Tools/msi/tools/tools.wxs
+++ b/Tools/msi/tools/tools.wxs
@@ -9,6 +9,7 @@
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<ComponentGroupRef Id="tools_py" />
<ComponentGroupRef Id="tools_scripts" />
+ <ComponentRef Id="OptionalFeature" />
</Feature>
</Product>
</Wix>