Відповіді:
Це спосіб зробити це з назвою:
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
Ви можете зафіксувати весь процес, щоб отримати ідентифікатор для наступних маніпуляцій:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
if/else
заяви, які мають довжину лише один рядок, не повинні мати фігурні дужки для позначення оператора блоку. Це стосується 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, тому що він насправді повинен бути виключенням з нульовим посиланням, і його все одно викидає система, і я також пояснив ситуацію, в якій процес ніколи не починався, або метод закриття () використовувався для закриття процес.
Це залежить від того, наскільки надійною ви бажаєте бути такою функцією. Якщо ви хочете дізнатися, чи наявний у вас певний примірник процесу все ще працює і доступний із 100% точністю, то вам не пощастить. Причина полягає в тому, що від об'єкта керованого процесу існує лише два способи ідентифікації процесу.
Перший - це ідентифікатор процесу. На жаль, ідентифікатори технологічних процесів не є унікальними і можуть бути перероблені. Пошук у списку процесів для відповідного ідентифікатора лише скаже вам, що існує процес з тим же ідентифікатором, який працює, але це не обов'язково ваш процес.
Другий пункт - Ручка процесу. Він має таку ж проблему, що і Id, і з цим незручніше працювати.
Якщо ви шукаєте надійність середнього рівня, то достатньо перевірити поточний список процесів для процесу того ж ідентифікатора.
Process.GetProcesses()
це шлях. Але вам може знадобитися використовувати один або декілька різних критеріїв, щоб знайти свій процес, залежно від того, як він працює (наприклад, як служба чи звичайний додаток, незалежно від того, має він чи ні).
Можливо (напевно) я неправильно читаю питання, але ви шукаєте властивість HasExited, яка скаже вам, що процес, представлений вашим об'єктом Process, вийшов (нормально чи ні).
Якщо процес, на який ви посилаєтесь, має інтерфейс користувача, ви можете скористатися властивістю Responding, щоб визначити, чи відповідає інтерфейс користувача на введення користувача чи ні.
Ви також можете встановити EnableRaisingEvents та обробити подію Exited (яке надсилається асинхронно) або зателефонувати WaitForExit (), якщо ви хочете заблокувати.
Ви можете інстанціювати екземпляр Process один раз для потрібного процесу та продовжувати відстежувати процес за допомогою цього об’єкта .NET Process (він буде тримати відстеження, поки ви не викликаєте явно Закрити цей об’єкт .NET, навіть якщо процес, який він відстежував, загинув. [це для того, щоб дати вам час завершення процесу, він же ExitTime тощо])
Цитуючи http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
Коли пов'язаний процес закінчується (тобто коли він закривається операційною системою через нормальне або аномальне припинення), система зберігає адміністративну інформацію про процес і повертається до компонента, який назвав WaitForExit. Потім компонент Process може отримати доступ до інформації, яка включає в себе ExitTime, використовуючи ручку до завершеного процесу.
Оскільки пов'язаний процес закінчився, властивість Handle компонента більше не вказує на існуючий ресурс процесу. Натомість ручку можна використовувати лише для доступу до інформації операційної системи про ресурс процесу. Система обізнана з ручками для завершених процесів, які не були випущені компонентами Process, тому вона зберігає інформацію про ExitTime і Handle в пам'яті, поки компонент Process спеціально не звільнить ресурси. З цієї причини, кожного разу, коли ви зателефонуєте запустити екземпляр процесу, зателефонуйте Закрити, коли пов'язаний процес припиниться, і вам більше не потрібна адміністративна інформація про нього. Закриття звільняє пам'ять, що виділяється на процес, що вийшов.
Я спробував рішення 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 фреймворків щодо перевірки існуючого процесу за ідентифікатором процесу, ці функції дуже повільні. Для запуску Process.GetProcess () або Process.GetProcessById / Name () коштує величезна кількість циклів процесора.
Набагато швидший спосіб перевірити запущений процес за ідентифікатором - це використання нативної API OpenProcess () . Якщо ручка повернення дорівнює 0, процес не існує. Якщо обробка відрізняється від 0, процес запущений. Немає гарантій, що цей метод працюватиме на 100% у будь-який час завдяки дозволу.
З цим пов'язано багато проблем, оскільки, здається, інші частково вирішують:
Незалежно від того, чи є властивості, про які згадували інші, внутрішні чи ні, ви все одно можете отримати інформацію від них за допомогою відображення, якщо дозволяє дозвіл.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
Ви можете підключити код Win32 для знімка або використовувати 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
), але все-таки виконується робота.