ฉันจะรู้ได้อย่างไรว่ากระบวนการกำลังทำงานอยู่หรือไม่


155

เมื่อฉันได้รับการอ้างอิงถึงSystem.Diagnostics.Processฉันจะทราบได้อย่างไรว่ากระบวนการกำลังทำงานอยู่หรือไม่

คำตอบ:


252

นี่คือวิธีทำด้วยชื่อ:

Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
  MessageBox.Show("nothing");
else
  MessageBox.Show("run");

คุณสามารถวนซ้ำกระบวนการทั้งหมดเพื่อรับ ID สำหรับการจัดการในภายหลัง:

Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
   Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}

นี่คือสิ่งที่ฉันกำลังมองหา แม้ว่านี่จะเป็นการโพสต์ที่เก่ามาก แต่คุณจะอธิบายให้ฉันฟังว่านี่เป็น C # ที่ถูกต้องหรือไม่ ฉันไม่สงสัยเลยฉันเห็นว่าใช้งานได้ แต่ฉันไม่เคยเห็นถ้าไม่มี {}
MatthewD

4
@MatthewD: if/elseคำสั่งC # ที่มีความยาวเพียงหนึ่งบรรทัดไม่จำเป็นต้องมีเครื่องหมายปีกกาเพื่อระบุคำสั่งบล็อก นอกจากนี้ยังไปforeachและforงบ มันเดือดลงไปในรูปแบบการเข้ารหัส
Hallmanac

ฉันได้ทำการวิจัยเกี่ยวกับเรื่องนี้ด้วยพบว่าข้อมูลนั้น แต่ฉันไม่เห็นforข้อมูล ปีของ c # .net dev และฉันไม่เคยเห็นสไตล์นี้มาก่อน เหมือนที่พวกเขาพูดว่า "คุณเรียนรู้สิ่งใหม่ทุกวัน" ขอขอบคุณสำหรับการโพสต์และการตอบกลับ ..
MatthewD

3
@MatthewD ใช่นี่เป็นภาษาจริง (เช่น Java) เป็นวิธีปฏิบัติที่ดีโดยทั่วไปในการหลีกเลี่ยงผู้เดินสมุทรแบบนี้และใส่วงเล็บปีกกาไว้เสมอเนื่องจากมีโอกาสที่คุณอาจต้องเพิ่มคำสั่งเพิ่มเติมในอนาคตซึ่งในกรณีนี้การจัดฟันจะอยู่ที่นั่นเมื่อคุณต้องการ แต่สำหรับสิ่งต่าง ๆ เช่นนี้ถ้าคุณมั่นใจ 100% ว่าคุณต้องการเพียงข้อความเดียวมันก็โอเคที่จะทำและมีผลทางไวยากรณ์
David Mordigal

1
หากคุณไม่พบกระบวนการให้ลองลบส่วนขยายออก (เช่น: .exe)
DxTx

28

นี่เป็นวิธีที่ง่ายที่สุดที่ฉันพบหลังจากใช้ตัวสะท้อนแสง ฉันสร้างวิธีส่วนขยายสำหรับสิ่งนั้น:

public static class ProcessExtensions
{
    public static bool IsRunning(this Process process)
    {
        if (process == null) 
            throw new ArgumentNullException("process");

        try
        {
            Process.GetProcessById(process.Id);
        }
        catch (ArgumentException)
        {
            return false;
        }
        return true;
    }
}

Process.GetProcessById(processId)วิธีการเรียกProcessManager.IsProcessRunning(processId)วิธีการและพ่นArgumentExceptionในกรณีกระบวนการไม่อยู่ ด้วยเหตุผลบางอย่างProcessManagerชั้นเรียนเป็นภายใน ...


นี่เป็นคำตอบที่ดีจริงๆ อย่างไรก็ตามคุณไม่ควรผ่านข้อยกเว้น null ของอาร์กิวเมนต์ (เนื่องจากมีข้อยกเว้นอ้างอิง null จะถูกโยนทิ้งไปและคุณไม่ได้ทำอะไรกับข้อยกเว้นนอกจากนี้คุณจะได้รับ InvalidOperationException หากคุณไม่ได้เรียกใช้ Start () วิธีการหรือคุณรื้อฟื้นความใกล้ () วิธีผมโพสต์คำตอบไปยังบัญชีสำหรับทั้งสองสถานการณ์..
Aelphaeis

16

โซลูชันแบบซิงโครนัส:

void DisplayProcessStatus(Process process)
{
    process.Refresh();  // Important


    if(process.HasExited)
    {
        Console.WriteLine("Exited.");
    }
    else
    {
        Console.WriteLine("Running.");
    } 
}

โซลูชันแบบอะซิงโครนัส:

void RegisterProcessExit(Process process)
{
    // NOTE there will be a race condition with the caller here
    //   how to fix it is left as an exercise
    process.Exited += process_Exited;
}

static void process_Exited(object sender, EventArgs e)
{
   Console.WriteLine("Process has exited.");
}

6
สำหรับตัวเลือกแรก: ฉันจะรู้ได้อย่างไรว่ากระบวนการนั้นเริ่มต้นตั้งแต่แรก?
reshefm

8

reshefm มีคำตอบที่ดีงาม; อย่างไรก็ตามมันไม่ได้คำนึงถึงสถานการณ์ที่กระบวนการไม่เคยเริ่มต้นด้วย

นี่คือเวอร์ชันดัดแปลงของสิ่งที่เขาโพสต์

    public static bool IsRunning(this Process process)
    {
        try  {Process.GetProcessById(process.Id);}
        catch (InvalidOperationException) { return false; }
        catch (ArgumentException){return false;}
        return true;
    }

ฉันลบ ArgumentNullException ของเขาเพราะจริง ๆ แล้วมันน่าจะเป็นข้อยกเว้นการอ้างอิงเป็นโมฆะและมันก็ถูกโยนโดยระบบต่อไปและฉันยังคำนึงถึงสถานการณ์ที่กระบวนการไม่เคยเริ่มต้นด้วยหรือวิธีการปิด () ถูกใช้เพื่อปิด กระบวนการ.


โดยส่วนตัวแล้วฉันค่อนข้างจะเห็น ArgumentNullException เมื่อตรวจสอบข้อยกเว้นที่บันทึกไว้มากกว่า NullReferenceException เนื่องจาก ArgumentNullException นั้นชัดเจนมากขึ้นเกี่ยวกับสิ่งที่ผิดพลาด
ฌอน

1
@ ปกติฉันจะเห็นด้วยกับคุณ แต่นี่เป็นวิธีส่วนขยาย ฉันคิดว่ามันเหมาะสมกว่าที่จะโยนข้อยกเว้นตัวชี้โมฆะเนื่องจากไวยากรณ์ แต่ก็รู้สึกว่าสอดคล้องกับวิธีการโทรของวัตถุ null มากขึ้น
Aelphaeis

สิ่งนี้จะทริกเกอร์ตัวจัดการเหตุการณ์ FirstHandledException ทุกครั้ง วิธีการสแปมบันทึกของคุณมีเพื่อน
ความหน่วงแฝง

6

นี่ควรเป็นหนึ่งซับ:

public static class ProcessHelpers {
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}

3

ขึ้นอยู่กับว่าคุณต้องการให้ฟังก์ชันนี้น่าเชื่อถือแค่ไหน หากคุณต้องการทราบว่าอินสแตนซ์กระบวนการเฉพาะที่คุณยังทำงานอยู่และมีความแม่นยำ 100% แสดงว่าคุณไม่มีโชค สาเหตุที่มาจากวัตถุกระบวนการจัดการมีเพียง 2 วิธีในการระบุกระบวนการ

แรกคือรหัสกระบวนการ น่าเสียดายที่รหัสกระบวนการไม่ซ้ำกันและสามารถนำกลับมาใช้ใหม่ได้ การค้นหารายการกระบวนการสำหรับรหัสที่ตรงกันจะบอกคุณเท่านั้นว่ามีกระบวนการที่ใช้รหัสเดียวกันทำงานอยู่ แต่ไม่จำเป็นต้องเป็นกระบวนการของคุณ

รายการที่สองคือตัวจัดการกระบวนการ มันมีปัญหาแบบเดียวกันกับ Id และมันก็อึดอัดกว่าที่จะทำงานด้วย

หากคุณกำลังมองหาความน่าเชื่อถือในระดับกลางจากนั้นตรวจสอบรายการกระบวนการปัจจุบันของกระบวนการของ ID เดียวกันนั้นเพียงพอ


1

Process.GetProcesses()เป็นวิธีที่จะไป แต่คุณอาจต้องใช้เกณฑ์อย่างน้อยหนึ่งเกณฑ์เพื่อค้นหากระบวนการของคุณขึ้นอยู่กับว่ามันทำงานอย่างไร (เช่นเป็นบริการหรือแอพปกติไม่ว่าจะมีแถบหัวเรื่องหรือไม่ก็ตาม)


หากคุณใส่วิธีนี้ในการวนซ้ำมันมีค่าใช้จ่ายรอบ CPU มาก ฉันแนะนำให้ใช้ GetProcessByName () หรือ GetProcessByID ()
Hao Nguyen

0

อาจจะ (อาจ) ฉันกำลังอ่านคำถามผิด แต่คุณกำลังมองหาคุณสมบัติ HasExited ที่จะบอกคุณว่ากระบวนการที่เป็นตัวแทนโดยวัตถุกระบวนการของคุณได้ออกจาก (ทั้งปกติหรือไม่)

หากกระบวนการที่คุณมีการอ้างอิงมี UI คุณสามารถใช้คุณสมบัติการตอบสนองเพื่อตรวจสอบว่า UI กำลังตอบสนองต่อการป้อนข้อมูลของผู้ใช้หรือไม่

คุณยังสามารถตั้งค่า EnableRaisingEvents และจัดการเหตุการณ์ Exited (ซึ่งถูกส่งแบบ asychronously) หรือโทร WaitForExit () ถ้าคุณต้องการบล็อก


0

คุณสามารถสร้างอินสแตนซ์ของกระบวนการได้หนึ่งครั้งสำหรับกระบวนการที่คุณต้องการและติดตามกระบวนการโดยใช้วัตถุ. กระบวนการ NET นั้น (มันจะทำการติดตามต่อไปจนกว่าคุณจะเรียกปิดบนวัตถุ. NET นั้นอย่างชัดเจนแม้ว่ากระบวนการที่ติดตามนั้นได้ตายไปแล้ว [สิ่งนี้จะช่วยให้คุณมีเวลาใกล้กระบวนการหรือที่รู้จักว่า ExitTime ฯลฯ ])

การอ้างอิงhttp://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :

เมื่อกระบวนการที่เกี่ยวข้องออกจาก (นั่นคือเมื่อมันถูกปิดโดยระบบปฏิบัติการผ่านการเลิกจ้างปกติหรือผิดปกติ) ระบบจะจัดเก็บข้อมูลการดูแลเกี่ยวกับกระบวนการและกลับไปยังองค์ประกอบที่เรียกว่า WaitForExit ส่วนประกอบกระบวนการสามารถเข้าถึงข้อมูลซึ่งรวมถึง ExitTime โดยใช้หมายเลขอ้างอิงไปยังกระบวนการที่ออก

เนื่องจากกระบวนการที่เกี่ยวข้องได้จบการทำงานคุณสมบัติการจัดการของส่วนประกอบจะไม่ชี้ไปยังทรัพยากรกระบวนการที่มีอยู่อีกต่อไป หมายเลขอ้างอิงสามารถใช้เพื่อเข้าถึงข้อมูลของระบบปฏิบัติการเกี่ยวกับทรัพยากรกระบวนการเท่านั้น ระบบรับรู้ถึงการจัดการกับกระบวนการที่ไม่ได้เผยแพร่โดยส่วนประกอบกระบวนการดังนั้นจึงเก็บข้อมูล ExitTime และ Handle ไว้ในหน่วยความจำจนกว่าส่วนประกอบกระบวนการจะปล่อยทรัพยากรโดยเฉพาะ ด้วยเหตุผลนี้ทุกครั้งที่คุณเรียกใช้เริ่มสำหรับอินสแตนซ์กระบวนการให้เรียกปิดเมื่อกระบวนการที่เกี่ยวข้องได้สิ้นสุดลงและคุณไม่ต้องการข้อมูลการดูแลระบบอีกต่อไป ปิดทำให้หน่วยความจำที่จัดสรรให้กับกระบวนการที่ออกให้เป็นอิสระ


0

ฉันลองวิธีแก้ปัญหาของ Coincoin:
ก่อนประมวลผลไฟล์ฉันจะคัดลอกมันเป็นไฟล์ชั่วคราวและเปิด
เมื่อเสร็จแล้วฉันจะปิดแอปพลิเคชันหากยังคงเปิดอยู่และลบไฟล์ชั่วคราว:
ฉันเพิ่งใช้ตัวแปร Process และตรวจสอบภายหลัง:

private Process openApplication;  
private void btnOpenFile_Click(object sender, EventArgs e) {  
    ...
    // copy current file to fileCache  
    ...  
    // open fileCache with proper application
    openApplication = System.Diagnostics.Process.Start( fileCache );  
}

หลังจากนั้นฉันปิดแอปพลิเคชัน:

 ...   
openApplication.Refresh(); 

// close application if it is still open       
if ( !openApplication.HasExited() ) {
    openApplication.Kill();  
}

// delete temporary file  
System.IO.File.Delete( fileCache );

มันใช้งานได้ดี


3
ที่openApplication.HasExited()HasExited ไม่ใช่ฟังก์ชัน วิธีที่ถูกต้องก็openApplication.HasExitedคือ
caiosm1005

0

แม้จะรองรับ API จาก. Net framework ที่เกี่ยวข้องกับการตรวจสอบกระบวนการที่มีอยู่โดย process ID แต่ฟังก์ชั่นเหล่านั้นช้ามาก มีค่าใช้จ่ายจำนวนมากรอบ CPU เพื่อเรียกใช้ Process.GetProcesses () หรือ Process.GetProcessById / Name ()

วิธีเร็วมากในการตรวจสอบกระบวนการทำงานโดยใช้ ID คือการใช้ API พื้นเมืองOpenProcess () ถ้า return handle เป็น 0 กระบวนการจะไม่มีอยู่ ถ้าหมายเลขอ้างอิงต่างจาก 0 แสดงว่ากระบวนการกำลังทำงาน ไม่มีการรับประกันวิธีนี้จะใช้งานได้ 100% ตลอดเวลาเนื่องจากได้รับอนุญาต


0

มีปัญหามากมายที่เกี่ยวข้องกับสิ่งนี้เนื่องจากปัญหาอื่น ๆ ได้กล่าวถึงบางส่วนแล้ว:

  • สมาชิกอินสแตนซ์ใด ๆ ไม่รับประกันว่าจะปลอดภัยต่อเธรด ความหมายมีเงื่อนไขการแข่งขันที่อาจเกิดขึ้นกับอายุการใช้งานของสแน็ปช็อตในขณะที่พยายามประเมินคุณสมบัติของวัตถุ
  • ตัวจัดการกระบวนการจะโยน Win32Exception สำหรับ ACCESS DENIED โดยที่ไม่อนุญาตให้ใช้สิทธิ์สำหรับการประเมินนี้และคุณสมบัติอื่น ๆ
  • สำหรับสถานะ ISN'T RUNNING ArgumentException จะถูกเพิ่มเมื่อพยายามประเมินคุณสมบัติบางอย่าง

ไม่ว่าคุณสมบัติที่ผู้อื่นพูดถึงจะเป็นแบบภายในหรือไม่ก็ตามคุณยังสามารถรับข้อมูลจากพวกเขาผ่านการไตร่ตรองหากได้รับอนุญาต

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

คุณสามารถ pinvoke รหัส Win32 สำหรับSnapshotหรือคุณสามารถใช้WMIซึ่งช้ากว่า

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

ตัวเลือกอื่นจะเป็นOpenProcess / CloseProcess แต่คุณจะยังคงพบปัญหาเดียวกันกับข้อยกเว้นที่ถูกโยนเหมือนเดิม

สำหรับ WMI - OnNewEvent.Properties ["?"]:

  • "ParentProcessID"
  • "ProcessID"
  • "ProcessName"
  • "SECURITY_DESCRIPTOR"
  • "SessionID"
  • "ซิด"
  • "TIME_CREATED"

0
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
    MessageBox.Show("Working");
}
else
{
    MessageBox.Show("Not Working");
}

นอกจากนี้คุณสามารถใช้ตัวจับเวลาสำหรับตรวจสอบกระบวนการทุกครั้ง


3
จะไม่เป็นวิธีอื่น ๆ ? ถ้า length == 0 นั่นแปลว่าไม่ทำงาน
Jay Jacobs

คำตอบนั้นเหมือนกับ Patrick Desjardins: stackoverflow.com/a/262291/7713750
Rekshino

วิธีอื่น ๆ ที่มีความยาว> 0 หมายถึงพบกระบวนการ
HaseeB Mir

นี่อาจมีข้อผิดพลาด ( length == 0ควรแสดงNot Working) แต่ก็ยังทำงานได้สำเร็จ
Momoro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.