Как узнать, работает ли процесс уже с помощью c#?

У меня есть приложение c# winforms, которое время от времени должно запускать внешний exe, но я не хочу запускать другой процесс, если он уже запущен, а скорее переключиться на него.

Так как в C# я бы так это в примере ниже?

using System.Diagnostics;

...

Process foo = new Process();

foo.StartInfo.FileName = @"C:barfoo.exe";
foo.StartInfo.Arguments = "Username Password";

bool isRunning = //TODO: Check to see if process foo.exe is already running


if (isRunning)
{
   //TODO: Switch to foo.exe process
}
else
{
   foo.Start(); 
}

9 ответов


Это должно сделать это для тебя.

Проверка Процессов

//Namespaces we need to use
using System.Diagnostics;

public bool IsProcessOpen(string name)
{
    //here we're going to get a list of all running processes on
    //the computer
    foreach (Process clsProcess in Process.GetProcesses()) {
        //now we're going to see if any of the running processes
        //match the currently running processes. Be sure to not
        //add the .exe to the name you provide, i.e: NOTEPAD,
        //not NOTEPAD.EXE or false is always returned even if
        //notepad is running.
        //Remember, if you have the process running more than once, 
        //say IE open 4 times the loop thr way it is now will close all 4,
        //if you want it to just close the first one it finds
        //then add a return; after the Kill
        if (clsProcess.ProcessName.Contains(name))
        {
            //if the process is found to be running then we
            //return a true
            return true;
        }
    }
    //otherwise we return a false
    return false;
}



вы также можете использовать LINQ,

var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));

я использовал функцию AppActivate в среде выполнения VB для активации существующего процесса. Вам придется импортировать Microsoft.VisualBasic dll в проект C#.

using System;
using System.Diagnostics;
using Microsoft.VisualBasic;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] proc = Process.GetProcessesByName("notepad");
            Interaction.AppActivate(proc[0].MainWindowTitle);
        }
    }
}

вы можете просто перечислить процессы, используя


Я обнаружил, что мьютекс не работает, как в консольном приложении. Таким образом, использование WMI для запроса процессов, которые можно увидеть в окне Диспетчера задач, решит вашу проблему.

использовать что-то вроде этого:

static bool isStillRunning() {
   string processName = Process.GetCurrentProcess().MainModule.ModuleName;
   ManagementObjectSearcher mos = new ManagementObjectSearcher();
   mos.Query.QueryString = @"SELECT * FROM Win32_Process WHERE Name = '" + processName + @"'";
   if (mos.Get().Count > 1)
   {
        return true;
    }
    else
        return false;
}

Примечание: добавить ссылку на сборку системы".Управление", чтобы включить тип intellisense.


Я думаю, что полный ответ на вашу проблему требует понимания того, что происходит, когда ваше приложение определяет, что экземпляр foo.exe уже работает i.e что делает ' / / TODO: переключиться на foo.exe процесс " на самом деле означает?


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

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

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


две проблемы, чтобы иметь в виду:

  1. ваш пример связан с размещением пароль в командной строке. Что текстовое представление секрета может быть уязвимость.

  2. при перечислении процессов, задать себя, который обрабатывает вас на самом деле хотите перечислить. Все пользователи, или только текущий пользователь? Что если текущий пользователь вошел в систему дважды (два настольные компьютеры)?


Mnebuerquo написал:

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

у меня нет доступа исходного кода к процессу, который я хочу запустить.

Я закончил использование proccess MainWindowHandle для переключения на процесс, как только я обнаружил, что он работает alread:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);