C# 在C中,如何从外部应用程序(在我的例子中是explorer)查找并关闭窗口,或者在从应用程序外部关闭窗口时触发事件#
就我而言 我试图启动和停止explorer.exe,但当我在下面的代码中运行时,会出现一个异常 “无法处理请求,因为进程已退出。” 那么如何在程序中找到打开和关闭它的资源管理器窗口呢 以及如何在打开的资源管理器窗口从程序外部关闭时触发事件C# 在C中,如何从外部应用程序(在我的例子中是explorer)查找并关闭窗口,或者在从应用程序外部关闭窗口时触发事件#,c#,windows,winforms,C#,Windows,Winforms,就我而言 我试图启动和停止explorer.exe,但当我在下面的代码中运行时,会出现一个异常 “无法处理请求,因为进程已退出。” 那么如何在程序中找到打开和关闭它的资源管理器窗口呢 以及如何在打开的资源管理器窗口从程序外部关闭时触发事件 现在我已经自己解决了这个问题。(thnx Jimi提供所有提示:-) 请注意,提供的代码只是为了分享我到目前为止在解决问题方面取得的进展,根本不完整。防故障、耐碰撞、消毒或其他 该示例启动一个自动化事件处理程序,该处理程序检查每个WindowOpenedEv
现在我已经自己解决了这个问题。(thnx Jimi提供所有提示:-) 请注意,提供的代码只是为了分享我到目前为止在解决问题方面取得的进展,根本不完整。防故障、耐碰撞、消毒或其他 该示例启动一个自动化事件处理程序,该处理程序检查每个
WindowOpenedEvent
是否具有类名CabinetWClass
和名称“:D\”
如果找到它,它会将ProcessID
和NativeWindowHandle
与AutoEle的表示形式一起存储在customclass的对象中
这种组合应该为打开的文件资源管理器窗口提供某种唯一标识符
代码在每个WindowClosedEvent
它测试保存在autoele
中的AutoMationElement是否在每个WindowClosedEvent
如果不是,则文件资源管理器窗口必须在程序外部关闭
以编程方式关闭窗口
我使用Windows API函数:
SendMessage()编码>并使用WM_CLOSE
(设置为常数)
按钮1在开始时可用,单击会在路径D上打开文件浏览器:\
按钮1将被禁用,而按钮2将被启用
当打开的浏览器窗口用按钮2关闭或从外部关闭时,程序
按钮2再次被禁用,按钮1被启用。
我相信有更好的方法,我期待看到一些更好的代码。我只是从这个开始,所以一切都是新的:-)
评论不用于扩展讨论;这段对话已经结束。
public partial class Form1 : Form
{
private readonly Process proc = new Process();
public Form1()
{
InitializeComponent();
button2.Enabled = false;
}
private void button1_Click(object sender, EventArgs e)
{
proc.StartInfo = new ProcessStartInfo {
FileName = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + "/explorer.exe",
Arguments = @"D:\",
UseShellExecute = false
};
proc.Start();
button1.Enabled = false;
button2.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
proc.Kill();
button1.Enabled = true;
button2.Enabled = false;
}
private void button3_Click(object sender, EventArgs e)
{
Process[] Findit = Process.GetProcessesByName("Explorer");
int a = Findit.Length;
}
}
SendMessagege(Handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Windows.Automation;
using System.Runtime.InteropServices;
namespace ExplorerOpenClose
{
//Class created to store a asomewhat unique identifier for the explorer window that opened (Combinaton ProcessID and NativeWindowHandle
public class AutoEle
{
public AutomationElement src;
public int ProcesId=0;
public int NativeWindowHandle=0;
}
public partial class Form1 : Form
{
private Process proc = new Process();
private AutoEle AutoEle = new AutoEle();
public Form1()
{
InitializeComponent();
button2.Enabled = false;
// Start a Automation EventHanlder on window open and window close
AutomationElement This = AutomationElement.RootElement.FindFirst(TreeScope.Subtree, Condition.TrueCondition);
RegisterForAutomationEvents(This);
}
// Button1 Opens a Explorer on path "D:\
private void button1_Click(object sender, EventArgs e)
{
proc.StartInfo = new ProcessStartInfo
{
FileName = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + "/explorer.exe",
Arguments = @"D:\",
UseShellExecute = false
};
proc.Start();
button1.Enabled = false;
button2.Enabled = true;
}
//With Button 2 Closes The browser that opened with Explorer on path "D:\
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
const UInt32 WM_CLOSE = 0x0010;
// Check That the Native WindowHandle is Still the one we found before belonging to the same process
// And close the Window
try
{
if (AutoEle.src.Current.ProcessId == AutoEle.ProcesId & AutoEle.src.Current.NativeWindowHandle == AutoEle.NativeWindowHandle)
{
SendMessage(new IntPtr(AutoEle.NativeWindowHandle), WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
AutoEle.ProcesId = 0;
AutoEle.NativeWindowHandle = 0;
}
}
catch (ElementNotAvailableException)
{
// The window was allready closed. which is strang that i would end up here because i check for that
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
Automation.RemoveAllEventHandlers();
base.OnFormClosed(e);
}
private void RegisterForAutomationEvents(AutomationElement targetControl)
{
AutomationEventHandler eventHandler = new AutomationEventHandler(OnWindowOpenOrClose);
Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, targetControl, TreeScope.Subtree,eventHandler);
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, targetControl, TreeScope.Subtree, eventHandler);
}
private void OnWindowOpenOrClose(object src, AutomationEventArgs e)
{
// Make sure the element still exists. Elements
// can disappear before the event is processed.
AutomationElement sourceElement;
try
{
sourceElement = src as AutomationElement;
}
catch (ElementNotAvailableException)
{
return;
}
if (e.EventId == WindowPattern.WindowOpenedEvent)
{
try
{
// check if it is ClassName CabinetWClass and the drive D:\ is the name
if (sourceElement.Current.ClassName == "CabinetWClass" & sourceElement.Current.Name == @"D:\")
{
// FOUND !!!! return sourceElement.Current.ProcessId;
// NativeWindowHandle = new IntPtr(sourceElement.Current.NativeWindowHandle);
//ProcessId = Process.GetProcessById(sourceElement.Current.ProcessId);
//ProcessId = sourceElement.Current.ProcessId;
//ProcToKill.Exited += new EventHandler (myProcess_Exited);
AutoEle.ProcesId = sourceElement.Current.ProcessId;
AutoEle.NativeWindowHandle = sourceElement.Current.NativeWindowHandle;
AutoEle.src = sourceElement;
}
}
catch (ElementNotAvailableException)
{
}
return;
}
if (e.EventId == WindowPattern.WindowClosedEvent)
{
try
{
if (AutoEle.ProcesId > 0)
{
try
{ // Tis will provoke am exception if the process does not exist anymore which means it was closed :-)
if (AutoEle.src.Current.ProcessId == AutoEle.ProcesId & AutoEle.src.Current.NativeWindowHandle == AutoEle.NativeWindowHandle);
}
catch (ElementNotAvailableException)
{
AutoEle.ProcesId = 0;
AutoEle.NativeWindowHandle = 0;
Invoke(new MethodInvoker(() =>
{
button1.Enabled = true;
button2.Enabled = false;
}));
}
}
}
catch (ElementNotAvailableException)
{
}
return;
}
}
}
}