From a2faae7efd9338302cbeefa8e0ed78abe6fcf6ee Mon Sep 17 00:00:00 2001 From: hereafter Date: Thu, 7 Jan 2021 03:59:30 +0800 Subject: [PATCH] make "open terminal here" context menu work for directory background (#8638) This commit makes "Open in Windows Terminal" Context menu work again for directory background even on system that OS fix is not applied. This is a fallback solution to OS fixes mentioned in #6414. While OS fix is on its way, we need a fallback that works on existing OS versions. The approach to this is: when no item is selected (nullptr for IShellItemArray*), we use shell api to query the path of current active Explorer window. A special case is handled for Windows Desktop. Once we are able to obtain the path, we launch Windows Terminal with it. ## Validation Steps Performed 1. Right click on desktop to bring up the Context menu, pick "Open in Windows Terminal", verify that a terminal is opened with correct initial path. 2. Open a few File Explorer windows, pick any window, navigate to a folder, click on "Background" to bring up the context menu, click "Open in Windows Terminal" verify that a terminal is opened with correct initial path. Closes #6414 --- ...29ff14ec985d6b7bf09e296a831c955d41040b.txt | 14 +++ .github/actions/spell-check/expect/expect.txt | 40 ------ .../CascadiaPackage/Package-Dev.appxmanifest | 9 +- .../CascadiaPackage/Package-Pre.appxmanifest | 8 +- .../CascadiaPackage/Package.appxmanifest | 7 +- .../ShellExtension/OpenTerminalHere.cpp | 115 +++++++++++++++++- .../ShellExtension/OpenTerminalHere.h | 3 + .../WindowsTerminalShellExt.vcxproj | 10 +- .../TerminalConnection.vcxproj | 1 - 9 files changed, 135 insertions(+), 72 deletions(-) create mode 100644 .github/actions/spell-check/expect/a129ff14ec985d6b7bf09e296a831c955d41040b.txt diff --git a/.github/actions/spell-check/expect/a129ff14ec985d6b7bf09e296a831c955d41040b.txt b/.github/actions/spell-check/expect/a129ff14ec985d6b7bf09e296a831c955d41040b.txt new file mode 100644 index 000000000000..877c72b2e049 --- /dev/null +++ b/.github/actions/spell-check/expect/a129ff14ec985d6b7bf09e296a831c955d41040b.txt @@ -0,0 +1,14 @@ +checkboxes +CSIDL +csv +horiz +IDispatch +inlines +IWeb +Progman +reserialize +SHANDLE +SHGFP +udk +unfocus +WClass diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index ad77d9104047..5f2703f73666 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -168,7 +168,6 @@ BOLDFONT BOOLIFY bools boostorg -Bopomofo Borland BOTTOMLEFT BOTTOMRIGHT @@ -248,7 +247,6 @@ charset CHARSETINFO chcp checkbox -Checkboxes chh Childitem chk @@ -384,7 +382,6 @@ CORESYSTEM cotaskmem countof cout -CParams CPG cpinfo CPINFOEX @@ -413,7 +410,6 @@ csbi csbiex csharp CSHORT -cso csproj Csr csrmsg @@ -426,7 +422,6 @@ cstdlib cstr cstring cstyle -CSV CSwitch CText ctime @@ -628,7 +623,6 @@ doskey dotnet doubleclick downlevel -DOWNSCALE dpg dpi DPIAPI @@ -841,7 +835,6 @@ gcy gdi gdip gdirenderer -GENERATEPROJECTPRIFILE geopol GETALIAS GETALIASES @@ -957,7 +950,6 @@ hfont hglobal hh hhh -hhhh hhook hhx HIBYTE @@ -984,7 +976,6 @@ hmod hmodule hmon HMONITOR -Horiz HORZ hostable hostlib @@ -1097,10 +1088,8 @@ INITMENU inkscape inl INLINEPREFIX -Inlines INotify inout -INPATHROOT inproc Inputkeyinfo INPUTPROCESSORPROFILE @@ -1113,7 +1102,6 @@ INTERCEPTCOPYPASTE INTERNALNAME interop interoperability -intersectors inthread intptr intsafe @@ -1212,7 +1200,6 @@ KJ KLF KLMNOPQRST KLMNOPQRSTQQQQQ -Kode KU KVM KX @@ -1344,7 +1331,6 @@ mailto majorly makeappx MAKEINTRESOURCE -MAKEINTRESOURCEA MAKEINTRESOURCEW MAKELANGID MAKELONG @@ -1417,7 +1403,6 @@ monostate MOUSEACTIVATE MOUSEFIRST MOUSEHWHEEL -mousemode MOUSEMOVE mousewheel MOVESTART @@ -1439,7 +1424,6 @@ MSGSELECTMODE msiexec MSIL msix -msixbundle msrc msvcrt MSVS @@ -1842,7 +1826,6 @@ pshn PSHNOTIFY PSHORT pshpack -psin PSINGLE psl psldl @@ -1962,16 +1945,13 @@ Replymessage repositorypath rescap Resequence -Reserialize RESETCONTENT resheader resizable resmimetype -reso restrictedcapabilities resw resx -RETROII retval rfa rfc @@ -1991,7 +1971,6 @@ rgpwsz rgrc rgs rgui -rgus rgw rgwch rhs @@ -2042,14 +2021,11 @@ SBCSDBCS sbi sbiex sbold -sbri -scanbri scancode scanline schemename SCL scm -scol scprintf SCRBUF SCRBUFSIZE @@ -2128,7 +2104,6 @@ sfi SFINAE SFUI sgr -SGRXY SHCo shcore shellapi @@ -2183,9 +2158,6 @@ SOURCESDIRECTORY SPACEBAR spammy spand -spe -sph -spherefunctions splashscreen sprintf sqlproj @@ -2303,7 +2275,6 @@ TCI tcome tcommandline tcommands -tcon TDelegated TDP TEAMPROJECT @@ -2449,8 +2420,6 @@ ucdxml uch UCHAR ucs -UDK -UDKs UDM uer uget @@ -2473,7 +2442,6 @@ UNCPRIORITY undef Unescape unexpand -Unfocus unhighlighting unhosted unicode @@ -2564,7 +2532,6 @@ vga vgaoem viewkind viewports -Viginetting Virt VIRTTERM Virtualizing @@ -2781,7 +2748,6 @@ wwaproj WWith wx wxh -wz xa xact xamarin @@ -2800,14 +2766,12 @@ XColors xcopy XCount xdy -xe XEncoding xes Xes XES xff XFile -xlang XManifest XMath XMFLOAT @@ -2831,9 +2795,7 @@ xutr xvalue XVIRTUALSCREEN XWalk -XWV xy -xyw Xzn yact YAML @@ -2850,7 +2812,6 @@ YVIRTUALSCREEN Yw YWalk yx -yzx Zc ZCmd ZCtrl @@ -2862,7 +2823,6 @@ zu zxcvbnm zy AAAAABBBBBBCCC -AAAAA BBBBBCCC abcd LPMINMAXINFO diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index 173ca496ea75..f4fa79fb4a53 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -82,14 +82,9 @@ - + + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 57a2a38c178f..62fbb9de1dbb 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -82,15 +82,9 @@ - - diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 3565188a6301..fb44274e7f49 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -83,14 +83,9 @@ - diff --git a/src/cascadia/ShellExtension/OpenTerminalHere.cpp b/src/cascadia/ShellExtension/OpenTerminalHere.cpp index d5669e21f637..bd748338d7ab 100644 --- a/src/cascadia/ShellExtension/OpenTerminalHere.cpp +++ b/src/cascadia/ShellExtension/OpenTerminalHere.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "OpenTerminalHere.h" +#include // TODO GH#6112: Localize these strings static constexpr std::wstring_view VerbDisplayName{ L"Open in Windows Terminal" }; @@ -117,14 +118,29 @@ static std::wstring _getExePath() HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray, IBindCtx* /*pBindContext*/) { - DWORD count; - psiItemArray->GetCount(&count); + wil::unique_cotaskmem_string pszName; - winrt::com_ptr psi; - RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put())); + if (psiItemArray == nullptr) + { + // get the current path from explorer.exe + const auto path = this->_GetPathFromExplorer(); - wil::unique_cotaskmem_string pszName; - RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName)); + // no go, unable to get a reasonable path + if (path.empty()) + { + return S_FALSE; + } + pszName = wil::make_cotaskmem_string(path.c_str(), path.length()); + } + else + { + DWORD count; + psiItemArray->GetCount(&count); + + winrt::com_ptr psi; + RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put())); + RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName)); + } { wil::unique_process_information _piClient; @@ -214,3 +230,90 @@ HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum) *ppEnum = nullptr; return E_NOTIMPL; } + +std::wstring OpenTerminalHere::_GetPathFromExplorer() const +{ + using namespace std; + using namespace winrt; + + wstring path; + HRESULT hr = NOERROR; + + auto hwnd = ::GetForegroundWindow(); + if (hwnd == nullptr) + { + return path; + } + + TCHAR szName[MAX_PATH] = { 0 }; + ::GetClassName(hwnd, szName, MAX_PATH); + if (0 == StrCmp(szName, L"WorkerW") || + 0 == StrCmp(szName, L"Progman")) + { + //special folder: desktop + hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName); + if (FAILED(hr)) + { + return path; + } + + path = szName; + return path; + } + + if (0 != StrCmp(szName, L"CabinetWClass")) + { + return path; + } + + auto shell = create_instance(CLSID_ShellWindows); + if (shell == nullptr) + { + return path; + } + + com_ptr disp; + wil::unique_variant variant; + variant.vt = VT_I4; + + com_ptr browser; + // look for correct explorer window + for (variant.intVal = 0; + shell->Item(variant, disp.put()) == S_OK; + variant.intVal++) + { + com_ptr tmp; + if (FAILED(disp->QueryInterface(tmp.put()))) + { + continue; + } + + HWND tmpHWND = NULL; + hr = tmp->get_HWND(reinterpret_cast(&tmpHWND)); + if (hwnd == tmpHWND) + { + browser = tmp; + break; //found + } + } + + if (browser != nullptr) + { + wil::unique_bstr url; + hr = browser->get_LocationURL(&url); + if (FAILED(hr)) + { + return path; + } + + wstring sUrl(url.get(), SysStringLen(url.get())); + DWORD size = MAX_PATH; + hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL); + if (SUCCEEDED(hr)) + { + path = szName; + } + } + + return path; +} diff --git a/src/cascadia/ShellExtension/OpenTerminalHere.h b/src/cascadia/ShellExtension/OpenTerminalHere.h index c79fc3424aa8..c2dc4098dc44 100644 --- a/src/cascadia/ShellExtension/OpenTerminalHere.h +++ b/src/cascadia/ShellExtension/OpenTerminalHere.h @@ -46,6 +46,9 @@ struct __declspec(uuid("9f156763-7844-4dc4-b2b1-901f640f5155")) STDMETHODIMP GetCanonicalName(GUID* pguidCommandName); STDMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum); #pragma endregion + +private: + std::wstring _GetPathFromExplorer() const; }; CoCreatableClass(OpenTerminalHere); diff --git a/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj b/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj index 681bcad5cf7d..e95305528c4d 100644 --- a/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj +++ b/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj @@ -11,10 +11,13 @@ true - - + + + User32.lib;%(AdditionalDependencies) + + @@ -40,7 +43,6 @@ -