Как узнать, работает ли процесс?

Когда я получаю ссылку на System.Diagnostics.Process, как я могу узнать, запущен ли процесс в настоящее время?

Ответ 1

Это способ сделать это с именем:

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);
}

Ответ 2

Это самый простой способ, который я нашел после использования рефлектора. Я создал для этого метод расширения:

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 является внутренним...

Ответ 3

Синхронное решение:

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.");
}

Ответ 4

у reshefm был довольно хороший ответ; однако он не учитывает ситуацию, в которой процесс никогда не начинался.

Вот измененная версия того, что он опубликовал.

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

Я удалил его аргумент ArgumentNullException, потому что на самом деле он предположил, что он является исключительным исключением, и все равно его выбрасывает система, и я также объяснял ситуацию, когда процесс не начинался, или использовался метод close() для закрытия процесса.

Ответ 5

Это должен быть однострочный:

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

Ответ 6

Это зависит от того, насколько надежна эта функция. Если вы хотите узнать, все ли у вас есть конкретный экземпляр процесса, он доступен и доступен со 100% -ной точностью, тогда вам не повезло. Причина в том, что из объекта управляемого процесса существует всего 2 способа идентифицировать процесс.

Первый - это идентификатор процесса. К сожалению, идентификаторы процессов не уникальны и могут быть переработаны. Поиск списка процессов для соответствующего идентификатора покажет вам, что есть процесс с тем же запущенным идентификатором, но это не обязательно ваш процесс.

Второй элемент - это Process Handle. У этой проблемы есть такая же проблема, как и идентификатор, и работать с ней более неудобно.

Если вы ищете надежность среднего уровня, то проверка текущего списка процессов для одного и того же идентификатора достаточно.

Ответ 7

Process.GetProcesses() - путь. Но вам может понадобиться использовать один или несколько разных критериев для поиска вашего процесса, в зависимости от того, как он работает (например, как сервис или обычное приложение, независимо от того, имеет ли он заголовок).

Ответ 8

Возможно (возможно) Я читаю вопрос неправильно, но вы ищете свойство HasExited, которое сообщит вам, что процесс, представленный вашим объектом Process, вышел из него (обычно или нет).

Если у процесса, к которому у вас есть ссылка, есть пользовательский интерфейс, вы можете использовать свойство Responding, чтобы определить, отвечает ли пользовательский интерфейс на ввод пользователя или нет.

Вы также можете установить EnableRaisingEvents и обработать событие Exited (которое отправляется асинхронно) или вызвать WaitForExit(), если вы хотите заблокировать.

Ответ 9

Вы можете создать экземпляр процесса один раз для процесса, который вы хотите, и продолжать отслеживать процесс с использованием этого объекта .NET Process (он будет продолжать отслеживать, пока вы не вызовете Close на этом объекте .NET явно, даже если процесс был отслеживание скончалось [это возможность дать вам время закрытия процесса, aka ExitTime и т.д.))

Цитата http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx:

Когда связанный процесс завершается (то есть, когда он закрывается операционной системы через нормальное или ненормальное завершение), система хранит административную информацию о процессе и возвращает который вызвал WaitForExit. Затем компонент Process может доступ к информации, которая включает в себя ExitTime, с помощью Обращение к завершенному процессу.

Поскольку связанный процесс завершен, свойство Handle компонент больше не указывает на существующий ресурс процесса. Вместо, дескриптор может использоваться только для доступа к операционным системам информацию о ресурсе процесса. Система знает о ручках для выхода процессов, которые не были выпущены компонентами Process, поэтому он сохраняет информацию ExitTime и Handle в памяти до тех пор, пока Технологический компонент специально освобождает ресурсы. По этой причине, в любое время, когда вы вызываете Start для экземпляра Process, вызовите Close, когда связанный процесс прекратился, и вам больше не нужно административную информацию об этом. Закрыть освобождает выделенную память к завершенному процессу.

Ответ 10

Я попробовал решение 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 );

Он работает (пока)

Ответ 11

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

также вы можете использовать таймер для проверки процесса каждый раз

Ответ 12

Несмотря на поддерживаемый API из .Net-систем, связанных с проверкой существующего процесса по идентификатору процесса, эти функции выполняются очень медленно. Для запуска Process.GetProcesses() или Process.GetProcessById/Name() требуется огромное количество циклов процессора.

Более быстрый способ проверить запущенный процесс по ID - использовать собственный API OpenProcess(). Если дескриптор возврата равен 0, процесс не существует. Если дескриптор отличается от 0, процесс выполняется. Там нет гарантии, что этот метод будет работать 100% в любое время из-за разрешения.

Ответ 13

Есть много проблем, связанных с этим, поскольку другие, кажется, частично решают:

  • Любые члены экземпляра не гарантированно являются потокобезопасными. Это означает, что существуют условия гонки, которые могут возникать в течение срока действия снимка при попытке оценить свойства объекта.
  • Дескриптор процесса выбрасывает Win32Exception для ACCESS DENIED, где разрешения для оценки этого и других подобных свойств не разрешены.
  • Для статуса ISN'T RUNNING, ArgumentException также будет вызываться при попытке оценить некоторые из его свойств.

Независимо от того, какие свойства были упомянуты другими, являются внутренними или нет, вы все равно можете получить информацию от них, если разрешите.

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

Вы можете закрепить код Win32 для Snapshot или использовать WMI, который работает медленнее.

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

Другим вариантом может быть OpenProcess/CloseProcess, но вы все равно столкнетесь с теми же проблемами, за исключением тех же исключений, что и раньше.

Для WMI - OnNewEvent.Properties ["?"]:

  • "ParentProcessID"
  • "ProcessID"
  • "Имя процесса"
  • "SECURITY_DESCRIPTOR"
  • "Идентификатор сессии"
  • "Sid"
  • "Time_created"