Why there is while loop in CountProcess method? It should be simple if.
if(Process.GetProcessByName("explorer").Length == 0)
{
Process.Start("explorer.exe");
}
=== UPDATE ===
Ok, I'm starting to realize what is your problem.
If this wasn't explorer.exe - this code should work:
private static Process proc { get; set; }
private void button1_Click(object sender, EventArgs e)
{
if (proc == null || proc.HasExited)
{
proc = Process.Start("explorer.exe");
}
}
It checks whether Process was ever created (if first time - allow processing, if not - deny starting a new one) If he clicks for the second time, the process is not null but it SHOULD BE as proc.HasExited == false (if you didn't close it)
But if you run this code - probably starting new explorer window will be possible because this newly created process is being closed immediately. And this is because:
The reason that WaitForSingleObject returns immediately is that Explorer is a single-instance program (well, limited-instance)
You can try modifying the registry as proposed here :
Open explorer window and wait for it to close
But if this to be client application to be installed on others computer, I wouldn't advise changing programmatically someone registry.
=== UPDATE 2 ====
This solution below works - but with some restrictions (You must add com reference: "Microsoft Internet Controls") It allows to open one explorer window - and then checks whether window with the same "start folder path" as the base is already opened (watch out for slash and backslash difference in two different places of the code)
using SHDocVw;
public bool ExistOpenedWindow()
{
ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;
foreach (InternetExplorer ie in _shellWindows)
{
//this parses the name of the process
processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
//this could also be used for IE windows with processType of "iexplore"
if (processType.Equals("explorer") && ie.LocationURL.Contains("C:/"))
{
return true;
}
}
return false;
}
private void button1_Click(object sender, EventArgs e)
{
if (proc == null || !ExistOpenedWindow())
{
proc = Process.Start("explorer.exe", @"C:\");
}
}
So if you choose your base path (which will be sent as argument to explorer.exe") to be C:/, after clicking button once again, it will check whether there is ANY explorer window containing such path (opened by you or not)
Compare here: Start explorer.exe without creating a window C#
And here: Is there a way to close a particular instance of explorer with C#?
=== UPDATE 3 ====
After some thoughts - i've managed to come to working solution:
public bool ExistOpenedWindow()
{
var currentlyOpenedWindows = GetAllOpenedExplorerWindow();
return currentlyOpenedWindows.Any(t => t.HWND == ActiveOpenedWindowHwnd);
}
public List<InternetExplorer> GetAllOpenedExplorerWindow()
{
List<InternetExplorer> windows = new List<InternetExplorer>();
ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;
foreach (InternetExplorer ie in _shellWindows)
{
//this parses the name of the process
processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
//this could also be used for IE windows with processType of "iexplore"
if (processType.Equals("explorer"))
{
windows.Add(ie);
}
}
return windows;
}
public static int ActiveOpenedWindowHwnd;
private void button1_Click(object sender, EventArgs e)
{
var currentlyOpenedWindows = GetAllOpenedExplorerWindow();
if (ActiveOpenedWindowHwnd == 0 || !ExistOpenedWindow())
{
Process.Start("explorer.exe");
ShellWindows windows;
while ((windows = new SHDocVw.ShellWindows()).Count <= currentlyOpenedWindows.Count)
{
Thread.Sleep(50);
}
var currentlyOpenedWindowsNew = GetAllOpenedExplorerWindow();
var openedWindow = currentlyOpenedWindowsNew.Except(currentlyOpenedWindows).Single();
ActiveOpenedWindowHwnd = openedWindow.HWND;
}
}