在WPF C#应用程序中,用户可以从给定菜单启动“explorer.exe”进程。
通过
照常实现Process.Start("explorer.exe");
但是,我需要将同步进程的资源管理器数量限制为一个实例,而不是通过单击按钮将用户启动的实例数量限制为。
所以通常的方法是计算给定进程的实例数,“explorer.exe”实际上正在运行,如果有多个,则阻止Process.Start()。
问题在于我被困在计数功能中。这是我写的:
static bool CountProcess(string name) {
return false; // by defualt it returns false.
int counter = 0;
while(true) {
counter = Process.GetProcessesByName(name).length; // get the quantity of processes for a given name.
if(counter > 1) {
return true;
break;
}
}
}
然后我调用这个函数:
if(countProcess("explorer")) {
// Do nothing.
} else {
Process p = Process.Start("explorer.exe");
}
然而,在构建和执行之后,应用程序在打开给定进程时会被卡住。实际上,Visual Studio不提供任何调试反馈。
如何将此功能重构为1)操作,2)有效。
答案 0 :(得分:2)
为什么在CountProcess方法中有while循环?如果这应该很简单。
if(Process.GetProcessByName("explorer").Length == 0)
{
Process.Start("explorer.exe");
}
=== UPDATE ===
好的,我开始意识到你的问题是什么。
如果这不是explorer.exe - 此代码应该有效:
private static Process proc { get; set; }
private void button1_Click(object sender, EventArgs e)
{
if (proc == null || proc.HasExited)
{
proc = Process.Start("explorer.exe");
}
}
它检查是否曾创建过程(如果是第一次 - 允许处理,如果没有 - 拒绝开始新的)如果他第二次点击,则该过程不为null但它应该是proc.HasExited ==假(如果你没有关闭它)
但是如果你运行这段代码 - 可能会启动新的资源管理器窗口,因为这个新创建的进程会立即关闭。这是因为:
WaitForSingleObject立即返回的原因是Explorer是一个单实例程序(好吧,有限实例)
您可以尝试按照此处的建议修改注册表:
Open explorer window and wait for it to close
但是如果这是要在其他计算机上安装的客户端应用程序,我不建议以编程方式更改某个注册表。
===更新2 ====
以下解决方案有效 - 但有一些限制(您必须添加com参考:" Microsoft Internet Controls")它允许打开一个资源管理器窗口 - 然后检查窗口是否具有相同的"启动文件夹路径"因为基础已经打开(注意代码的两个不同位置的斜杠和反斜杠差异)
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:\");
}
}
因此,如果您选择基本路径(将作为参数发送到explorer.exe")为C:/,再次单击按钮后,将检查是否存在包含此类路径的任何资源管理器窗口(你是否打开过)
在此比较:Start explorer.exe without creating a window C#
在这里:Is there a way to close a particular instance of explorer with C#?
===更新3 ====
经过一番思考 - 我已经设法找到了解决方案:
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;
}
}