Fix crash when unpackaged due to PrimaryLanguageOverride (#10434)
## Summary of the Pull Request `ApplicationLanguages::PrimaryLanguageOverride` requires packaged activation. This PR prevents any such application crashes, by skipping any calls to `PrimaryLanguageOverride`, as well as hiding the language selector in the settings UI. ## PR Checklist * [x] I work here * [x] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. ## Validation Steps Performed When WT is run unpackaged: * Doesn't crash during start ✔️ * SUI doesn't show the language selector ✔️
This commit is contained in:
parent
2bd5791feb
commit
1ae6e3b772
|
@ -114,7 +114,7 @@ try
|
|||
std::filesystem::path modulePath{ wil::GetModuleFileNameW<std::wstring>(wil::GetModuleInstanceHandle()) };
|
||||
modulePath.replace_filename(WindowsTerminalExe);
|
||||
// WindowsTerminal.exe,-101 will be the first icon group in WT
|
||||
// We're using WindowsTerminal here explicitly, and not wt (from _getExePath), because
|
||||
// We're using WindowsTerminal here explicitly, and not wt (from GetWtExePath), because
|
||||
// WindowsTerminal is the only one built with the right icons.
|
||||
const auto resource{ modulePath.wstring() + L",-101" };
|
||||
return SHStrDupW(resource.c_str(), ppszIcon);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
using namespace winrt::Windows::ApplicationModel;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
|
@ -913,18 +914,26 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
void AppLogic::_ApplyLanguageSettingChange()
|
||||
void AppLogic::_ApplyLanguageSettingChange() noexcept
|
||||
try
|
||||
{
|
||||
if (!IsPackaged())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using ApplicationLanguages = winrt::Windows::Globalization::ApplicationLanguages;
|
||||
|
||||
const auto language = _settings.GlobalSettings().Language();
|
||||
// NOTE: PrimaryLanguageOverride throws if this instance is unpackaged.
|
||||
const auto primaryLanguageOverride = ApplicationLanguages::PrimaryLanguageOverride();
|
||||
const auto language = _settings.GlobalSettings().Language();
|
||||
|
||||
if (primaryLanguageOverride != language)
|
||||
{
|
||||
ApplicationLanguages::PrimaryLanguageOverride(language);
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
void AppLogic::_RefreshThemeRoutine()
|
||||
{
|
||||
|
|
|
@ -131,7 +131,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void _ShowLoadWarningsDialog();
|
||||
bool _IsKeyboardServiceEnabled();
|
||||
|
||||
void _ApplyLanguageSettingChange();
|
||||
void _ApplyLanguageSettingChange() noexcept;
|
||||
void _RefreshThemeRoutine();
|
||||
fire_and_forget _ApplyStartupTaskStateChange();
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <ShObjIdl.h>
|
||||
#include <Propkey.h>
|
||||
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
// This property key isn't already defined in propkey.h, but is used by UWP Jumplist to determine the icon of the jumplist item.
|
||||
|
@ -52,66 +54,6 @@ static std::wstring _normalizeIconPath(std::wstring_view path)
|
|||
return std::wstring{ fullPath };
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Helper function for getting the path to the appropriate executable to use
|
||||
// for this instance of the jumplist. For the dev build, it should be `wtd.exe`,
|
||||
// but if we're preview or release, we want to make sure to get the correct
|
||||
// `wt.exe` that corresponds to _us_.
|
||||
// - If we're unpackaged, this needs to get us `WindowsTerminal.exe`, because
|
||||
// the `wt*exe` alias won't have been installed for this install.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the full path to the exe, one of `wt.exe`, `wtd.exe`, or `WindowsTerminal.exe`.
|
||||
static std::wstring_view _getExePath()
|
||||
{
|
||||
static constexpr std::wstring_view WtExe{ L"wt.exe" };
|
||||
static constexpr std::wstring_view WindowsTerminalExe{ L"WindowsTerminal.exe" };
|
||||
static constexpr std::wstring_view WtdExe{ L"wtd.exe" };
|
||||
|
||||
static constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\" };
|
||||
|
||||
// use C++11 magic statics to make sure we only do this once.
|
||||
static const std::wstring exePath = []() -> std::wstring {
|
||||
// First, check a packaged location for the exe. If we've got a package
|
||||
// family name, that means we're one of the packaged Dev build, packaged
|
||||
// Release build, or packaged Preview build.
|
||||
//
|
||||
// If we're the preview or release build, there's no way of knowing if the
|
||||
// `wt.exe` on the %PATH% is us or not. Fortunately, _our_ execution alias
|
||||
// is located in "%LOCALAPPDATA%\Microsoft\WindowsApps\<our package family
|
||||
// name>", _always_, so we can use that to look up the exe easier.
|
||||
try
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
const auto id{ package.Id() };
|
||||
const std::wstring pfn{ id.FamilyName() };
|
||||
const auto isDevPackage{ pfn.rfind(L"WindowsTerminalDev") == 0 };
|
||||
if (!pfn.empty())
|
||||
{
|
||||
const std::filesystem::path windowsAppsPath{ wil::ExpandEnvironmentStringsW<std::wstring>(LocalAppDataAppsPath.data()) };
|
||||
const std::filesystem::path wtPath{ windowsAppsPath / pfn / (isDevPackage ? WtdExe : WtExe) };
|
||||
return wtPath;
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// If we're here, then we couldn't resolve our exe from the package. This
|
||||
// means we're running unpackaged. We should just use the
|
||||
// WindowsTerminal.exe that's sitting in the directory next to us.
|
||||
try
|
||||
{
|
||||
std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||
module.replace_filename(WindowsTerminalExe);
|
||||
return module;
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return std::wstring{ WtExe };
|
||||
}();
|
||||
return exePath;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the items of the Jumplist based on the given settings.
|
||||
// Arguments:
|
||||
|
@ -187,7 +129,7 @@ winrt::fire_and_forget Jumplist::UpdateJumplist(const CascadiaSettings& settings
|
|||
// - Creates a ShellLink object. Each item in a jumplist is a ShellLink, which is sort of
|
||||
// like a shortcut. It requires the path to the application (wt.exe), the arguments to pass,
|
||||
// and the path to the icon for the jumplist item. The path to the application isn't passed
|
||||
// into this function, as we'll determine it with _getExePath
|
||||
// into this function, as we'll determine it with GetWtExePath
|
||||
// Arguments:
|
||||
// - name: The name of the item displayed in the jumplist.
|
||||
// - path: The path to the icon for the jumplist item.
|
||||
|
@ -204,7 +146,7 @@ winrt::fire_and_forget Jumplist::UpdateJumplist(const CascadiaSettings& settings
|
|||
{
|
||||
auto sh = winrt::create_instance<IShellLinkW>(CLSID_ShellLink, CLSCTX_ALL);
|
||||
|
||||
const auto module{ _getExePath() };
|
||||
const auto module{ GetWtExePath() };
|
||||
RETURN_IF_FAILED(sh->SetPath(module.data()));
|
||||
RETURN_IF_FAILED(sh->SetArguments(args.data()));
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "GlobalAppearancePageNavigationState.g.cpp"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
@ -47,6 +48,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
return language.NativeName();
|
||||
}
|
||||
|
||||
// Returns whether the language selector is available/shown.
|
||||
//
|
||||
// winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride()
|
||||
// doesn't work for unpackaged applications. The corresponding code in TerminalApp is disabled.
|
||||
// It would be confusing for our users if we presented a dysfunctional language selector.
|
||||
bool GlobalAppearance::LanguageSelectorAvailable()
|
||||
{
|
||||
return IsPackaged();
|
||||
}
|
||||
|
||||
// Returns the list of languages the user may override the application language with.
|
||||
// The returned list are BCP 47 language tags like {"und", "en-US", "de-DE", "es-ES", ...}.
|
||||
// "und" is short for "undefined" and is synonymous for "Use system language" in this code.
|
||||
|
@ -57,6 +68,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
return _languageList;
|
||||
}
|
||||
|
||||
if (!LanguageSelectorAvailable())
|
||||
{
|
||||
_languageList = {};
|
||||
return _languageList;
|
||||
}
|
||||
|
||||
// In order to return the language list this code does the following:
|
||||
// [1] Get all possible languages we want to allow the user to choose.
|
||||
// We have to acquire languages from multiple sources, creating duplicates. See below at [1].
|
||||
|
@ -144,30 +161,41 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
winrt::Windows::Foundation::IInspectable GlobalAppearance::CurrentLanguage()
|
||||
{
|
||||
if (_currentLanguage.empty())
|
||||
if (_currentLanguage)
|
||||
{
|
||||
_currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride();
|
||||
if (_currentLanguage.empty())
|
||||
{
|
||||
_currentLanguage = systemLanguageTag;
|
||||
}
|
||||
return _currentLanguage;
|
||||
}
|
||||
|
||||
return winrt::box_value(_currentLanguage);
|
||||
if (!LanguageSelectorAvailable())
|
||||
{
|
||||
_currentLanguage = {};
|
||||
return _currentLanguage;
|
||||
}
|
||||
|
||||
// NOTE: PrimaryLanguageOverride throws if this instance is unpackaged.
|
||||
auto currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride();
|
||||
if (currentLanguage.empty())
|
||||
{
|
||||
currentLanguage = systemLanguageTag;
|
||||
}
|
||||
|
||||
_currentLanguage = winrt::box_value(currentLanguage);
|
||||
return _currentLanguage;
|
||||
}
|
||||
|
||||
void GlobalAppearance::CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag)
|
||||
{
|
||||
_currentLanguage = winrt::unbox_value<winrt::hstring>(tag);
|
||||
_currentLanguage = tag;
|
||||
|
||||
const auto currentLanguage = winrt::unbox_value<winrt::hstring>(_currentLanguage);
|
||||
const auto globals = _State.Globals();
|
||||
if (_currentLanguage == systemLanguageTag)
|
||||
if (currentLanguage == systemLanguageTag)
|
||||
{
|
||||
globals.ClearLanguage();
|
||||
}
|
||||
else
|
||||
{
|
||||
globals.Language(_currentLanguage);
|
||||
globals.Language(currentLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,15 +35,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
// "Deutsch (Deutschland)". This works independently of the user's locale.
|
||||
static winrt::hstring LanguageDisplayConverter(const winrt::hstring& tag);
|
||||
|
||||
bool LanguageSelectorAvailable();
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> LanguageList();
|
||||
winrt::Windows::Foundation::IInspectable CurrentLanguage();
|
||||
void CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag);
|
||||
|
||||
private:
|
||||
std::vector<winrt::hstring> _GetSupportedLanguageTags();
|
||||
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _languageList{ nullptr };
|
||||
winrt::hstring _currentLanguage;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _languageList;
|
||||
winrt::Windows::Foundation::IInspectable _currentLanguage;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
GlobalAppearancePageNavigationState State { get; };
|
||||
|
||||
static String LanguageDisplayConverter(String tag);
|
||||
Boolean LanguageSelectorAvailable { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<String> LanguageList { get; };
|
||||
IInspectable CurrentLanguage;
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
<StackPanel Style="{StaticResource SettingsStackStyle}">
|
||||
<!-- Language -->
|
||||
<local:SettingContainer x:Uid="Globals_Language"
|
||||
Margin="0">
|
||||
Margin="0"
|
||||
Visibility="{x:Bind LanguageSelectorAvailable}">
|
||||
<ComboBox ItemsSource="{x:Bind LanguageList}"
|
||||
SelectedItem="{x:Bind CurrentLanguage, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Globalization.h>
|
||||
|
|
|
@ -2,21 +2,14 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include <argb.h>
|
||||
#include <conattrs.hpp>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include "CascadiaSettings.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../inc/DefaultSettings.h"
|
||||
#include "Utils.h"
|
||||
#include "LibraryResources.h"
|
||||
#include "CascadiaSettings.g.cpp"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "AzureCloudShellGenerator.h"
|
||||
#include "PowershellCoreProfileGenerator.h"
|
||||
#include "WslDistroGenerator.h"
|
||||
#include "AzureCloudShellGenerator.h"
|
||||
|
||||
#include "CascadiaSettings.g.cpp"
|
||||
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
|
|
|
@ -147,7 +147,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
std::unordered_set<std::string> _AccumulateJsonFilesInDirectory(const std::wstring_view directory);
|
||||
void _ParseAndLayerFragmentFiles(const std::unordered_set<std::string> files, const winrt::hstring source);
|
||||
|
||||
static bool _IsPackaged();
|
||||
static void _WriteSettings(std::string_view content, const hstring filepath);
|
||||
static std::optional<std::string> _ReadUserSettings();
|
||||
static std::optional<std::string> _ReadFile(HANDLE hFile);
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include <argb.h>
|
||||
#include "CascadiaSettings.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "Utils.h"
|
||||
#include "JsonUtils.h"
|
||||
#include <appmodel.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include <shlobj.h>
|
||||
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
// defaults.h is a file containing the default json settings in a std::string_view
|
||||
#include "defaults.h"
|
||||
|
@ -1058,20 +1055,6 @@ winrt::com_ptr<ColorScheme> CascadiaSettings::_FindMatchingColorScheme(const Jso
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if we're running in a packaged context.
|
||||
// If we are, we want to change our settings path slightly.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - true iff we're running in a packaged context.
|
||||
bool CascadiaSettings::_IsPackaged()
|
||||
{
|
||||
UINT32 length = 0;
|
||||
LONG rc = GetCurrentPackageFullName(&length, nullptr);
|
||||
return rc != APPMODEL_ERROR_NO_PACKAGE;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Writes the given content in UTF-8 to a settings file using the Win32 APIS's.
|
||||
// Will overwrite any existing content in the file.
|
||||
|
@ -1216,7 +1199,7 @@ winrt::hstring CascadiaSettings::SettingsPath()
|
|||
|
||||
std::filesystem::path parentDirectoryForSettingsFile{ localAppDataFolder.get() };
|
||||
|
||||
if (!_IsPackaged())
|
||||
if (!IsPackaged())
|
||||
{
|
||||
parentDirectoryForSettingsFile /= UnpackagedSettingsFolderName;
|
||||
}
|
||||
|
|
|
@ -25,23 +25,22 @@
|
|||
|
||||
#include <wil/cppwinrt.h>
|
||||
|
||||
#include <unknwn.h>
|
||||
|
||||
#include <hstring.h>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.ApplicationModel.AppExtensions.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||
#include <winrt/Windows.UI.Xaml.Media.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include <winrt/Windows.System.h>
|
||||
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||
|
||||
#include <winrt/Microsoft.Terminal.Core.h>
|
||||
#include <winrt/Microsoft.Terminal.Control.h>
|
||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||
|
||||
// Including TraceLogging essentials for the binary
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <winmeta.h>
|
||||
|
@ -52,11 +51,5 @@ TRACELOGGING_DECLARE_PROVIDER(g_hSettingsModelProvider);
|
|||
// JsonCpp
|
||||
#include <json.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <winrt/Microsoft.Terminal.Core.h>
|
||||
#include <winrt/Microsoft.Terminal.Control.h>
|
||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||
|
||||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||
#include "til.h"
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
constexpr std::wstring_view WtExe{ L"wt.exe" };
|
||||
constexpr std::wstring_view WtdExe{ L"wtd.exe" };
|
||||
constexpr std::wstring_view WindowsTerminalExe{ L"WindowsTerminal.exe" };
|
||||
constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\" };
|
||||
|
||||
static constexpr std::wstring_view WtExe{ L"wt.exe" };
|
||||
static constexpr std::wstring_view WtdExe{ L"wtd.exe" };
|
||||
static constexpr std::wstring_view WindowsTerminalExe{ L"WindowsTerminal.exe" };
|
||||
|
||||
static constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\" };
|
||||
_TIL_INLINEPREFIX bool IsPackaged()
|
||||
{
|
||||
static const bool isPackaged = []() -> bool {
|
||||
try
|
||||
{
|
||||
const auto package = winrt::Windows::ApplicationModel::Package::Current();
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
return isPackaged;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This is a helper to determine if we're running as a part of the Dev Build
|
||||
|
@ -18,19 +32,21 @@ static constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Micro
|
|||
_TIL_INLINEPREFIX bool IsDevBuild()
|
||||
{
|
||||
// use C++11 magic statics to make sure we only do this once.
|
||||
static bool isDevBuild = []() -> bool {
|
||||
try
|
||||
static const bool isDevBuild = []() -> bool {
|
||||
if (IsPackaged())
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
const auto id = package.Id();
|
||||
const std::wstring name{ id.FullName() };
|
||||
// Does our PFN start with WindowsTerminalDev?
|
||||
return name.rfind(L"WindowsTerminalDev", 0) == 0;
|
||||
try
|
||||
{
|
||||
const auto package = winrt::Windows::ApplicationModel::Package::Current();
|
||||
const auto id = package.Id();
|
||||
const auto name = id.FullName();
|
||||
return til::starts_with(name, L"WindowsTerminalDev");
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return true;
|
||||
}();
|
||||
|
||||
return isDevBuild;
|
||||
}
|
||||
|
||||
|
@ -45,9 +61,8 @@ _TIL_INLINEPREFIX bool IsDevBuild()
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - the full path to the exe, one of `wt.exe`, `wtd.exe`, or `WindowsTerminal.exe`.
|
||||
_TIL_INLINEPREFIX std::wstring GetWtExePath()
|
||||
_TIL_INLINEPREFIX const std::wstring& GetWtExePath()
|
||||
{
|
||||
// use C++11 magic statics to make sure we only do this once.
|
||||
static const std::wstring exePath = []() -> std::wstring {
|
||||
// First, check a packaged location for the exe. If we've got a package
|
||||
// family name, that means we're one of the packaged Dev build, packaged
|
||||
|
@ -57,37 +72,35 @@ _TIL_INLINEPREFIX std::wstring GetWtExePath()
|
|||
// `wt.exe` on the %PATH% is us or not. Fortunately, _our_ execution alias
|
||||
// is located in "%LOCALAPPDATA%\Microsoft\WindowsApps\<our package family
|
||||
// name>", _always_, so we can use that to look up the exe easier.
|
||||
try
|
||||
if (IsPackaged())
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
const auto id = package.Id();
|
||||
const std::wstring pfn{ id.FamilyName() };
|
||||
if (!pfn.empty())
|
||||
try
|
||||
{
|
||||
const std::filesystem::path windowsAppsPath{ wil::ExpandEnvironmentStringsW<std::wstring>(LocalAppDataAppsPath.data()) };
|
||||
const std::filesystem::path wtPath = windowsAppsPath / pfn / (IsDevBuild() ? WtdExe : WtExe);
|
||||
return wtPath;
|
||||
const auto package = winrt::Windows::ApplicationModel::Package::Current();
|
||||
const auto id = package.Id();
|
||||
const auto pfn = id.FamilyName();
|
||||
if (!pfn.empty())
|
||||
{
|
||||
const std::filesystem::path windowsAppsPath{ wil::ExpandEnvironmentStringsW<std::wstring>(LocalAppDataAppsPath.data()) };
|
||||
const std::filesystem::path wtPath = windowsAppsPath / std::wstring_view{ pfn } / (IsDevBuild() ? WtdExe : WtExe);
|
||||
return wtPath;
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// If we're here, then we couldn't resolve our exe from the package. This
|
||||
// means we're running unpackaged. We should just use the
|
||||
// WindowsTerminal.exe that's sitting in the directory next to us.
|
||||
try
|
||||
{
|
||||
HMODULE hModule = GetModuleHandle(nullptr);
|
||||
THROW_LAST_ERROR_IF(hModule == nullptr);
|
||||
std::wstring dllPathString;
|
||||
THROW_IF_FAILED(wil::GetModuleFileNameW(hModule, dllPathString));
|
||||
const std::filesystem::path dllPath{ dllPathString };
|
||||
const std::filesystem::path rootDir = dllPath.parent_path();
|
||||
std::filesystem::path wtPath = rootDir / WindowsTerminalExe;
|
||||
return wtPath;
|
||||
std::filesystem::path module = wil::GetModuleFileNameW<std::wstring>(nullptr);
|
||||
module.replace_filename(WindowsTerminalExe);
|
||||
return module;
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return L"wt.exe";
|
||||
return std::wstring{ WtExe };
|
||||
}();
|
||||
return exePath;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue