I'm trying to capture the path of selected files and folders from the standard OpenFileDialog window created by another application.
I have seen that is possible to perform this task with windows explorer:
IntPtr handle = GetOpenFileDialogHwnd();
ArrayList selected = new ArrayList();
var shell = new Shell32.Shell();
foreach(SHDocVw.InternetExplorer window in shell.Windows())
{
if (window.HWND == (int)handle)
{
Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
foreach(Shell32.FolderItem item in items)
{
selected.Add(item.Path);
}
}
}
However, the SHDocVw.ShellWindows () method does not return the opened openFileDialog hwnd. As windows explorer is very similar to OpenFileDialog, I imagine there is some way to do a cast having the hwnd of OpenFileDialog for the Shell32.IShellFolderViewDual2 interface like:
var view = Shell32.ShellFolderViewDual2.FromHwnd(hwnd);
Is there any alternative way?
The goal is simple, make a log of files used in standard OpenFileDialog windows. Workable in Windows 7, 8, 10.
I know, it seems a very very very strange thing.
Edit:
Inspect.exe give me hope:
An open file dialog is not a shell window so it won't show up in the ShellWindows list.
You can send the undocumented WM_GETISHELLBROWSER (WM_USER+7) message to the dialog window, but the returned IShellBrowser pointer is only valid inside the same process. Using it in another process would cause access violation.
Once you got IShellBrowser you can get other interfaces like IShellView or IFolderView2. For selection you want to use IFolderView2::GetSelection.
It is possible to inject a proxy DLL into the target process to control the file dialog, but you can't write the DLL in C#.