Как я могу узнать, запущен ли процесс? - PullRequest
136 голосов
/ 04 ноября 2008

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

Ответы [ 13 ]

220 голосов
/ 04 ноября 2008

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

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);
}
24 голосов
/ 06 ноября 2008

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

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

16 голосов
/ 04 ноября 2008

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

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.");
}
8 голосов
/ 31 января 2014

у 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 () закрыть процесс.

6 голосов
/ 07 июля 2016

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

public static class ProcessHelpers {
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
3 голосов
/ 04 ноября 2008

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

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

Второй элемент - это дескриптор процесса. У него та же проблема, что и у идентификатора, и работать с ним более неудобно.

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

1 голос
/ 04 ноября 2008

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

0 голосов
/ 17 апреля 2019

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

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

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

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

Вы можете вводить код Win32 для Снимок или использовать WMI , что медленнее.

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

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

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

  • "ParentProcessID"
  • "ProcessID"
  • "ProcessName"
  • "SECURITY_DESCRIPTOR"
  • "SessionID"
  • "Sid"
  • "time_created"
0 голосов
/ 09 августа 2017

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

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

0 голосов
/ 12 июля 2013
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
    MessageBox.Show("Working");
}
else
{
    MessageBox.Show("Not Working");
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...