问题
I am using the following code so that when the user clicks on a button, an instance of Windows Explorer is opened at a specific path. But this causes a new instance of the Explorer to be opened.
I want to change it so that, if Explorer is already open in the same path, the program does not create a new process and instead bring the open instance to front.
private void button_Click(object sender, EventArgs e)
{
if (Directory.Exists(myPath))
Process filesFolder = Process.Start("explorer.exe", Conf.FilesLocation);
}
回答1:
You can use the "open" verb, which will open directories in explorer and re-use an an existing explorer.exe if you pass it a directory that it already has open:
So, assuming Conf.FilesLocation
is a directory:
var proc = new ProcessStartInfo();
proc.FileName = Conf.FilesLocation;
proc.Verb = "open";
proc.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc );
回答2:
What I have found to work as well, is to use the file://
protocol, when you do this Windows seems to give focus to the folder if it is already open, rather than opening another window
Process.Start("file://" + Conf.FilesLocation);
回答3:
Although @nos's answer works well, mostly (sometimes, in a not deterministically way it creates another explorer windows even though it may already exists), I became unsatisfied with the time spent by the Process.Start(proc)
to open an existing window, sometimes 2 to 4 seconds.
So, adapting some VB.NET code I achieve a very fast way of reusing a existing explorer window that is pointing to a desired folder:
First, add COM references:
using Shell32;//Shell32.dll for ShellFolderView
using SHDocVw;//Microsoft Internet Controls for IShellWindows
[DllImport("user32.dll")]
public static extern int ShowWindow(IntPtr Hwnd, int iCmdShow);
[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr Hwnd);
public static bool ShowInExplorer(string folderName)
{
var SW_RESTORE = 9;
var exShell = (IShellDispatch2)Activator.CreateInstance(
Type.GetTypeFromProgID("Shell.Application"));
foreach (ShellBrowserWindow w in (IShellWindows) exShell.Windows())
{
if (w.Document is ShellFolderView)
{
var expPath = w.Document.FocusedItem.Path;
if (!Directory.Exists(Path.GetDirectoryName(expPath)) ||
Path.GetDirectoryName(expPath) != folderName) continue;
if (IsIconic(new IntPtr(w.HWND)))
{
w.Visible = false;
w.Visible = true;
ShowWindow(new IntPtr(w.HWND),SW_RESTORE);
break;
}
else
{
w.Visible = false;
w.Visible = true;
break;
}
}
}
}
Although we are interested in ShellFolderView objects, and foreach (ShellBrowserWindow w in (ShellFolderView) exShell.Windows())
was more logical, unfortunately ShellFolderView does not implement IEnumerable, so, no foreach :(
Anyway, these is a very fast (200 ms) way of select and blink the correct already opened explorer window.
来源:https://stackoverflow.com/questions/33826845/if-windows-explorer-is-open-at-a-specific-path-do-not-create-a-new-instance