Tuesday, 6 February 2018

C # 프로세스 waitforexit hasexited


C # 프로세스 waitforexit hasexited
App Store를 통해 가져 오기 우리의 응용 프로그램 에서이 게시물을 읽으십시오!
Process. HasExited는 프로세스가 실행 중이더라도 true를 반환합니다.
나는 Process. HasExited가 프로세스가 여전히 실행 중일 때라도 true를 반환하는 것을 관찰 해왔다.
아래 코드는 "testprogram. exe"라는 이름의 프로세스를 시작한 다음 종료 될 때까지 기다립니다. 문제는 가끔 예외가 발생한다는 것입니다. HasExited가 true를 반환하더라도 프로세스 자체가 시스템에서 여전히 살아있는 것 같습니다. 어떻게 할 수 있습니까?
우리 프로그램은 종료되기 직전에 로그 파일에 기록을하기 때문에이 로그 파일이 읽히기 전에이 로그 파일 (일명 프로세스가 종료 / 완료 되었음)이 절대적으로 존재해야합니다. 계속 존재 여부를 확인하는 것은 선택 사항이 아닙니다.
업데이트 : 방금 process. WaitForExit () 폴링 루프 대신 기다리고 시도하고 그 결과는 똑같습니다.
추가 : 위의 코드는 '명확한'문제를 모두 보여주었습니다. 명확하게; 내 문제는 여전히 Process. GetProcessesByName ( "testprogram")에 의해 프로세스를 보류 할 수 없다는 것입니다. HasExited를 true로 설정 한 후
진짜 문제는 내가 외부에서 실행하고있는 프로그램이 파일을 작성한다는 것입니다. 바로 전에 (정상적으로) 종료됩니다. 나는 프로세스가 끝났을 때 HasExited를 사용하여 프로세스를 종료했기 때문에 파일을 읽을 수 있다는 것을 알았지 만, 프로그램이 아직 디스크에 파일을 쓰지 않은 경우에도 HasExited가 true를 반환하는 것처럼 보입니다. 다음은 정확한 문제를 보여주는 예제 코드입니다.
11 답변.
이 게시물은 오래되었다는 것을 알지만 내 앱에서 Exited 이벤트를 실행하기 전에 Exited 이벤트를 실행하는 이유를 알기 위해 앞으로도이 문제가 발생하는 사람들에게 유용 할 수도있는 뭔가를 발견했습니다.
프로세스가 시작되면 PID가 할당됩니다. 사용자에게 사용자 계정 컨트롤 대화 상자가 나타나면 '예'를 선택하면 프로세스가 다시 시작되고 새 PID가 할당됩니다.
나는 이것을 몇 시간 동안 앉아 있었다. 희망을 갖고 이것은 누군가 시간을 절약 할 수있다.
나는이 방법을 시도하도록 제안 할 것이다.
어쨌든. HasExited의 MSDN 페이지에서 다음과 같은 강조 표시를 읽습니다.
표준 출력이 비동기 이벤트 핸들러로 방향 재 지정되면이 등록 정보가 true를 리턴 할 때 출력 처리가 완료되지 않을 수도 있습니다. 비동기 이벤트 처리가 완료되었는지 확인하려면 HasExited를 확인하기 전에 매개 변수를 사용하지 않는 WaitForExit () 오버로드를 호출하십시오.
그것은 당신이 모든 것을 방향 전환 할 때 어떤 식 으로든 당신의 문제에 연결될 수 있습니다.
먼저, testprogram이 자체 프로세스를 생성하지 않고 해당 프로세스가 완료 될 때까지 기다리지 않고 종료해야합니까? 우리는 여기서 어떤 종류의 경쟁 조건을 다루고 있으며, 테스트 프로그램이 중요 할 수 있습니다.
두 번째 요점은 이것에 관한 것입니다. "이 로그 파일이 존재한다는 것을 절대적으로 확신해야합니다." 글쎄, 그런 건 없어. 확인을하면 파일이 사라집니다. 이 문제를 해결하는 일반적인 방법은 확인하는 것이 아니라 파일로 수행하려는 작업을 수행하는 것입니다. 계속 읽으십시오. 예외를 잡으십시오. 문제가 불안정하고 아무 것도 변경하지 않으려는 경우 다시 시도하십시오. 시스템에 둘 이상의 액터 (스레드 또는 기타)가있는 경우 제대로 작동하지 않습니다.
수많은 무작위적인 아이디어가 뒤 따른다.
프로세스 완료에 의존하지 않고 FileSystemWatcher를 사용해 보셨습니까?
파일을 읽으려고하면 (프로세스가 존재하는지 확인하지 않고 대신에 처리하는 것) process. Exited 이벤트에서 어떤 것이 더 나아지나요? [안된다]
시스템이 건강합니까? 이벤트 로그에서 의심스러운 부분이 있습니까?
정말 공격적인 바이러스 백신 정책이 관련 될 수 있습니까?
(모든 코드를 보지 않고 테스트 프로그램을 보지 않고도 많이 알 수는 없습니다.)
나도 알아, 이건 오래된 게시물이지만 나는 누군가를 도울 수 있습니다.
때때로 Process 클래스가 거짓말을합니다! 프로세스가 종료되었거나 프로세스가 관리자 권한으로 실행되고 프로그램에 사용자 권한 만있는 경우 HasExited는 true를 반환합니다.
문제의 근본 원인에 대한 추가 조사를 위해 프로세스 모니터를 사용하여 실제로 어떤 일이 일어나는지 확인해야합니다. 간단히 시작하고 외부 프로그램과 자신의 도구를 포함 시켜서 어떤 일이 일어나는지 기록하십시오.
로그에서 외부 도구가 출력 파일에 작성하는 방법과 해당 파일을 여는 방법을 확인해야합니다. 그러나이 로그에서 이러한 모든 액세스가 어떤 순서로 발생하는지 확인해야합니다.
내 마음에 가장 먼저 들려오는 것은 Process 클래스가 거짓말을하지 않으며 프로세스가 실제로 그렇게 말할 때 사라 졌다는 것입니다. 문제는이 시점에서 파일이 아직 완전하게 이용 가능하지 않은 것 같습니다. 나는 이것이 OS의 문제라고 생각한다. 왜냐하면 디스크에 완전히 기록되지 않은 캐시 내에서 파일의 일부분을 여전히 보유하고 있으며, 파일 핸들을 플러시하지 않고 단순히 종료했을 뿐이다.
이를 염두에두고 로그에서 외부 도구가 파일을 생성하고 파일을 플러시 / 닫을 때 (OS에서 로그 내에서이 지점을 찾으면 필터를 제거 할 수 있음) 볼 수 있습니다.
따라서 내 가정이 정확하다면 근본 원인은 바꿀 수없는 외부 도구의 불량한 행동입니다. 따라서 프로세스가 종료 된 후 잠시 기다려야하며 시간 초과가 파일을 비울만큼 길어지기를 바랍니다 / OS에 의해 닫혔습니다 (어쩌면 그것이 성공할 때까지 타임 아웃이있는 루프에서 파일을 열려고 시도합니다).
우선, 폴링하는 대신 Process. WaitForExit을 사용하는 데 문제가 있습니까?
어쨌든, 프로세스가 사용 가능한 관점에서 빠져 나가는 것이 기술적으로 가능할 수도 있지만, 프로세스는 여전히 디스크 캐쉬 캐시와 같은 작업을하는 동안 잠시 동안 진행됩니다. 로그 파일이 특히 커 (또는 디스크 쓰기에 많은 작업을 수행하는 작업)?
두 가지 가능성이 있습니다. 프로세스 개체는 프로세스에 대한 참조를 계속 보유하므로 종료되었지만 아직 삭제되지 않았습니다. 또는 두 번째 프로세스 실행 인스턴스가 있습니다. 프로세스 ID를 비교하여 확인해야합니다. 이 시도.
핸들이 프로세스에 열려 있으면 운영 체제는 프로세스가 종료 될 때 프로세스 메모리를 해제하지만 핸들, 종료 코드 및 종료 시간과 같은 프로세스에 대한 관리 정보를 보유합니다.
아마 관련이 없지만 주목할만한 가치가 있습니다.
1/10의 시간에만 문제가 발생하고 HasExited의 사용법에 따라 잠시 후에 프로세스가 사라지면 HasExited 검사가 작동 한 후에 다른 지연을 추가하십시오.
문제가 지속되는지 확인하십시오.
개인적으로, 나는 항상 모든 종류의 폴링 대신 Exited 이벤트 핸들러를 사용했고, Thread. Destroy. Process를 둘러싼 단순한 사용자 정의 래퍼를 사용하여 스레드 안전성, CloseMainWindow (), WaitForExit (timeout) 마지막으로 Kill (), logging 등등. 그리고 결코 문제가 발생하지 않았습니다.
어쩌면 문제가 테스트 프로그램에 있습니까? 이 코드는 멋지게 flush / close 등을 하는가? 그것은 내게 보인다면 testprogram 디스크에 파일을 씁니다, 파일을 적어도 사용할 수 있어야합니다 (비어 있거나하지 않음)

C # 프로세스 waitforexit hasexited
App Store를 통해 가져 오기 우리의 응용 프로그램 에서이 게시물을 읽으십시오!
C # : Process. HasExited는 프로세스가 종료 되더라도 false를 반환합니다.
나는 프로세스에서 Kill ()이라고 불렀고 종료 된 것으로 보인다. 그러나 HasExited를 테스트 할 때 나는 틀린 말을합니다.
그리고 이것은 무한정 계속됩니다. 물론, 이 코드를 변경하여 대기를 중지해야하지만, HasExited가 여전히 false를 반환하는 이유에 대해 궁금합니다. 프로세스가지도를 떨어 뜨린 것처럼 보일 때입니다.
표준 출력을 리디렉션합니까? MSDN은 다음과 같이 설명합니다.
표준 출력이 비동기 이벤트 핸들러로 방향 재 지정되면이 등록 정보가 true를 리턴 할 때 출력 처리가 완료되지 않을 수도 있습니다. 비동기 이벤트 처리가 완료되었는지 확인하려면 HasExited를 확인하기 전에 매개 변수를 사용하지 않는 WaitForExit () 오버로드를 호출하십시오.
어쨌든, 제안 된 해결 방법은 아마도 트릭을해야합니다 :

사용 예제.
나는이 방법으로 그것을 해결했다.
나는 입력, 출력 및 오류 모두를 리디렉션하고 출력 및 오류 스트림에서 읽기를 처리했습니다. 이 솔루션은 Windows 7과 Windows 8 모두 SDK 7 - 8.1에서 작동합니다.
Mark Beers, Rob, stevejay 대답을 고려하여 비동기 스트림 읽기를 사용하여 문제를 해결할 클래스를 만들려고했습니다. 그렇게하면 비동기 프로세스 출력 스트림 읽기와 관련된 버그가 있음을 알았습니다.
당신은 그렇게 할 수 없습니다 :
System. InvalidOperationException이 발생합니다 : StandardOut가 리디렉션되지 않았거나 프로세스가 아직 시작되지 않았습니다.
그런 다음 프로세스가 시작된 후 비동기 출력 읽기를 시작해야합니다.
이렇게하면 출력 스트림이 비동기로 설정되기 전에 데이터를받을 수 있기 때문에 경쟁 조건을 만듭니다.
그렇다면 어떤 사람들은 스트림을 비동기로 설정하기 전에 스트림을 읽어야한다고 말할 수 있습니다. 그러나 같은 문제가 발생합니다. 동기 읽기 사이에 경쟁 조건이 있으며 스트림을 비동기 모드로 설정합니다.
"Process"와 "ProcessStartInfo"가 설계된 실제 방식으로 프로세스의 출력 스트림을 안전하게 비동기 적으로 읽는 방법은 없습니다.
다른 사용자가 제안한 것과 같이 비동기 읽기를 사용하는 것이 좋습니다. 그러나 경쟁 조건으로 인해 정보가 누락 될 수 있음을 알고 있어야합니다.
위의 답변 중 하나도 해당 작업을 수행하지 않습니다.
롭 솔루션이 중단되고 'Mark Byers'솔루션이 폐기 된 예외를 얻습니다. (다른 답변의 '솔루션'을 시도했습니다.)
그래서 나는 또 다른 해결책을 제안하기로 결정했다.
이 코드는 디버깅되어 완벽하게 작동합니다.
이것이 간단하고 더 나은 접근 방법입니다 (우리는 AutoResetEvent가 필요 없습니다) :
나는 같은 문제가 있었지만 그 이유는 다르다. 그러나 Windows 8에서는 발생하지만 Windows 7에서는 발생하지 않습니다. 다음 줄이 문제를 일으킨 것으로 보입니다.
해결책은 UseShellExecute를 비활성화하지 않는 것입니다. 원하지 않는 쉘 팝업 창을 받았지만 특별한 일이 일어나지 않을 때까지 기다리는 프로그램보다 훨씬 낫습니다. 그래서 다음과 같은 해결 방법을 추가했습니다.
이제 나를 귀찮게하는 것은 Windows 8에서 왜 이런 일이 일어나고 있는지입니다.
소개.
현재 허용되는 응답이 작동하지 않고 (예외가 throw 됨) 해결 방법이 너무 많지만 완전한 코드가 없습니다. 이것이 대중적인 질문이기 때문에 많은 사람들의 시간을 낭비하는 것은 분명합니다.
Mark Byers의 대답과 Karol Tyl의 대답을 결합하여 Process. Start 메서드를 사용하는 방법을 기반으로 전체 코드를 작성했습니다.
git 명령을 통해 진행 대화 상자를 만드는 데 사용했습니다. 이것이 내가 그것을 사용한 방법입니다 :
이론적으로 stdout과 stderr를 결합 할 수도 있지만 테스트하지는 않았습니다.
나는 이것이 늙다는 것을 알고 있지만이 전체 페이지를 읽은 후에는 해결할 수있는 코드가 없기 때문에 무하마드 레 한 (Muhammad Rehan)을 시도하지는 않았다. . 그것이 완전히 진실하지 않은 경우 작동하지 않는다고 말할 때, 때로는 잘 작동 할 것입니다. EOF 마크 전에 출력의 길이와 관련이 있다고 생각합니다.
어쨌든, 나를 위해 일한 솔루션은 다른 스레드를 사용하여 StandardOutput 및 StandardError를 읽고 메시지를 작성하는 것이 었습니다.
희망이 사람이 도움이되기를 바랍니다, 누가 힘들 수 있다고 생각!
내부 타임 아웃과 생성 된 애플리케이션에 의한 StandardOutput 및 StandardError의 사용으로 인해 다른 솔루션 (EM0를 포함하여)은 여전히 ​​내 애플리케이션에 대해 교착 상태입니다. 여기 나를 위해 일한 것입니다 :
편집 : StartInfo의 초기화를 코드 샘플에 추가했습니다.
이 게시물 어쩌면 구식하지만 난 왜 그것이 일반적으로 끊어지는 주된 원인은 redirectStandardoutput에 대한 스택 오버 플로우 때문이거나 redirectStandarderror가있는 경우입니다.
출력 데이터 또는 오류 데이터가 크기 때문에 무한정 지속되는 동안 정지 시간이 발생합니다.

프로세스. 종료 된 이벤트.
API 참조 문서에는 새로운 홈이 있습니다. 새로운 경험을 보려면 docs. microsoft의 API 브라우저를 방문하십시오.
프로세스가 종료 될 때 발생합니다.
어셈블리 : System (System. dll)
Exited 이벤트는 연결된 프로세스가 종료되었음을 나타냅니다. 이 발생은 프로세스가 종료 (중단)되었거나 성공적으로 닫혔다는 것을 의미합니다. 이 이벤트는 EnableRaisingEvents 속성 값이 true 인 경우에만 발생할 수 있습니다.
연결된 프로세스가 종료 될 때 통보받는 방법에는 동기식 및 비동기식 두 가지가 있습니다. 동기 통지는 프로세스가 종료 할 때까지 현재 스레드를 차단하도록 WaitForExit 메소드를 호출하는 것을 의미합니다. 비동기 알림은 Exited 이벤트를 사용하므로 호출하는 스레드가 그 사이에 계속 실행될 수 있습니다. 후자의 경우, 호출 응용 프로그램이 Exited 이벤트를 수신하려면 EnableRaisingEvents를 true로 설정해야합니다.
운영 체제는 프로세스를 종료 할 때 Exited 이벤트에 대한 핸들러를 등록한 다른 모든 프로세스에 통지합니다. 이 시점에서 방금 종료 한 프로세스의 핸들을 ExitTime 및 HasExited와 같은 일부 속성에 액세스하여 운영 체제가 핸들을 완전히 릴리스 할 때까지 유지 관리 할 수 ​​있습니다.
종료 된 프로세스에 대한 핸들이 있더라도 Start를 다시 호출하여 동일한 프로세스에 다시 연결할 수는 없습니다. Call Start는 자동으로 관련 프로세스를 해제하고 동일한 파일이지만 완전히 새로운 Handle을 가진 프로세스에 연결합니다.
Windows Forms 응용 프로그램에서 Exited 이벤트를 사용하는 방법에 대한 자세한 내용은 SynchronizingObject 속성을 참조하십시오.
다음 코드 예제에서는 파일을 인쇄하는 프로세스를 만듭니다. 프로세스가 생성 될 때 EnableRaisingEvents 속성이 설정 되었기 때문에 프로세스가 종료 될 때 Exited 이벤트가 발생합니다. Exited 이벤트 핸들러는 프로세스 정보를 표시합니다.
즉각적인 호출자에 대한 완전한 신뢰. 이 멤버는 부분적으로 신뢰할 수있는 코드에서 사용할 수 없습니다.

No comments:

Post a Comment