เมื่อฉันได้รับการอ้างอิงถึงSystem.Diagnostics.Process
ฉันจะทราบได้อย่างไรว่ากระบวนการกำลังทำงานอยู่หรือไม่
เมื่อฉันได้รับการอ้างอิงถึงSystem.Diagnostics.Process
ฉันจะทราบได้อย่างไรว่ากระบวนการกำลังทำงานอยู่หรือไม่
คำตอบ:
นี่คือวิธีทำด้วยชื่อ:
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);
}
if/else
คำสั่งC # ที่มีความยาวเพียงหนึ่งบรรทัดไม่จำเป็นต้องมีเครื่องหมายปีกกาเพื่อระบุคำสั่งบล็อก นอกจากนี้ยังไปforeach
และfor
งบ มันเดือดลงไปในรูปแบบการเข้ารหัส
for
ข้อมูล ปีของ c # .net dev และฉันไม่เคยเห็นสไตล์นี้มาก่อน เหมือนที่พวกเขาพูดว่า "คุณเรียนรู้สิ่งใหม่ทุกวัน" ขอขอบคุณสำหรับการโพสต์และการตอบกลับ ..
นี่เป็นวิธีที่ง่ายที่สุดที่ฉันพบหลังจากใช้ตัวสะท้อนแสง ฉันสร้างวิธีส่วนขยายสำหรับสิ่งนั้น:
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
ชั้นเรียนเป็นภายใน ...
โซลูชันแบบซิงโครนัส:
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.");
}
reshefm มีคำตอบที่ดีงาม; อย่างไรก็ตามมันไม่ได้คำนึงถึงสถานการณ์ที่กระบวนการไม่เคยเริ่มต้นด้วย
นี่คือเวอร์ชันดัดแปลงของสิ่งที่เขาโพสต์
public static bool IsRunning(this Process process)
{
try {Process.GetProcessById(process.Id);}
catch (InvalidOperationException) { return false; }
catch (ArgumentException){return false;}
return true;
}
ฉันลบ ArgumentNullException ของเขาเพราะจริง ๆ แล้วมันน่าจะเป็นข้อยกเว้นการอ้างอิงเป็นโมฆะและมันก็ถูกโยนโดยระบบต่อไปและฉันยังคำนึงถึงสถานการณ์ที่กระบวนการไม่เคยเริ่มต้นด้วยหรือวิธีการปิด () ถูกใช้เพื่อปิด กระบวนการ.
นี่ควรเป็นหนึ่งซับ:
public static class ProcessHelpers {
public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
ขึ้นอยู่กับว่าคุณต้องการให้ฟังก์ชันนี้น่าเชื่อถือแค่ไหน หากคุณต้องการทราบว่าอินสแตนซ์กระบวนการเฉพาะที่คุณยังทำงานอยู่และมีความแม่นยำ 100% แสดงว่าคุณไม่มีโชค สาเหตุที่มาจากวัตถุกระบวนการจัดการมีเพียง 2 วิธีในการระบุกระบวนการ
แรกคือรหัสกระบวนการ น่าเสียดายที่รหัสกระบวนการไม่ซ้ำกันและสามารถนำกลับมาใช้ใหม่ได้ การค้นหารายการกระบวนการสำหรับรหัสที่ตรงกันจะบอกคุณเท่านั้นว่ามีกระบวนการที่ใช้รหัสเดียวกันทำงานอยู่ แต่ไม่จำเป็นต้องเป็นกระบวนการของคุณ
รายการที่สองคือตัวจัดการกระบวนการ มันมีปัญหาแบบเดียวกันกับ Id และมันก็อึดอัดกว่าที่จะทำงานด้วย
หากคุณกำลังมองหาความน่าเชื่อถือในระดับกลางจากนั้นตรวจสอบรายการกระบวนการปัจจุบันของกระบวนการของ ID เดียวกันนั้นเพียงพอ
Process.GetProcesses()
เป็นวิธีที่จะไป แต่คุณอาจต้องใช้เกณฑ์อย่างน้อยหนึ่งเกณฑ์เพื่อค้นหากระบวนการของคุณขึ้นอยู่กับว่ามันทำงานอย่างไร (เช่นเป็นบริการหรือแอพปกติไม่ว่าจะมีแถบหัวเรื่องหรือไม่ก็ตาม)
อาจจะ (อาจ) ฉันกำลังอ่านคำถามผิด แต่คุณกำลังมองหาคุณสมบัติ HasExited ที่จะบอกคุณว่ากระบวนการที่เป็นตัวแทนโดยวัตถุกระบวนการของคุณได้ออกจาก (ทั้งปกติหรือไม่)
หากกระบวนการที่คุณมีการอ้างอิงมี UI คุณสามารถใช้คุณสมบัติการตอบสนองเพื่อตรวจสอบว่า UI กำลังตอบสนองต่อการป้อนข้อมูลของผู้ใช้หรือไม่
คุณยังสามารถตั้งค่า EnableRaisingEvents และจัดการเหตุการณ์ Exited (ซึ่งถูกส่งแบบ asychronously) หรือโทร WaitForExit () ถ้าคุณต้องการบล็อก
คุณสามารถสร้างอินสแตนซ์ของกระบวนการได้หนึ่งครั้งสำหรับกระบวนการที่คุณต้องการและติดตามกระบวนการโดยใช้วัตถุ. กระบวนการ NET นั้น (มันจะทำการติดตามต่อไปจนกว่าคุณจะเรียกปิดบนวัตถุ. NET นั้นอย่างชัดเจนแม้ว่ากระบวนการที่ติดตามนั้นได้ตายไปแล้ว [สิ่งนี้จะช่วยให้คุณมีเวลาใกล้กระบวนการหรือที่รู้จักว่า ExitTime ฯลฯ ])
การอ้างอิงhttp://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
เมื่อกระบวนการที่เกี่ยวข้องออกจาก (นั่นคือเมื่อมันถูกปิดโดยระบบปฏิบัติการผ่านการเลิกจ้างปกติหรือผิดปกติ) ระบบจะจัดเก็บข้อมูลการดูแลเกี่ยวกับกระบวนการและกลับไปยังองค์ประกอบที่เรียกว่า WaitForExit ส่วนประกอบกระบวนการสามารถเข้าถึงข้อมูลซึ่งรวมถึง ExitTime โดยใช้หมายเลขอ้างอิงไปยังกระบวนการที่ออก
เนื่องจากกระบวนการที่เกี่ยวข้องได้จบการทำงานคุณสมบัติการจัดการของส่วนประกอบจะไม่ชี้ไปยังทรัพยากรกระบวนการที่มีอยู่อีกต่อไป หมายเลขอ้างอิงสามารถใช้เพื่อเข้าถึงข้อมูลของระบบปฏิบัติการเกี่ยวกับทรัพยากรกระบวนการเท่านั้น ระบบรับรู้ถึงการจัดการกับกระบวนการที่ไม่ได้เผยแพร่โดยส่วนประกอบกระบวนการดังนั้นจึงเก็บข้อมูล ExitTime และ Handle ไว้ในหน่วยความจำจนกว่าส่วนประกอบกระบวนการจะปล่อยทรัพยากรโดยเฉพาะ ด้วยเหตุผลนี้ทุกครั้งที่คุณเรียกใช้เริ่มสำหรับอินสแตนซ์กระบวนการให้เรียกปิดเมื่อกระบวนการที่เกี่ยวข้องได้สิ้นสุดลงและคุณไม่ต้องการข้อมูลการดูแลระบบอีกต่อไป ปิดทำให้หน่วยความจำที่จัดสรรให้กับกระบวนการที่ออกให้เป็นอิสระ
ฉันลองวิธีแก้ปัญหาของ 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 );
มันใช้งานได้ดี
openApplication.HasExited()
HasExited ไม่ใช่ฟังก์ชัน วิธีที่ถูกต้องก็openApplication.HasExited
คือ
แม้จะรองรับ API จาก. Net framework ที่เกี่ยวข้องกับการตรวจสอบกระบวนการที่มีอยู่โดย process ID แต่ฟังก์ชั่นเหล่านั้นช้ามาก มีค่าใช้จ่ายจำนวนมากรอบ CPU เพื่อเรียกใช้ Process.GetProcesses () หรือ Process.GetProcessById / Name ()
วิธีเร็วมากในการตรวจสอบกระบวนการทำงานโดยใช้ ID คือการใช้ API พื้นเมืองOpenProcess () ถ้า return handle เป็น 0 กระบวนการจะไม่มีอยู่ ถ้าหมายเลขอ้างอิงต่างจาก 0 แสดงว่ากระบวนการกำลังทำงาน ไม่มีการรับประกันวิธีนี้จะใช้งานได้ 100% ตลอดเวลาเนื่องจากได้รับอนุญาต
มีปัญหามากมายที่เกี่ยวข้องกับสิ่งนี้เนื่องจากปัญหาอื่น ๆ ได้กล่าวถึงบางส่วนแล้ว:
ไม่ว่าคุณสมบัติที่ผู้อื่นพูดถึงจะเป็นแบบภายในหรือไม่ก็ตามคุณยังสามารถรับข้อมูลจากพวกเขาผ่านการไตร่ตรองหากได้รับอนุญาต
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 ["?"]:
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
นอกจากนี้คุณสามารถใช้ตัวจับเวลาสำหรับตรวจสอบกระบวนการทุกครั้ง
length == 0
ควรแสดงNot Working
) แต่ก็ยังทำงานได้สำเร็จ