मेरे मामले में

मैं explorer.exe को प्रारंभ और बंद करने का प्रयास करता हूं, लेकिन जब मैं नीचे कोड चलाता हूं तो मुझे यह कहते हुए एक अपवाद मिलता है कि "अनुरोध संसाधित नहीं कर सकता क्योंकि प्रक्रिया समाप्त हो गई है।"

तो मैं एक्सप्लोरर विंडो को कैसे ढूंढूं जिसने इसे प्रोग्राम के भीतर से खोला और बंद किया?

और जब मेरे प्रोग्राम के बाहर से खुली हुई एक्सप्लोरर विंडो बंद हो रही है, तो मैं एक घटना को कैसे ट्रिगर करूं।


  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;            
    }         
      
}
-1
Hennie 14 सितंबर 2020, 18:05

1 उत्तर

सबसे बढ़िया उत्तर

अभी के लिए मैंने खुद ही समस्या का समाधान कर लिया है। (सभी सुझावों के लिए thnx जिमी :-))

ध्यान रखें कि प्रस्तुत कोड केवल समस्या को हल करने में मेरी प्रगति को साझा करने के लिए है और किसी भी तरह से पूर्ण नहीं है। फेलप्रूफ क्रैश रेसिस्टेंट सैनिटाइज्ड या जो भी हो।

उदाहरण एक ऑटोमेशन इवेंट हैंडलर शुरू करता है जो प्रत्येक WindowOpenedEvent को वर्ग नाम CabinetWClass और नाम ":D\" के लिए जांचता है।

यदि यह इसे पाता है, तो यह ऑटोमेशन एलिमेंट के प्रतिनिधित्व के साथ ProcessID और NativeWindowHandle को कस्टमक्लास AutoEle के ऑब्जेक्ट में स्टोर करता है।

इस संयोजन को खुली हुई फ़ाइल एक्सप्लोरर विंडो के लिए एक प्रकार का विशिष्ट पहचानकर्ता प्रस्तुत करना चाहिए।

कोड प्रत्येक WindowClosedEvent पर समान ऑटोमेशन इवेंट हैंडलर का उपयोग करता है यह परीक्षण करता है कि autoele में सहेजा गया AutoMationElement अभी भी प्रत्येक WindowClosedEvent पर मौजूद है या नहीं

यदि नहीं तो फ़ाइल एक्सप्लोरर विंडो प्रोग्राम के बाहर बंद होनी चाहिए।

विंडो को प्रोग्रामेटिक रूप से बंद करने के लिए मैं विंडोज एपीआई कार्यों का उपयोग करता हूं: SendMessage(); और WM_CLOSE का उपयोग करें (स्थिर के रूप में सेट करें)

SendMessagege(Handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 

Button1 प्रारंभ में उपलब्ध होता है और जब क्लिक किया जाता है तो पथ D:\ पर एक फ़ाइल ब्राउज़र खोलता है

बटन 1 अक्षम हो रहा है और फिर बटन 2 सक्षम हो जाएगा।

जब या तो खुली हुई ब्राउज़र विंडो बटन 2 के साथ या बाहर से बंद होती है, तो प्रोग्राम बटन 2 फिर से अक्षम हो जाता है और बटन 1 सक्षम हो जाता है। मुझे यकीन है कि बेहतर तरीके हैं और मैं कुछ बेहतर कोड देखने के लिए उत्सुक हूं। मैं अभी इसके साथ शुरुआत कर रहा हूं इसलिए सब कुछ नया है :-)

    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;
            }
        }        
    }
    
}
0
Hennie 17 सितंबर 2020, 00:31