diff options
Diffstat (limited to 'Tools/msi')
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] <a href="#">license terms</a>.</String> <String Id="InstallAcceptCheckbox">I &agree to the license terms and conditions</String> - <String Id="InstallJustForMeButton">&Install Now</String> - <String Id="InstallJustForMeButtonNote">[DefaultJustForMeTargetDir] + <String Id="InstallButton">&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">&Install</String> <String Id="InstallSimpleButtonNote">Uses setting preselected by your administrator</String> + <String Id="InstallUpgradeButton">&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&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 <a href="mailto:python-list@python.org">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 <a href="#">log file</a>.</String> <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String> <String Id="FailureRestartButton">&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> |