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
This commit is contained in:
hereafter 2021-01-07 03:59:30 +08:00 committed by GitHub
parent 6b2ae625a5
commit fcca88ab25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 73 deletions

View file

@ -0,0 +1,14 @@
checkboxes
CSIDL
csv
horiz
IDispatch
inlines
IWeb
Progman
reserialize
SHANDLE
SHGFP
udk
unfocus
WClass

View file

@ -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

View file

@ -82,14 +82,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

View file

@ -82,15 +82,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

View file

@ -83,14 +83,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

View file

@ -3,6 +3,7 @@
#include "pch.h"
#include "OpenTerminalHere.h"
#include <ShlObj.h>
// 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);
winrt::com_ptr<IShellItem> psi;
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
wil::unique_cotaskmem_string pszName;
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
if (psiItemArray == nullptr)
{
// get the current path from explorer.exe
const auto path = this->_GetPathFromExplorer();
// 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<IShellItem> 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<IShellWindows>(CLSID_ShellWindows);
if (shell == nullptr)
{
return path;
}
com_ptr<IDispatch> disp;
wil::unique_variant variant;
variant.vt = VT_I4;
com_ptr<IWebBrowserApp> browser;
// look for correct explorer window
for (variant.intVal = 0;
shell->Item(variant, disp.put()) == S_OK;
variant.intVal++)
{
com_ptr<IWebBrowserApp> tmp;
if (FAILED(disp->QueryInterface(tmp.put())))
{
continue;
}
HWND tmpHWND = NULL;
hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&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;
}

View file

@ -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);

View file

@ -11,10 +11,13 @@
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>User32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="OpenTerminalHere.h" />
@ -40,7 +43,6 @@
<None Include="packages.config" />
<None Include="WindowsTerminalShellExt.def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
@ -56,7 +58,5 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>

View file

@ -81,6 +81,5 @@
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>