C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[45775] [자답]Re:IDE 제작중에 16 bit DOS용 프로그램 리다이렉션 문의
고황일 [hwangil] 1369 읽음    2006-07-21 10:46
결국.. DevC++ 소스프로그램의 델파이 소스를 빌더로 변경해서 해결했습니다.
머 배치파일이나 윈도 플, 도스 플.. 다되는군요..

참고 하시라고.. ^^

간략하게 사용법은..

Memo1->Text = RunAndGetOutput("c:\\test.bat", "c:\\", false);
이러면.. 모든과정이 끝난다음에 결과가 메모로 입력됩니다.
실행중간에 라인단위로 전달받을려면..
소스를 조금만 수정하세요.. 주석부..

== 소스 ==
String __fastcall TForm1::RunAndGetOutput(String Cmd, String WorkDir,
//  ErrFunc: TErrFunc;               // 에러 표시용 함수 지정
//  LineOutputFunc: TLineOutputFunc; // 라인단위 출력용 함수 지정
//  CheckAbortFunc: TCheckAbortFunc; // 중지용 함수 실행
        bool ShowReturnValue)
{
  STARTUPINFO tsi;
  PROCESS_INFORMATION tpi;
  DWORD nRead;
  char aBuf[101];
  SECURITY_ATTRIBUTES sa;
  HANDLE hOutputReadTmp, hOutputRead, hOutputWrite, hInputWriteTmp, hInputRead,
  hInputWrite, hErrorWrite;
  String FOutput;
  String CurrentLine;
  bool bAbort;
  String Result;

  FOutput = "";
  CurrentLine = "";

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.lpSecurityDescriptor = NULL;
  sa.bInheritHandle = true;

  CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0);
  DuplicateHandle(GetCurrentProcess(), hOutputWrite, GetCurrentProcess(),
                  &hErrorWrite, 0, true, DUPLICATE_SAME_ACCESS);

  CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0);

  // Create new output read handle and the input write handle. Set
  // the inheritance properties to FALSE. Otherwise, the child inherits
  // the these handles; resulting in non-closeable handles to the pipes
  // being created.

  DuplicateHandle(GetCurrentProcess(), hOutputReadTmp,  GetCurrentProcess(),
                  &hOutputRead, 0, false, DUPLICATE_SAME_ACCESS);
  DuplicateHandle(GetCurrentProcess(), hInputWriteTmp, GetCurrentProcess(),
                  &hInputWrite, 0, false, DUPLICATE_SAME_ACCESS);
  CloseHandle(hOutputReadTmp);
  CloseHandle(hInputWriteTmp);


  memset(&tsi, 0, sizeof(STARTUPINFO));
  tsi.cb = sizeof(STARTUPINFO);
  tsi.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
  tsi.hStdInput = hInputRead;
  tsi.hStdOutput = hOutputWrite;
  tsi.hStdError = hErrorWrite;

  bool dFlag = CreateProcess(NULL, Cmd.c_str(), &sa, &sa, true, 0, NULL, WorkDir.c_str(), &tsi, &tpi);
  if (!dFlag) {
    Result = "Unable to run '" + Cmd + "': " + SysErrorMessage(GetLastError());
    return "";
  }
  CloseHandle(hOutputWrite);
  CloseHandle(hInputRead );
  CloseHandle(hErrorWrite);

  bAbort = false;

  while (1) {
// 여기서 외부 중지를 할 수 있도록 한다.
//     if (CheckAbortFunc != NULL)
//        CheckAbortFunc(bAbort);
//     if (bAbort) {
//       TerminateProcess(tpi.hProcess, 1);
//       break;
//     }
     if ((!ReadFile(hOutputRead, &aBuf, 16, &nRead, NULL)) || (nRead == 0)) {
        if (GetLastError() == ERROR_BROKEN_PIPE)
          break;
        else
          MessageDlg("Pipe read error, could not execute file", mtError, TMsgDlgButtons() << mbOK, 0);
     }
     aBuf[nRead] = 0;

     FOutput = FOutput + String(aBuf);

// 라인 단위 출력을 한다.
//     if (LineOutputFunc != NULL) {
//         CurrentLine = CurrentLine + String(aBuf);
//         if (CurrentLine.c_str()[CurrentLine.Length()] == 10) {
//             CurrentLine.Delete(CurrentLine.Length(), 1);
//             LineOutputFunc(CurrentLine);
//             CurrentLine = "";
//         }
//     }
  }

  GetExitCodeProcess(tpi.hProcess, &nRead);
  if (ShowReturnValue)
     Result = FOutput + " " + IntToStr(nRead);
  else
     Result = FOutput;

  CloseHandle(hOutputRead);
  CloseHandle(hInputWrite);
  CloseHandle(tpi.hProcess);
  CloseHandle(tpi.hThread);

  return Result;
}
//---------------------------------------------------------------------------


고황일 님이 쓰신 글 :
: 다들 비도 많이 오고 무더운데 고생이 많습니다.
: 이번에 신형 장비를 받고 장비용 프로그램을 짜다 개발 환경이 너무 않좋아서 개발 툴을 작성하고 있습니다.
: 머.. 대단한 실력은 아니지만 그럭저럭 구현을 다 했는데요, 콘솔 리다이렉션이 문제입니다.
: 컴파일/링크 과정에 콘솔 출력들을 ListBox에 표시하고 싶은데요 계속 콘솔 창이 떠버려서 문제입니다.
:
: 이 프로그램이 cygwin에 있는 g++를 이용하여 컴파일을 해야하는데
: 간단하게 g++.exe 파일을 실행만 하면 좋은데.. 몇가지 스크립트를 배치 파일로 작성을
: 해 놨지 뭡니다까... 그래서 스크립트 자동화를 해벌릴려고 했더니 배치 파일내에서
: 소스 파일을 파싱하는 java 프로그램을 실행해서 스크립트가 새로 갱신이 되는 구조로 되어있어서
: 개발 툴내에서 어쩔수 없이 배치 파일을 실행을 해야하는 상황이 생겼습니다.
:
: 포럼내에서 검색해서 찾은 방법은 하나의 실행 파일을 (16bit DOS/32bit 콘솔) 실행했을때는
: 리다이렉션이 가능한데.. 배치파일을 실행하면 콘솔 창이 계속 떠버리는 상황이 발생됩니다.
: 제가 원하는 것은 개발 툴내에서 배치파일을 호출을 해도 모든 콘솔 출력을 ListBox 컴포넌트에
: 기록을 하는건데.. 계속 실패하고 있습니다.
:
: 선배님의 자문을 구합니다.

+ -

관련 글 리스트
45754 IDE 제작중에 16 bit DOS용 프로그램 리다이렉션 문의 고황일 1381 2006/07/20
45775     [자답]Re:IDE 제작중에 16 bit DOS용 프로그램 리다이렉션 문의 고황일 1369 2006/07/21
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.