The key to getting Explorer to do your dirty work lies in the IShellDispatch2 interface. Particular, the ShellExecute method.
IShellDispatch2 is one of the shell automation objects used to support scripting languages. However, that doesn’t mean you have to use VBScript to gain some value from it. In this case, IShellDispatch2::ShellExecute is exactly what we want, because it wraps the normal ShellExecute call but runs it from the context of the object implementing the interface - in this case, we want the IShellDispatch2 associated with the desktop shell.
Knowing this is only half the battle, though. The next trick is to figure out just how to get to the right IShellDispatch2 object (the one for the desktop shell instance of Explorer.exe).
Fortunately, one of our architects, Chris Guzak (seen on C9 here), was able to point me in the right direction and connect up all the dots.
Our hunt begins with the IShellWindows interface, which can be used not only to reliably find the HWND for the desktop shell window, but also to get an IDispatch interface for it:
IShellWindows *psw;
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
if (SUCCEEDED(hr))
{
HWND hwnd;
IDispatch* pdisp;
VARIANT vEmpty = {}; // VT_EMPTY
if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp))
{
Next, we need the IShellBrowser interface, and we get that by querying for IServiceProvider and asking the SID_STopLevelBrowser service for an IShellBrowser interface. And from there we can get the IShellView.
IShellBrowser *psb;
hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
if (SUCCEEDED(hr))
{
IShellView *psv;
hr = psb->QueryActiveShellView(&psv);
From there we need to get to that IShellDispatch2 interface that started this whole adventure.
IDispatch *pdispBackground;
HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
if (SUCCEEDED(hr))
{
IShellFolderViewDual *psfvd;
hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
if (SUCCEEDED(hr))
{
IDispatch *pdisp;
hr = psfvd->get_Application(&pdisp);
if (SUCCEEDED(hr))
{
IShellDispatch2 *psd;
hr = pdisp->QueryInterface(IID_PPV_ARGS(&psd));
At this point you should be able to figure out where to go from here.
If that’s not easy enough, watch out for Part 3 of this series in the next day or two. It will contain a sample and describe how the Start++ installer makes use of it.
[powered by WordPress.]
Hi. I'm Brandon. I'm a geek, and I work on Search technology for Windows at Microsoft. This is my blog.
The views expressed within my blog are my own - and are not in any way indicative of those of the company I work for, Microsoft, or it's employees. No warranties or other guarantees will be offered as to the quality of the opinions or anything else offered here.
Most popular searches that brought people here today:
an expression
contains an inva (2)search (1)windows vista start
search bar (1)google desktop
search crawl sh (1)windows vista 64 bit
+ downl (1)64 bit version of
silverlight (1)wds x64 (1)vista thinkpad
trackpad driver (1)windows don't take
flash (1)start (1)
April 27th, 2008 at 2:22 am
[...] FAQ | Start++ | Contact Me Getting the shell to run an application for you - Part 2: How April 27, 2008 at 2:07 am Windows Shell, Windows [...]
April 28th, 2008 at 4:09 am
Dude. That’s genius. Scary-ass complicated, but genius.
Now all that’s needed is to package this up in a Wix installer extension, and Bob’s yer uncle. Oh, and any idea on version compatibility?
Nice one.
Matt