IShellWindows
のインスタンスを作成し、それを使用して現在開いているすべてのエクスプローラウィンドウを列挙します。関連するさまざまなインターフェイスを使用して、IShellWindows
で列挙された各項目のウィンドウハンドルと現在のフォルダをPIDL
の形式で取得できます。ウィンドウハンドルがGetForegroundWindow()
の結果と等しい場合は、PIDLをパスに変換します。
以下では、すべてのエクスプローラウィンドウに関する情報を取得するためのコードを示します。部分的にはcode of Raymond Chenに基づいていますが、スマートポインタを使用して、脆弱でクリーンなコードを使用します。私は例外を使ってエラー処理を追加しました。
まず含ん必要といくつかのユーティリティコード:
#include <Windows.h>
#include <shlobj.h>
#include <atlcomcli.h> // for COM smart pointers
#include <vector>
#include <system_error>
#include <memory>
// Throw a std::system_error if the HRESULT indicates failure.
template< typename T >
void ThrowIfFailed(HRESULT hr, T&& msg)
{
if(FAILED(hr))
throw std::system_error{ hr, std::system_category(), std::forward<T>(msg) };
}
// Deleter for a PIDL allocated by the shell.
struct CoTaskMemDeleter
{
void operator()(ITEMIDLIST* pidl) const { ::CoTaskMemFree(pidl); }
};
// A smart pointer for PIDLs.
using UniquePidlPtr = std::unique_ptr< ITEMIDLIST, CoTaskMemDeleter >;
今、私たちは、ウィンドウハンドルと、現在のフォルダのPIDL
含めて現在開いているすべてのエクスプローラウィンドウに関する情報を返すために機能GetCurrentExplorerFolders()
を定義します。 PIDL
パスとキャッチ例外に変換、GetCurrentExplorerFolders()
を呼び出す方法を示す
// Return value of GetCurrentExplorerFolders()
struct ExplorerFolderInfo
{
HWND hwnd = nullptr; // window handle of explorer
UniquePidlPtr pidl; // PIDL that points to current folder
};
// Get information about all currently open explorer windows.
// Throws std::system_error exception to report errors.
std::vector<ExplorerFolderInfo> GetCurrentExplorerFolders()
{
CComPtr<IShellWindows> pshWindows;
ThrowIfFailed(
pshWindows.CoCreateInstance(CLSID_ShellWindows),
"Could not create instance of IShellWindows");
long count = 0;
ThrowIfFailed(
pshWindows->get_Count(&count),
"Could not get number of shell windows");
std::vector<ExplorerFolderInfo> result;
result.reserve(count);
for(long i = 0; i < count; ++i)
{
ExplorerFolderInfo info;
CComVariant vi{ i };
CComPtr<IDispatch> pDisp;
ThrowIfFailed(
pshWindows->Item(vi, &pDisp),
"Could not get item from IShellWindows");
if(! pDisp)
// Skip - this shell window was registered with a NULL IDispatch
continue;
CComQIPtr<IWebBrowserApp> pApp{ pDisp };
if(! pApp)
// This window doesn't implement IWebBrowserApp
continue;
// Get the window handle.
pApp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&info.hwnd));
CComQIPtr<IServiceProvider> psp{ pApp };
if(! psp)
// This window doesn't implement IServiceProvider
continue;
CComPtr<IShellBrowser> pBrowser;
if(FAILED(psp->QueryService(SID_STopLevelBrowser, &pBrowser)))
// This window doesn't provide IShellBrowser
continue;
CComPtr<IShellView> pShellView;
if(FAILED(pBrowser->QueryActiveShellView(&pShellView)))
// For some reason there is no active shell view
continue;
CComQIPtr<IFolderView> pFolderView{ pShellView };
if(! pFolderView)
// The shell view doesn't implement IFolderView
continue;
// Get the interface from which we can finally query the PIDL of
// the current folder.
CComPtr<IPersistFolder2> pFolder;
if(FAILED(pFolderView->GetFolder(IID_IPersistFolder2, (void**) &pFolder)))
continue;
LPITEMIDLIST pidl = nullptr;
if(SUCCEEDED(pFolder->GetCurFolder(&pidl)))
{
// Take ownership of the PIDL via std::unique_ptr.
info.pidl = UniquePidlPtr{ pidl };
result.push_back(std::move(info));
}
}
return result;
}
例。
int main()
{
::CoInitialize(nullptr);
try
{
std::wcout << L"Currently open explorer windows:\n";
for(const auto& info : GetCurrentExplorerFolders())
{
wchar_t path[ 32767 ];
if(::SHGetPathFromIDListEx(info.pidl.get(), path, ARRAYSIZE(path), 0))
std::wcout << L"hwnd: 0x" << std::hex << info.hwnd << L", path: " << path << L"\n";
}
}
catch(std::system_error& e)
{
std::cout << "ERROR: " << e.what() << "\nError code: " << e.code() << "\n";
}
::CoUninitialize();
}
可能な出力:
Currently open explorer windows:
hwnd: 0x0030058E, path: C:\Windows
hwnd: 0x000C06D4, path: C:\Program Files
はたぶん、このスレッドがあなたにヒントを与えることができます。http://stackoverflow.com/questions/20960316/get-folder-path-from-explorer-window – OnNIX
HTTPS ://en.wikipedia.org/wiki/Dangling_pointer –
ハッキングを止めてシェルを使用します。また、Win32関数を呼び出す場合は、エラーをチェックする習慣が必要です。あなたの危険で戻り値を無視してください。 –