프로세스가 실행 중인지 어떻게 알 수 있습니까?


155

에 대한 참조를 얻을 때 System.Diagnostics.Process프로세스가 현재 실행 중인지 어떻게 알 수 있습니까?

답변:


252

이것은 이름으로 수행하는 방법입니다.

Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
  MessageBox.Show("nothing");
else
  MessageBox.Show("run");

나중에 조작 할 수 있도록 모든 프로세스를 반복하여 ID를 얻을 수 있습니다.

Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
   Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}

이것은 내가 찾던 것입니다. 이것은 매우 오래된 게시물이지만 이것이 어떻게 유효한 C #인지 설명해 주시겠습니까? 나는 그것을 의심하지 않고, 그것이 효과가있는 것을 보았지만, {}가 없다면 다른 것을 본 적이 없다.
MatthewD

4
@MatthewD : if/else한 줄의 길이 인 C # 문은 블록 문을 나타 내기 위해 중괄호를 사용할 필요가 없습니다. 이것은 또한 진술 foreach하고 진행 for합니다. 코딩 스타일로 귀결됩니다.
Hallmanac

나도 이것에 대한 조사를했는데 그 정보를 찾았지만 정보를 보지 못했습니다 for. c # .net dev 년 동안 나는이 스타일을 본 적이 없다. 그들이 말하는 것처럼 "매일 새로운 것을 배우십시오". 게시물과 답장을 보내 주셔서 감사합니다 ..
MatthewD

3
@MatthewD 예, 이것은 실제로 Java와 같은 대부분의 언어에 적용됩니다. 일반적으로 이와 같은 단일 라이너를 피하고 항상 중괄호를 사용하는 것이 좋습니다. 언제나 나중에 더 많은 문을 추가해야 할 가능성이 있기 때문에 필요한 경우 이미 중괄호가있을 것입니다. 그러나 이와 같은 일에 대해 100 % 확신하는 경우 하나의 진술 만 필요하면 구문 적으로 유효합니다.
David Mordigal

1
프로세스를 찾을 수 없으면 확장 프로그램을 제거하십시오. (예 : .exe)
DxTx

28

이것이 리플렉터를 사용한 후 찾은 가장 간단한 방법입니다. 이를 위해 확장 방법을 만들었습니다.

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수업은 내부에 있습니다 ...


이것은 정말 좋은 대답이었습니다. 그러나 null 예외 인수를 사용하면 안됩니다 (null 참조 예외가 발생하여 예외로 아무것도하지 않았기 때문에 Start ()를 호출하지 않으면 InvalidOperationException이 발생합니다) 메소드 또는 귀하가 close () 메소드를 호출했습니다.이 두 가지 상황을 설명하기 위해 다른 답변을 게시했습니다.
Aelphaeis

16

동기식 솔루션 :

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

6
첫 번째 옵션 : 프로세스가 처음 시작되었는지 어떻게 알 수 있습니까?
reshefm

8

reshefm은 꽤 좋은 대답을했습니다. 그러나 프로세스가 시작되지 않은 상황을 설명하지는 않습니다.

다음은 그가 게시 한 내용의 수정 된 버전입니다.

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

그의 ArgumentNullException은 실제로 null 참조 예외라고 가정하고 어쨌든 시스템에 의해 발생하기 때문에 프로세스가 시작되지 않았거나 close () 메소드를 사용하여 방법.


개인적으로, NullReferenceException보다 기록 된 예외를 검토 할 때 ArgumentNullException을 보는 것이 좋습니다. ArgumentNullException은 무엇이 잘못되었는지에 대해 훨씬 더 명확하기 때문입니다.
Sean

1
@Sean 나는 보통 당신에게 동의하지만 이것은 확장 방법입니다. 구문에 따라 null 포인터 예외를 throw하는 것이 더 적절하다고 생각합니다 .null 객체의 메서드를 호출하는 것과 더 일관성이 있다고 생각합니다.
Aelphaeis

이렇게하면 매번 FirstHandledException 이벤트 처리기가 트리거됩니다. 친구에게 로그를 스팸으로 보내는 방법.
대기 시간

6

이것은 하나의 라이너이어야합니다.

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

3

이 기능의 신뢰성에 달려 있습니다. 보유한 특정 프로세스 인스턴스가 여전히 실행 중이고 100 % 정확도로 사용 가능한지 알고 싶다면 운이 좋지 않습니다. 관리되는 프로세스 개체에는 프로세스를 식별하는 방법이 2 가지 밖에 없기 때문입니다.

첫 번째는 프로세스 ID입니다. 불행히도 프로세스 ID는 고유하지 않으며 재활용 할 수 있습니다. 일치하는 ID에 대한 프로세스 목록을 검색하면 동일한 ID를 가진 프로세스가 실행 중임을 나타내지 만 반드시 프로세스는 아닙니다.

두 번째 항목은 프로세스 핸들입니다. Id와 같은 문제가 있지만 작업하기가 더 어색합니다.

중간 수준의 안정성을 찾고 있다면 동일한 ID의 프로세스에 대한 현재 프로세스 목록을 확인하는 것으로 충분합니다.


1

Process.GetProcesses()갈 길입니다. 그러나 프로세스 실행 방법 (예 : 제목 표시 줄의 유무에 관계없이 서비스 또는 일반 앱)에 따라 프로세스를 찾기 위해 하나 이상의 다른 기준을 사용해야 할 수도 있습니다.


이 방법을 루프에 넣으면 많은 CPU주기가 필요합니다. GetProcessByName () 또는 GetProcessByID ()를 사용하는 것이 좋습니다.
Hao Nguyen

0

어쩌면 (아마도) 질문을 잘못 읽고 있지만 Process 객체가 나타내는 프로세스가 정상적으로 종료되었는지를 나타내는 HasExited 속성을 찾고 있습니까?

참조하는 프로세스에 UI가있는 경우 응답 특성을 사용하여 UI가 현재 사용자 입력에 응답하는지 여부를 판별 할 수 있습니다.

EnableRaisingEvents를 설정하고 Exited 이벤트 (비동기 적으로 전송 됨)를 처리하거나 차단하려는 경우 WaitForExit ()를 호출 할 수도 있습니다.


0

원하는 프로세스에 대해 프로세스 인스턴스를 한 번 인스턴스화하고 해당 .NET 프로세스 오브젝트를 사용하여 프로세스를 계속 추적 할 수 있습니다 (추적중인 프로세스가 종료 된 경우에도 명시 적으로 해당 .NET 오브젝트에서 닫기를 호출 할 때까지 추적을 계속합니다) [이것은 프로세스 종료 시간, 일명 종료 시간 등을 제공 할 수 있도록하기위한 것입니다.])

인용 http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :

연관된 프로세스가 종료되면 (즉, 정상 또는 비정상 종료를 통해 운영 체제에 의해 종료 될 때) 시스템은 프로세스에 대한 관리 정보를 저장하고 WaitForExit를 호출 한 구성 요소로 리턴합니다. 그런 다음 프로세스 컴포넌트는 종료 된 프로세스에 대한 핸들을 사용하여 ExitTime을 포함한 정보에 액세스 할 수 있습니다.

연관된 프로세스가 종료되었으므로 구성 요소의 Handle 특성이 더 이상 기존 프로세스 자원을 가리 키지 않습니다. 대신 핸들은 프로세스 자원에 대한 운영 체제 정보에 액세스하는 데만 사용할 수 있습니다. 시스템은 프로세스 구성 요소가 해제하지 않은 종료 된 프로세스에 대한 핸들을 인식하므로 프로세스 구성 요소가 자원을 구체적으로 해제 할 때까지 ExitTime 및 핸들 정보를 메모리에 유지합니다. 이러한 이유로 프로세스 인스턴스에 대해 Start를 호출 할 때마다 연관된 프로세스가 종료되고 더 이상 관리 정보가 필요하지 않으면 Close를 호출하십시오. Close는 종료 된 프로세스에 할당 된 메모리를 해제합니다.


0

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

그것은 (지금까지) 작동합니다


3
에서 openApplication.HasExited()HasExited는 함수가 아닙니다. 올바른 방법은입니다 openApplication.HasExited.
caiosm1005

0

프로세스 ID로 기존 프로세스를 확인하는 것과 관련하여 .Net 프레임 워크에서 지원되는 API에도 불구하고 이러한 기능은 매우 느립니다. Process.GetProcesses () 또는 Process.GetProcessById / Name ()을 실행하는 데 많은 CPU주기가 필요합니다.

ID로 실행중인 프로세스를 확인하는 훨씬 빠른 방법은 기본 API OpenProcess ()를 사용하는 것 입니다. 리턴 핸들이 0이면 프로세스가 존재하지 않습니다. 핸들이 0과 다른 경우 프로세스가 실행 중입니다. 허가로 인해이 방법이 항상 100 % 작동한다는 보장은 없습니다.


0

다른 것들이 부분적으로 다루는 것처럼, 이것과 관련된 많은 문제가 있습니다 :

  • 모든 인스턴스 멤버는 스레드 안전을 보장하지 않습니다. 즉, 객체의 속성을 평가하는 동안 스냅 샷 수명과 함께 발생할 수있는 경쟁 조건이 있습니다.
  • 프로세스 핸들은 ACCESS DENIED에 대해 Win32Exception을 발생 시키며이 속성 및 다른 속성을 평가하는 권한이 허용되지 않습니다.
  • IS N'T RUNNING 상태의 경우 일부 속성을 평가하려고 할 때 ArgumentException도 발생합니다.

다른 사람이 언급 한 속성이 내부에 있는지 여부에 관계없이 권한이 허용하는 경우 리플렉션을 통해 정보를 얻을 수 있습니다.

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

Snapshot에 대해 Win32 코드를 고정 하거나 속도가 느린 WMI 를 사용할 수 있습니다 .

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

또 다른 옵션은 OpenProcess입니다. / CloseProcess이지만, 이전과 동일하게 예외가 발생하는 것과 동일한 문제가 계속 발생합니다.

WMI-OnNewEvent.Properties [ "?"]의 경우 :

  • "ParentProcessID"
  • "프로세스 ID"
  • "프로세스 이름"
  • "SECURITY_DESCRIPTOR"
  • "세션 ID"
  • "시드"
  • "TIME_CREATED"

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

또한 매번 프로세스를 확인하기 위해 타이머를 사용할 수 있습니다


3
다른 방법이 아닐까요? 길이 == 0이면 작동하지 않는 것입니까?
Jay Jacobs

대답은 Patrick Desjardins와 동일합니다. stackoverflow.com/a/262291/7713750
Rekshino

길이가 0보다 길면 프로세스가 발견됩니다.
HaseeB Mir

오류가있을 수 있지만 ( length == 0표시되어야 함 Not Working) 여전히 작업을 수행합니다.
Momoro
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.