Re[7]: Перенаправление ввода-вывода консоли
От: ua1zcl Россия www.alexklm.ru
Дата: 21.05.04 18:34
Оценка:
Здравствуйте, вce!
Сегодня я проанилизировал некоторые примеры и пришёл к выоду что рершение задачи возможно разным путём. Не думаю, что кто-нибудь сможет оъяснить верность того или иного решения. Практика показала, что подобные задачи зачастую приходится решать путём подбора вариантов, ибо скудость информации от MS на эту тему безмерна. Привожу код работающий в 98 и 2000 Windows'ах.

/////////////////////////////////////////////////////////////////////////////////
static void EnsureChildProcDied(void);
static PROCESS_INFORMATION pi;


static bool RunProcess(PVOID pv)
{
 if(!pRcvBuf)pRcvBuf= new char[100];
 if(!pTsmBuf)pTsmBuf= new char[100];
 HANDLE hChildsInpPipe=0,hMyOutPipe=0;
 HANDLE hChildsOutPipe=0,hMyInpPipe=0;
 bool fSuccess;
 int iFailures=0;

 if(ptl)
 {
  sprintf(str,"Running %s   '%s' { %s} for {%s}\r\n",
             ptl->szTlType[0]?ptl->szTlType:"CommandLine tool",
                 ptl->szTlAlias[0]?ptl->szTlAlias:"",
                 pszThisToolFPath,pszTargetFile);
 }
 else sprintf(str,"Running...  {tool: %s} for {%s}\r\n",pszThisToolFPath,pszTargetFile);
 Lm(str);

 dwNbytesRead=0; dwReadSoFar=0; dwWritn=0;
 DWORD dwRes;
 DWORD dwRead=1;
 bool bRead=1,bRes=0;
 PVOID psd = NULL;
 LPSECURITY_ATTRIBUTES psa=0;

 if(sg.uOsVersion==W2000 || sg.uOsVersion==WXP || sg.uOsVersion==WNT4)
 {
  assert(psd = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
  assert(InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION));
  assert(SetSecurityDescriptorDacl(psd, -1, 0, 0));

  psa = (LPSECURITY_ATTRIBUTES)::GlobalAlloc(GPTR, sizeof(SECURITY_ATTRIBUTES));
  psa->nLength = sizeof(SECURITY_ATTRIBUTES);
  psa->lpSecurityDescriptor = psd;
  psa->bInheritHandle = TRUE;
 }

 memset(&pi,0,sizeof pi);
 STARTUPINFO si={0};
 BOOL bProc;
 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 HANDLE hCurProc=GetCurrentProcess();

 memset(&si, 0, sizeof(STARTUPINFO));

 if(!CreatePipe(&hMyInpPipe, &hChildsOutPipe, psa,10000)){ goto end;}
 if(!CreatePipe(&hChildsInpPipe, &hMyOutPipe, psa,10000)){ goto end;}

 si.cb = sizeof(STARTUPINFO);
 si.dwFlags = STARTF_USESTDHANDLES;

 si.hStdError = hChildsOutPipe;
 si.hStdInput = hChildsInpPipe;
 si.hStdOutput = hChildsOutPipe;

 si.wShowWindow=SW_HIDE;
 si.dwFillAttribute=0;//BACKGROUND_BLUE|FOREGROUND_GREEN;
 si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;//|STARTF_USEFILLATTRIBUTE;//    |

 SetCurrentDirectory(pszCurrDir);// Чтобы компилятор знал откуда плясать

 #ifdef DBUG
 SaveShortFile("_CmdLineReal.txt",pszFullCmdLine,strlen(pszFullCmdLine));
 #endif


 SetStdHandle(STD_OUTPUT_HANDLE,hChildsOutPipe);
 SetStdHandle(STD_ERROR_HANDLE,hChildsOutPipe);
 SetStdHandle(STD_INPUT_HANDLE,hChildsInpPipe);

 bProc=CreateProcess(NULL,pszFullCmdLine,0,psa,TRUE,CREATE_SUSPENDED,0,0, &si, &pi);//|CREATE_NEW_CONSOLE
 if(!bProc || (!pi.hProcess || !pi.hThread || !pi.dwProcessId || !pi.dwThreadId))
 { Mbox("No Process created"); Gle(); goto end;}

 if(hChildsOutPipe)CloseHandle(hChildsOutPipe); hChildsOutPipe=0;
 if(hChildsInpPipe)CloseHandle(hChildsInpPipe); hChildsInpPipe=0;

 dwTicksStarted=GetTickCount();

 dwRes=ResumeThread(pi.hThread);
 //sprintf(str,"ResumeThread return %d\r\n",dwRes); Lm(str);
 SetLastError(0);

 while((bRead && dwRead) || iFailures < 10)
 {
  dwRead=0;
  bRead=ReadFile(hMyInpPipe,pRcvBuf+dwNbytesRead,1,&dwRead,0);

   if(bRead && dwRead)
   { dwNbytesRead+=dwRead;
     if( dwNbytesRead+1>=50)
     { *(pRcvBuf+dwNbytesRead)=0; Lm(pRcvBuf);
       dwReadSoFar+=dwNbytesRead; dwNbytesRead=0;
     }
   }
   else iFailures++;
 }
 //sprintf(str,"dwReadSoFar %d\r\n",dwReadSoFar); Lm(str);
 bRes=CompleteReading();
 #ifdef DBUG
 SaveShortFile("_pszLe.txt",pszLe,iCurErrStrlen);
 #endif
 if(ptl)FindAndAddWarnsErrorMessage(ptl,pv);

end:
 if(hChildsInpPipe)CloseHandle(hChildsInpPipe);
 if(hMyOutPipe)CloseHandle(hMyOutPipe);
 if(hChildsOutPipe)CloseHandle(hChildsOutPipe);
 if(hMyInpPipe)CloseHandle(hMyInpPipe);

 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
 //CloseHandle(pi.hThread);
 // Cleanup memory allocation
 if(psa)GlobalFree(psa);
 if(psd)GlobalFree(psd);
 EnsureChildProcDied();
 dwTicksFinished=GetTickCount();
 return bRes;
}
////////////////////////////////////////////////////////////////////////////////

static void EnsureChildProcDied(void)
{
 if(pi.hProcess && pi.dwProcessId &&  GetProcessVersion(pi.dwProcessId))
 {
  DWORD dwRes=WaitForInputIdle(pi.hProcess,500);
  BOOL bTermRes=TerminateProcess(pi.hProcess,0);
  if(!bTermRes)Gle();
  else *zd.pbCompiling=0;
 }
}
////////////////////////////////////////////////////////////////////////////////
Александр
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.