성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 배치 파일 실행하고 출력 결과를 얻는 방법</h1> <p> 우선 배치 파일을 C#으로 실행하는 방법은 다음과 같이 간단합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Process.Start("test.bat"); </pre> <br /> 또는 ProcessStartInfo 타입을 이용해 복잡하게(?) 실행할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "test.bat"; Process proc = Process.Start(psi); </pre> <br /> 더 복잡하게 실행하는 다음의 방법도 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; Process.Start(psi); </pre> <br /> 위의 3가지 방법은 다른 듯 하지만, 실은 모두 똑같습니다. 결국 실행하면 마지막 방식으로 실행한 것처럼 cmd.exe로 "/C" 옵션을 경유해 배치 파일이 실행됩니다. 개인적으로는, 복잡하지만 제가 제어했다는 이유만으로 3번째 방법을 선호합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그럼, 배치 파일을 실행한 이후 그 출력 결과를 가져오려면 어떻게 해야 할까요?<br /> <br /> 이를 위해 다음과 같이 Process.StandardOutput 속성을 이용해 ReadToEnd를 호출하면?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; Process proc = Process.Start(psi); proc.WaitForExit(); string txt = proc.StandardOutput.ReadToEnd(); </pre> <br /> 아쉽게도 이런 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > System.InvalidOperationException was unhandled _HResult=-2146233079 _message=StandardOut has not been redirected or the process hasn't started yet. HResult=-2146233079 IsTransient=false Message=StandardOut has not been redirected or the process hasn't started yet. Source=System StackTrace: at System.Diagnostics.Process.get_StandardOutput() at ConsoleApplication1.Program.CallType1() in e:\...\ConsoleApplication1\Program.cs:line 52 at ConsoleApplication1.Program.Main(String[] args) in e:\...\ConsoleApplication1\Program.cs:line 15 InnerException: </pre> <br /> 즉, StandardOutput 속성을 사용하려면 미리 ProcessStartInfo.RedirectStandardOutput 속성을 true로 명시해줘야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; <span style='color: blue; font-weight: bold'>psi.RedirectStandardOutput = true;</span> Process proc = Process.Start(psi); proc.WaitForExit(); string txt = proc.StandardOutput.ReadToEnd(); </pre> <br /> 하지만, 이렇게 했어도 예외가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > System.InvalidOperationException was unhandled _HResult=-2146233079 _message=The Process object must have the UseShellExecute property set to false in order to redirect IO streams. HResult=-2146233079 IsTransient=false Message=The Process object must have the UseShellExecute property set to false in order to redirect IO streams. Source=System StackTrace: at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start(ProcessStartInfo startInfo) at ConsoleApplication1.Program.CallType1() in e:\...\ConsoleApplication1\Program.cs:line 49 at ConsoleApplication1.Program.Main(String[] args) in e:\...\ConsoleApplication1\Program.cs:line 15 InnerException: </pre> <br /> 친절하게도 이번엔 속성 이름까지 지정해주고 있습니다. 결국 다음과 같이 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; psi.RedirectStandardOutput = true; <span style='color: blue; font-weight: bold'>psi.UseShellExecute = false;</span> Process proc = Process.Start(psi); proc.WaitForExit(); string txt = proc.StandardOutput.ReadToEnd(); </pre> <br /> 위의 경우, ReadToEnd를 호출했기 때문에 Process.WaitForExit를 호출할 필요는 없습니다. 그래서 다음과 같이 작성해도 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; psi.RedirectStandardOutput = true; psi.UseShellExecute = false; Process proc = Process.Start(psi); <span style='color: blue; font-weight: bold'>string txt = proc.StandardOutput.ReadToEnd();</span> </pre> <br /> 만약, 출력 결과를 라인 단위로 가져오고 싶다면 이렇게 작성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "cmd.exe"; psi.Arguments = "/C test.bat"; psi.RedirectStandardOutput = true; psi.UseShellExecute = false; Process proc = Process.Start(psi); while (true) { string txt = proc.StandardOutput.ReadLine(); // blocking 함수 if (txt == null) // 프로세스가 종료한 경우 null 반환 { break; } Console.WriteLine(txt); } </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7690
(왼쪽의 숫자를 입력해야 합니다.)