2010-07-13 23 views
14

कार्य: यदि माता पिता प्रक्रिया समाप्त ऑटो सभी चाइल्ड प्रक्रियाओं को बंद। अभिभावक आय को न केवल सही तरीके से समाप्त किया जा सकता है, बल्कि उदाहरण के लिए ProcessExplorer में भी मार डाला जा सकता है। मैं इसे कैसे कर सकता हूं?कैसे बच्चे प्रक्रियाओं को समाप्त जब जनक प्रक्रिया सी # में समाप्त

С topic सलाह में इसी प्रकार के प्रश्न नौकरी वस्तुओं का उपयोग करें। बाहरी डीएलएल निर्यात किए बिना सी # में इसका उपयोग कैसे करें?


मैंने जॉब ऑब्जेक्ट्स का उपयोग करने की कोशिश की। लेकिन यह कोड ठीक से काम नहीं करता है:

var job = PInvoke.CreateJobObject(null, null); 
    var jobli = new PInvoke.JOBOBJECT_BASIC_LIMIT_INFORMATION(); 

    jobli.LimitFlags = PInvoke.LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 
        | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_PRIORITY_CLASS 
        | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_TIME 
        | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 
        | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_MEMORY; 

    var res = PInvoke.SetInformationJobObject(job, PInvoke.JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation, jobli, 48); 

    if (!res) 
    { 
    int b = PInvoke.GetLastError(); 
    Console.WriteLine("Error " + b); 
    } 

    var Prc = Process.Start(...); 

    PInvoke.AssignProcessToJobObject(job, Prc.Handle); 

PInvoke.SetInformationJobObject त्रुटि के साथ देता है। GetLastError त्रुटि 24 देता है। हालांकि, PInvoke.AssignProcessToJobObject काम करता है और जॉब कतार में जोड़ा गया बाल प्रक्रिया (मैं इसे ProcessExplorer में देख सकता हूं)। लेकिन, क्योंकि PInvoke.SetInformationJobObject काम नहीं करता है - जब मैं माता-पिता को मारता हूं तो उत्पन्न प्रक्रिया जीवित रहती है।

मैं इस कोड में गलत क्या है?

+0

अन्य प्रश्न उत्तर मेरे लिए अच्छा प्रतीत होता है, बस कर्नेल 32 से कार्यों को पिनवोक करें। http://www.pinvoke.net/default.aspx/kernel32.assignprocesstojobobject –

उत्तर

4

आप बच्चे की प्रक्रिया के लिए एक तर्क के रूप माता पिता की प्रक्रिया के ProcessID पारित कर सकते हैं। और फिर बाल प्रक्रियाएं समय-समय पर जांच के लिए ज़िम्मेदार होंगी कि माता-पिता की प्रक्रिया अभी भी चल रही है या नहीं। (Process.GetProcessById पर कॉल करके)

पैरेंट प्रक्रिया के अस्तित्व को ट्रैक करने का एक और तरीका Mutex सिंक्रनाइज़ेशन आदिम का उपयोग करना है। अभिभावक एप्लिकेशन प्रारंभ में बच्चों द्वारा ज्ञात नाम के साथ एक वैश्विक म्यूटेक्स बना देगा। बच्चे समय-समय पर जांच सकते हैं कि म्यूटेक्स अभी भी मौजूद है या नहीं, अगर नहीं। (एक बार जब माता-पिता की प्रक्रिया बंद हो जाती है तो म्यूटेक्स सिस्टम द्वारा स्वचालित रूप से नष्ट हो जाएगा, चाहे जिस तरह से बंद हो।)

+1

दोनों सलाह उपयोगी नहीं हैं - बाल प्रक्रियाएं मेरी नहीं हैं। वे कोई कार्यक्रम हो सकते हैं। – LionSoft

+2

@LionSoft: क्या आपके पास एक और बाल प्रक्रिया हो सकती है जो उन बच्चों की प्रक्रियाओं के निर्माण के लिए जिम्मेदार होगी? फिर वह प्रक्रिया जांच सकती है कि क्या माता-पिता की प्रक्रिया अभी भी चल रही है और यदि नहीं तो अन्य बच्चों को मार दें। – Regent

+0

लेकिन अगर ऐसा करना है तो "एक और बाल प्रक्रिया" को मजबूर कर दिया जाएगा? – LionSoft

2

विंडोज़ माता-पिता की प्रक्रिया बंद होने पर बच्चों की प्रक्रिया को बंद करने के लिए मजबूर नहीं करती है। जब आप टास्क मैनेजर या प्रोसेस एक्सप्लोरर जैसे टूल में "किल ट्री" चुनते हैं, तो टूल वास्तव में सभी बाल प्रक्रियाओं को पाता है और उन्हें एक-एक करके मारता है।

यदि आप यह सुनिश्चित करना चाहते हैं कि आपके आवेदन को समाप्त होने पर बाल प्रक्रियाएं साफ़ की जाएंगी, तो आप एक प्रोसेस मैनेजर क्लास बना सकते हैं जो वास्तव में प्रक्रियाओं को उत्पन्न करने वाले आईडीस्पोज़ेबल को लागू करता है, उनके उदाहरणों का ट्रैक रखता है और उनमें से प्रत्येक को निपटान पर कॉल करता है, जैसे

public class ProcessManager:IDisposable 
{ 
    List<Process> processes=new List<Process>(); 

    public Process Start(ProcessStartInfo info) 
    { 
     var newProcess = Process.Start(info); 
     newProcess.EnableRaisingEvents = true 
     processes.Add(newProcess); 
     newProcess.Exited += (sender, e) => processes.Remove(newProcess); 
     return newProcess; 
    } 

    ~ProcessManager() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     foreach (var process in processes) 
     { 
      try 
      { 
       if (!process.HasExited) 
        process.Kill(); 
      } 
      catch{}      
     } 
    } 
} 
+0

दुर्भाग्यवश, जब मैं ProcessExplorer में प्रक्रिया को शायद ही मारता हूं तो प्रक्रिया को अंतिमकरण कोड करने का कोई मौका नहीं है। इसलिए, आपका एक्सपेल केवल तभी काम करेगा जब मूल प्रक्रिया सही ढंग से समाप्त हो जाएगी। बीटीडब्ल्यू, अपने उदाहरण को सही करने के लिए, इसे लाइन ** newProcess.EnableRaisingEvents = true; ** * बाहर * ईवेंट असाइन करने से पहले जोड़ना होगा। – LionSoft

+2

जैसा कि मैंने कहा था, जब माता-पिता की प्रक्रिया मर जाती है तो विंडोज़ बाल प्रक्रियाओं को मार नहीं देती है। इसे लागू करने के लिए कोई ओएस तंत्र नहीं है। एक बच्चा प्रोसेस अपने माता-पिता से संबंधित नहीं है। यदि आप प्रसंस्करण नौकरियों को विकसित करना चाहते हैं जो प्रक्रिया समाप्त होने पर साफ होने की गारंटी है, तो आपको धागे का उपयोग करना होगा। आप EnableRaisingEvents के बारे में सही हैं, इसे ठीक करें। –

+2

स्पॉन्ड प्रक्रियाओं को मारने के लिए कम से कम दो ओएस तंत्र हैं: 1. डीबगर के रूप में बाल प्रक्रिया को संलग्न करें। 2. JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE ध्वज के साथ जॉब ऑब्जेक्ट्स का उपयोग करें लेकिन मैं अब तक इन दोनों विधियों को काम नहीं कर सकता। :( – LionSoft

3

क्या आपने त्रुटि कोड पर ध्यान दिया था? त्रुटि 24 ERROR_BAD_LENGTH है, जिसका शायद मतलब है कि 48 संरचना की सही लंबाई नहीं है। मुझे लगता है कि यह 44 है, लेकिन आपको सुनिश्चित करने के लिए sizeof करना चाहिए।

7

खिड़कियों पर एक प्रक्रिया पेड़ को मारने के लिए, केवल माता पिता प्रक्रिया या प्रक्रिया आईडी को देखते हुए, आप इस प्रक्रिया के पेड़ चलने के लिए की आवश्यकता होगी।

के लिए, आप एक दिया प्रक्रिया के लिए माता-पिता की प्रक्रिया आईडी प्राप्त करने के लिए एक तरह से की आवश्यकता होगी।

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Threading; 
using System.Diagnostics; 
using System.Management; 

namespace KillProcessTree 
{ 

public static class MyExtensions 
{ 
    public static int GetParentProcessId(this Process p) 
    { 
     int parentId = 0; 
     try 
     { 
      ManagementObject mo = new ManagementObject("win32_process.handle='" + p.Id + "'"); 
      mo.Get(); 
      parentId = Convert.ToInt32(mo["ParentProcessId"]); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
      parentId = 0; 
     } 
     return parentId; 
    } 
} 

एक बार आपके पास यह है कि वास्तव में पेड़ को मारना मुश्किल नहीं है।

class Program 
{ 
    /// <summary> 
    /// Kill specified process and all child processes 
    /// </summary> 
    static void Main(string[] args) 
    { 
     if (args.Length < 1) 
     { 
      Console.WriteLine("Usage: KillProcessTree <pid>"); 
      return; 
     } 

     int pid = int.Parse(args[0]); 

     Process root = Process.GetProcessById(pid); 
     if (root != null) 
     { 
      Console.WriteLine("KillProcessTree " + pid); 

      var list = new List<Process>(); 
      GetProcessAndChildren(Process.GetProcesses(), root, list, 1); 

      // kill each process 
      foreach (Process p in list) 
      { 
       try 
       { 
        p.Kill(); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.ToString()); 
       } 
      } 
     } 
     else 
     { 
      Console.WriteLine("Unknown process id: " + root); 
     } 
    } 

    /// <summary> 
    /// Get process and children 
    /// We use postorder (bottom up) traversal; good as any when you kill a process tree </summary> 
    /// </summary> 
    /// <param name="plist">Array of all processes</param> 
    /// <param name="parent">Parent process</param> 
    /// <param name="output">Output list</param> 
    /// <param name="indent">Indent level</param> 
    private static void GetProcessAndChildren(Process[] plist, Process parent, List<Process> output, int indent) 
    { 
     foreach (Process p in plist) 
     { 
      if (p.GetParentProcessId() == parent.Id) 
      { 
       GetProcessAndChildren(plist, p, output, indent + 1); 
      } 
     } 
     output.Add(parent); 
     Console.WriteLine(String.Format("{0," + indent*4 + "} {1}", parent.Id, parent.MainModule.ModuleName)); 
    } 
} 
} // namespace 
8

मैंने ऊपर दिए गए कोड की कोशिश की और वास्तव में, यह काम नहीं करता है, खराब आकार की शिकायत करता है।इसका कारण यह है कि संरचना मेजबान मंच के आधार पर परिवर्तन आकार का उपयोग करती है; मूल कोड खंड (एक दर्जन वेबसाइटों पर देखा गया) 32 बिट अनुप्रयोग मानता है।

इस पर संरचना स्विच करें (IntPtr आकार बदलने वाले सदस्यों को नोट करें) और यह काम करेगा। कम से कम इसने मेरे लिए किया।

[StructLayout(LayoutKind.Sequential)] 
struct JOBOBJECT_BASIC_LIMIT_INFORMATION 
{ 
    public Int64 PerProcessUserTimeLimit; 
    public Int64 PerJobUserTimeLimit; 
    public Int16 LimitFlags; 
    public UIntPtr MinimumWorkingSetSize; 
    public UIntPtr MaximumWorkingSetSize; 
    public Int16 ActiveProcessLimit; 
    public Int64 Affinity; 
    public Int16 PriorityClass; 
    public Int16 SchedulingClass; 
}