在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不提供任何调试反馈。
该功能如何重构为1)可操作的,2)高效的。
发布于 2017-08-01 16:16:48
为什么CountProcess方法中存在Why循环?应该很简单如果。
if(Process.GetProcessByName("explorer").Length == 0)
{
Process.Start("explorer.exe");
}===更新===
好吧,我开始意识到你的问题是什么。
如果这不是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");
}
}它检查进程是否曾经创建过(如果第一次允许处理,如果不拒绝启动新进程),如果他第二次单击,进程不是空的,但它应该是proc.HasExited == false (如果您没有关闭它)。
但是,如果您运行此代码-可能启动新的资源管理器窗口将是可能的,因为这个新创建的进程将立即关闭。这是因为:
WaitForSingleObject立即返回的原因是资源管理器是一个单实例程序(嗯,有限实例)。
您可以尝试按此处建议的方式修改注册表:
Open explorer window and wait for it to close
但是,如果这是要安装在其他计算机上的客户端应用程序,我不会建议以编程方式更改某个注册表。
===更新2 ====
下面的解决方案是可行的--但有一些限制(必须添加com引用:“”),它允许打开一个资源管理器窗口,然后检查窗口是否与已经打开的“开始文件夹路径”相同(请注意代码中两个不同位置的斜杠和反斜杠差异)。
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;
}
}https://stackoverflow.com/questions/45442681
复制相似问题