Khi tôi nhận được một tham chiếu đến a System.Diagnostics.Process
, làm thế nào tôi có thể biết nếu một quy trình hiện đang chạy?
Khi tôi nhận được một tham chiếu đến a System.Diagnostics.Process
, làm thế nào tôi có thể biết nếu một quy trình hiện đang chạy?
Câu trả lời:
Đây là một cách để làm điều đó với tên:
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
Bạn có thể lặp tất cả quá trình để lấy ID cho thao tác sau:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
if/else
câu lệnh C # chỉ dài một dòng không cần phải có dấu ngoặc nhọn để biểu thị câu lệnh khối. Điều này cũng đi foreach
và for
tuyên bố. Nó sôi sục theo phong cách mã hóa.
for
thông tin đó. Nhiều năm c # .net dev và tôi chưa bao giờ thấy phong cách này. Giống như họ nói, "bạn học được điều gì đó mới mỗi ngày". Cảm ơn bạn đã gửi bài và trả lời ..
Đây là cách đơn giản nhất mà tôi tìm thấy sau khi sử dụng gương phản xạ. Tôi đã tạo một phương thức mở rộng cho điều đó:
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;
}
}
Các Process.GetProcessById(processId)
phương pháp gọi là ProcessManager.IsProcessRunning(processId)
phương pháp và ném ArgumentException
trong trường hợp quá trình này không tồn tại. Vì một số lý do, ProcessManager
lớp học là nội bộ ...
Giải pháp đồng bộ:
void DisplayProcessStatus(Process process)
{
process.Refresh(); // Important
if(process.HasExited)
{
Console.WriteLine("Exited.");
}
else
{
Console.WriteLine("Running.");
}
}
Giải pháp không đồng bộ:
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 đã có một câu trả lời khá hay; tuy nhiên, nó không giải thích cho một tình huống trong đó quá trình không bao giờ bắt đầu.
Đây là một phiên bản sửa đổi của những gì ông đã đăng.
public static bool IsRunning(this Process process)
{
try {Process.GetProcessById(process.Id);}
catch (InvalidOperationException) { return false; }
catch (ArgumentException){return false;}
return true;
}
Tôi đã xóa ArgumentNullException của anh ấy vì nó thực sự là một ngoại lệ tham chiếu null và dù sao nó cũng bị hệ thống ném và tôi cũng tính đến tình huống trong đó quy trình không bao giờ bắt đầu bằng hoặc phương thức close () được sử dụng để đóng quá trình.
Nó phụ thuộc vào mức độ tin cậy của bạn muốn chức năng này. Nếu bạn muốn biết nếu ví dụ quy trình cụ thể mà bạn có vẫn đang chạy và có sẵn với độ chính xác 100% thì bạn đã hết may mắn. Lý do là từ đối tượng quy trình được quản lý chỉ có 2 cách để xác định quy trình.
Đầu tiên là Id quá trình. Thật không may, id quá trình không phải là duy nhất và có thể được tái chế. Tìm kiếm danh sách quy trình cho Id phù hợp sẽ chỉ cho bạn biết rằng có một quy trình có cùng id đang chạy, nhưng đó không nhất thiết là quy trình của bạn.
Mục thứ hai là Xử lý quy trình. Nó có cùng một vấn đề với Id và thật khó xử lý hơn.
Nếu bạn đang tìm kiếm độ tin cậy ở mức trung bình thì việc kiểm tra danh sách quy trình hiện tại cho một quy trình có cùng ID là đủ.
Process.GetProcesses()
là con đường để đi Nhưng bạn có thể cần sử dụng một hoặc nhiều tiêu chí khác nhau để tìm quy trình của mình, tùy thuộc vào cách nó đang chạy (ví dụ như một dịch vụ hoặc ứng dụng thông thường, cho dù nó có thanh tiêu đề hay không).
Có thể (có lẽ) Tôi đang đọc câu hỏi sai, nhưng bạn đang tìm thuộc tính HasExited sẽ cho bạn biết rằng quy trình được đại diện bởi đối tượng Process của bạn đã thoát (bình thường hoặc không).
Nếu quy trình bạn có tham chiếu để có UI, bạn có thể sử dụng thuộc tính Phản hồi để xác định xem UI hiện có phản hồi với đầu vào của người dùng hay không.
Bạn cũng có thể đặt EnableRaisingEvents và xử lý sự kiện Đã thoát (được gửi không đồng bộ) hoặc gọi WaitForExit () nếu bạn muốn chặn.
Bạn có thể khởi tạo một cá thể Process một lần cho quy trình bạn muốn và tiếp tục theo dõi quá trình bằng cách sử dụng đối tượng .NET Process đó (nó sẽ tiếp tục theo dõi cho đến khi bạn gọi Close trên đối tượng .NET đó, ngay cả khi quá trình mà nó đang theo dõi đã chết [điều này là để có thể cung cấp cho bạn thời gian xử lý gần, còn gọi là ExitTime, v.v.))
Trích dẫn http://msdn.microsoft.com/en-us/l Library / fb4aw7b8.aspx :
Khi một quy trình liên quan thoát ra (nghĩa là khi hệ thống vận hành ngừng hoạt động thông qua chấm dứt bình thường hoặc bất thường), hệ thống sẽ lưu trữ thông tin quản trị về quy trình và trở về thành phần có tên WaitForExit. Thành phần Process sau đó có thể truy cập thông tin, bao gồm ExitTime, bằng cách sử dụng Xử lý cho quy trình đã thoát.
Vì quy trình liên quan đã thoát, thuộc tính Xử lý của thành phần không còn trỏ đến tài nguyên quy trình hiện có. Thay vào đó, tay cầm chỉ có thể được sử dụng để truy cập thông tin của hệ điều hành về tài nguyên quy trình. Hệ thống nhận thức được việc xử lý các tiến trình đã thoát mà các thành phần Process chưa phát hành, do đó, nó giữ thông tin ExitTime và Xử lý trong bộ nhớ cho đến khi thành phần Process giải phóng cụ thể các tài nguyên. Vì lý do này, bất cứ khi nào bạn gọi Bắt đầu cho một cá thể Quy trình, hãy gọi Đóng khi quá trình liên quan đã chấm dứt và bạn không còn cần bất kỳ thông tin quản trị nào về nó. Đóng giải phóng bộ nhớ được phân bổ cho quá trình thoát.
Tôi đã thử giải pháp của Coincoin:
Trước khi xử lý một số tệp, tôi sao chép nó dưới dạng tệp tạm thời và mở tệp.
Khi tôi hoàn tất, tôi đóng ứng dụng nếu nó vẫn mở và xóa tệp tạm thời:
Tôi chỉ sử dụng biến Quy trình và kiểm tra sau đó:
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 );
}
Sau đó tôi đóng ứng dụng:
...
openApplication.Refresh();
// close application if it is still open
if ( !openApplication.HasExited() ) {
openApplication.Kill();
}
// delete temporary file
System.IO.File.Delete( fileCache );
Nó hoạt động (cho đến nay)
openApplication.HasExited()
, HasExited không phải là một chức năng. Cách chính xác sẽ là openApplication.HasExited
.
Mặc dù API được hỗ trợ từ các khung .Net liên quan đến việc kiểm tra quy trình hiện tại bằng ID tiến trình, các chức năng đó rất chậm. Nó tốn một số lượng lớn chu kỳ CPU để chạy Process.GetProcesses () hoặc Process.GetProcessById / Name ().
Một phương pháp nhanh hơn nhiều để kiểm tra một quy trình đang chạy bằng ID là sử dụng API OpenProcess () gốc . Nếu xử lý trả về là 0, quá trình không tồn tại. Nếu xử lý khác 0, quá trình đang chạy. Không có gì đảm bảo phương pháp này sẽ hoạt động 100% mọi lúc do sự cho phép.
Có nhiều vấn đề liên quan đến vấn đề này, vì những vấn đề khác dường như đã giải quyết một phần:
Cho dù các thuộc tính mà người khác đã đề cập có phải là nội bộ hay không, bạn vẫn có thể lấy thông tin từ chúng thông qua phản ánh nếu được phép.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
Bạn có thể xác định mã Win32 cho Ảnh chụp nhanh hoặc bạn có thể sử dụng WMI chậm hơn.
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
Một tùy chọn khác sẽ là OpenProcess / CloseProcess, nhưng bạn vẫn sẽ gặp phải các vấn đề tương tự với các ngoại lệ được đưa ra như trước đây.
Đối với WMI - OnNewEvent.ProperIES ["?"]:
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
ngoài ra bạn có thể sử dụng một bộ đếm thời gian để kiểm tra quá trình mỗi lần
length == 0
nên hiển thị Not Working
) nhưng vẫn hoàn thành công việc.