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

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

Так как же в C # сделать это в приведенном ниже примере?

using System.Diagnostics;

...

Process foo = new Process();

foo.StartInfo.FileName = @"C:\bar\foo.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 ]

31 голосов
/ 09 сентября 2008

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

Процессы проверки

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


22 голосов
/ 09 сентября 2008

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

var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));
6 голосов
/ 09 сентября 2008

Я использовал функцию 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);
        }
    }
}
4 голосов
/ 09 сентября 2008

Вы можете просто перечислить процессы, используя Process.GetProcesses метод.

2 голосов
/ 23 мая 2014

Я обнаружил, что Mutex не работает, как в консольном приложении. Поэтому использование 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;
}

ПРИМЕЧАНИЕ. Добавьте ссылку на сборку "System.Management", чтобы включить тип intellisense.

1 голос
/ 09 сентября 2008

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

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

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

1 голос
/ 09 сентября 2008

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

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

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

1 голос
/ 09 сентября 2008

Я думаю, что полный ответ на вашу проблему требует понимания того, что происходит, когда ваше приложение определяет, что экземпляр foo.exe уже запущен, т.е. что на самом деле означает «// TODO: Перейти к процессу foo.exe»? *

0 голосов
/ 09 сентября 2008

Mnebuerquo писал:

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

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

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

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