Ответы:
Это способ сделать это с именем:
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
операторы C # длиной всего одну строку не обязательно должны иметь фигурные скобки для обозначения оператора блока. Это касается 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, потому что он фактически подразумевает исключение нулевой ссылки, и оно все равно вызывается системой, и я также учел ситуацию, в которой процесс никогда не начинался, или метод close () использовался для закрытия обработать.
Это зависит от того, насколько надежной вы хотите, чтобы эта функция была. Если вы хотите узнать, работает ли конкретный экземпляр процесса и доступен ли он со 100% точностью, вам не повезло. Причина в том, что из объекта управляемого процесса есть только 2 способа идентифицировать процесс.
Первый - это идентификатор процесса. К сожалению, идентификаторы процессов не являются уникальными и могут быть переработаны. Поиск в списке процессов для соответствующего идентификатора только скажет вам, что существует процесс с таким же идентификатором, но это не обязательно ваш процесс.
Второй элемент - это дескриптор процесса. У него та же проблема, что и у идентификатора, и работать с ним более неудобно.
Если вам нужна надежность среднего уровня, то достаточно проверить текущий список процессов для процесса с тем же идентификатором.
Process.GetProcesses()
это путь Но вам может потребоваться использовать один или несколько различных критериев для поиска вашего процесса, в зависимости от того, как он выполняется (например, в качестве службы или обычного приложения, независимо от того, есть ли у него заголовок).
Возможно (возможно) я читаю вопрос неправильно, но вы ищете свойство HasExited, которое сообщит вам, что процесс, представленный вашим объектом Process, завершился (нормально или нет).
Если у процесса, на который у вас есть ссылка, есть пользовательский интерфейс, вы можете использовать свойство Responding, чтобы определить, отвечает ли пользовательский интерфейс в настоящее время на ввод пользователя или нет.
Вы также можете установить EnableRaisingEvents и обработать событие Exited (которое отправляется асинхронно) или вызвать WaitForExit (), если хотите заблокировать.
Вы можете создать экземпляр экземпляра Process один раз для нужного процесса и продолжать отслеживать процесс, используя этот объект .NET Process (он будет продолжать отслеживание, пока вы явно не вызовете Close для этого объекта .NET, даже если отслеживаемый процесс умер [это должно быть в состоянии дать вам время завершения процесса, иначе ExitTime и т. д.])
Цитирование http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
Когда связанный процесс завершается (то есть, когда он закрывается операционной системой из-за нормального или ненормального завершения), система сохраняет административную информацию о процессе и возвращается к компоненту, который вызвал WaitForExit. Компонент Process может затем получить доступ к информации, включая ExitTime, используя дескриптор завершенного процесса.
Поскольку связанный процесс завершен, свойство Handle компонента больше не указывает на существующий ресурс процесса. Вместо этого дескриптор можно использовать только для доступа к информации операционной системы о ресурсе процесса. Система знает о дескрипторах завершенных процессов, которые не были освобождены компонентами Process, поэтому она хранит информацию ExitTime и Handle в памяти до тех пор, пока компонент Process не освободит ресурсы. По этой причине каждый раз, когда вы вызываете Start для экземпляра Process, вызывайте Close, когда связанный процесс завершен, и вам больше не нужна никакая административная информация о нем. Close освобождает память, выделенную для завершенного процесса.
Я попробовал решение 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.GetProcesses () или Process.GetProcessById / Name () требуется огромное количество циклов ЦП.
Гораздо более быстрый способ проверки запущенного процесса по идентификатору - использовать нативный API OpenProcess () . Если возвращаемый дескриптор равен 0, процесс не существует. Если дескриптор отличается от 0, процесс выполняется. Нет никакой гарантии, что этот метод будет работать на все 100% из-за разрешения.
Есть много проблем, связанных с этим, поскольку другие, кажется, частично решают:
Независимо от того, какие свойства были упомянуты другими, являются внутренними или нет, вы все равно можете получить от них информацию путем размышления, если позволяет разрешение.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
Вы можете закрепить код Win32 для Snapshot или использовать 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
), но все еще выполняет свою работу.