2596890212
This is me trying to merge5ff9a24
and75e2b5f
and LAWD it's impossible. But we don't really care, because we're gonna just toss out the locking from #11083 and instead move ApplicationState to the Monarch (in the future)
144 lines
5.3 KiB
C++
144 lines
5.3 KiB
C++
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\\" };
|
|
|
|
_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
|
|
// Package or the release package. We'll need to return different text, icons,
|
|
// and use different commandlines depending on which one the user requested.
|
|
// - Uses a C++11 "magic static" to make sure this is only computed once.
|
|
// - If we can't determine if it's the dev build or not, we'll default to true
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - true if we believe this extension is being run in the dev build package.
|
|
_TIL_INLINEPREFIX bool IsDevBuild()
|
|
{
|
|
// use C++11 magic statics to make sure we only do this once.
|
|
static const bool isDevBuild = []() -> bool {
|
|
if (IsPackaged())
|
|
{
|
|
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();
|
|
}
|
|
|
|
return true;
|
|
}();
|
|
return isDevBuild;
|
|
}
|
|
|
|
// Function Description:
|
|
// - Helper function for getting the path to the appropriate executable to use
|
|
// for this instance of the shell extension. If we're running the dev build,
|
|
// it should be a `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`.
|
|
_TIL_INLINEPREFIX const std::wstring& GetWtExePath()
|
|
{
|
|
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.
|
|
if (IsPackaged())
|
|
{
|
|
try
|
|
{
|
|
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();
|
|
}
|
|
|
|
// 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:
|
|
// - Quotes and escapes the given string so that it can be used as a command-line arg.
|
|
// - e.g. given `\";foo\` will return `"\\\"\;foo\\"` so that the caller can construct a command-line
|
|
// using something such as `fmt::format(L"wt --title {}", QuoteAndQuoteAndEscapeCommandlineArg(TabTitle()))`.
|
|
// Arguments:
|
|
// - arg - the command-line argument to quote and escape.
|
|
// Return Value:
|
|
// - the quoted and escaped command-line argument.
|
|
_TIL_INLINEPREFIX std::wstring QuoteAndEscapeCommandlineArg(const std::wstring_view& arg)
|
|
{
|
|
std::wstring out;
|
|
out.reserve(arg.size() + 2);
|
|
out.push_back(L'"');
|
|
|
|
size_t backslashes = 0;
|
|
for (const auto ch : arg)
|
|
{
|
|
if (ch == L'\\')
|
|
{
|
|
backslashes++;
|
|
}
|
|
else
|
|
{
|
|
if (ch == L';' || ch == L'"')
|
|
{
|
|
out.append(backslashes + 1, L'\\');
|
|
}
|
|
backslashes = 0;
|
|
}
|
|
out.push_back(ch);
|
|
}
|
|
|
|
out.append(backslashes, L'\\');
|
|
out.push_back(L'"');
|
|
return out;
|
|
}
|