C# 在C中,如何从外部应用程序(在我的例子中是explorer)查找并关闭窗口,或者在从应用程序外部关闭窗口时触发事件#

C# 在C中,如何从外部应用程序(在我的例子中是explorer)查找并关闭窗口,或者在从应用程序外部关闭窗口时触发事件#,c#,windows,winforms,C#,Windows,Winforms,就我而言 我试图启动和停止explorer.exe,但当我在下面的代码中运行时,会出现一个异常 “无法处理请求,因为进程已退出。” 那么如何在程序中找到打开和关闭它的资源管理器窗口呢 以及如何在打开的资源管理器窗口从程序外部关闭时触发事件 现在我已经自己解决了这个问题。(thnx Jimi提供所有提示:-) 请注意,提供的代码只是为了分享我到目前为止在解决问题方面取得的进展,根本不完整。防故障、耐碰撞、消毒或其他 该示例启动一个自动化事件处理程序,该处理程序检查每个WindowOpenedEv

就我而言

我试图启动和停止explorer.exe,但当我在下面的代码中运行时,会出现一个异常 “无法处理请求,因为进程已退出。”

那么如何在程序中找到打开和关闭它的资源管理器窗口呢

以及如何在打开的资源管理器窗口从程序外部关闭时触发事件



现在我已经自己解决了这个问题。(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;
            }
        }        
    }
    
}