⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conredirect.cpp

📁 用于开发Atmel的AVR系列单片机的GCC集成开发环境
💻 CPP
字号:
/**************************************************************************
Project: WinAVRIDE        Class: Console with Redirected stdin,stdout,stderr
Copyright (C) 2005  Philipp Schober

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

History
19.Feb 2005 - First Release (V1.0)
****************************************************************************/

#include <vcl\vcl.h>
#pragma hdrstop

#include "ConRedirect.h"
//#include "Unit1.h"

//---------------------------------------------------------------------------
static inline TConRedirect *ValidCtrCheck()
{
	return new TConRedirect(NULL);
}
//---------------------------------------------------------------------------
__fastcall TConRedirect::TConRedirect(TComponent* Owner)
	: TComponent(Owner)
{
 OSVERSIONINFO osv;

 osv.dwOSVersionInfoSize = sizeof(osv);
 GetVersionEx(&osv);
 if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) isWinNT = true;
 else isWinNT = false;

 StdIn = NULL;
 StdOut = NULL;
 StdErr = NULL;
 StdInWrite = NULL;
 StdOutRead = NULL;
 StdErrRead = NULL;

 StdOutThread = NULL;
 StdErrThread = NULL;
 MonThread = NULL;
 childrunning = false;
}
//---------------------------------------------------------------------------
__fastcall TConRedirect::~TConRedirect()
{
 DWORD exitcode;

 GetExitCodeProcess (ChildProcess, &exitcode);
 if (exitcode == STILL_ACTIVE) // Check for open Process
 {
  TerminateProcess (ChildProcess, 0);
  WaitForSingleObject(ChildProcess, 2000); // Wait max. 2sec for Termination
 }
 Terminate ();
}
//---------------------------------------------------------------------------
namespace Conredirect
{
	void __fastcall Register()
	{
		TComponentClass classes[1] = {__classid(TConRedirect)};
		RegisterComponents("Beispiele", classes, 0);
	}
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::ClosePipeHandles (void)
{
 if (StdIn != NULL) CloseHandle (StdIn);
 StdIn = NULL;
 if (StdOut != NULL) CloseHandle (StdOut);
 StdOut = NULL;
 if (StdErr != NULL) CloseHandle (StdErr);
 StdErr = NULL;
 if (StdInWrite != NULL) CloseHandle (StdInWrite);
 StdInWrite = NULL;
 if (StdOutRead != NULL) CloseHandle (StdOutRead);
 StdOutRead = NULL;
 if (StdErrRead != NULL) CloseHandle (StdErrRead);
 StdErrRead = NULL;
}
//---------------------------------------------------------------------------
bool __fastcall TConRedirect::RunChild (char *appname, char *params, char *workpath)
{
 HANDLE Process;
 SECURITY_ATTRIBUTES sa;
 PROCESS_INFORMATION pi;
 STARTUPINFO si;

 ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
 sa.nLength= sizeof(SECURITY_ATTRIBUTES);
 sa.lpSecurityDescriptor = NULL;
 sa.bInheritHandle = TRUE;

 // Create the child stdin pipe.
 if (!CreatePipe(&StdIn, &StdInWriteTmp, &sa, 0))
 {
  ClosePipeHandles ();
  return false;
 }
 // Create the child stdout pipe.
 if (!CreatePipe(&StdOutReadTmp, &StdOut, &sa, 0))
 {
  ClosePipeHandles ();
  return false;
 }
 // Create the child stderr pipe.
 if (!CreatePipe(&StdErrReadTmp, &StdErr, &sa, 0))
 {
  ClosePipeHandles ();
  return false;
 }

 Process = GetCurrentProcess();
 // Duplicate Handles to non-inheritable Handles
  if (!DuplicateHandle(Process, StdInWriteTmp, Process, &StdInWrite, 0,
     FALSE, DUPLICATE_SAME_ACCESS))
 {
  ClosePipeHandles ();
  return false;
 }
 if (!DuplicateHandle(Process, StdOutReadTmp, Process, &StdOutRead, 0,
     FALSE, DUPLICATE_SAME_ACCESS))
 {
  ClosePipeHandles ();
  return false;
 }
 if (!DuplicateHandle(Process, StdErrReadTmp, Process, &StdErrRead, 0,
     FALSE, DUPLICATE_SAME_ACCESS))
 {
  ClosePipeHandles ();
  return false;
 }

 // Close inheritable Handles
 CloseHandle(StdInWriteTmp);
 CloseHandle(StdOutReadTmp);
 CloseHandle(StdErrReadTmp);

 // Set up the start up info struct.
 ZeroMemory(&si, sizeof(STARTUPINFO));
 si.cb = sizeof(STARTUPINFO);
 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
 si.hStdOutput = StdOut;
 si.hStdInput  = StdIn;
 si.hStdError  = StdErr;
 si.wShowWindow = SW_HIDE;

 // Create the NULL security token for the process
 LPVOID lpSD = NULL;
 LPSECURITY_ATTRIBUTES lpSA = NULL;

 // On NT/2000/XP the handle must have PROCESS_QUERY_INFORMATION access.
 if (isWinNT)
 {
  lpSD = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  InitializeSecurityDescriptor(lpSD, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(lpSD, -1, 0, 0);
  lpSA = (LPSECURITY_ATTRIBUTES)GlobalAlloc(GPTR, sizeof(SECURITY_ATTRIBUTES));
  lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
  lpSA->lpSecurityDescriptor = lpSD;
  lpSA->bInheritHandle = TRUE;
 }

 // Spawn Child Process.
 temp = CreateProcess(appname, params, lpSA, NULL, TRUE, CREATE_NEW_CONSOLE,
 					  NULL, workpath, &si, &pi);

 // Free allocated Memory
 if (lpSA != NULL) GlobalFree(lpSA);
 if (lpSD != NULL) GlobalFree(lpSD);

 // Check if Child Process Creation was successful
 if (!temp || pi.hProcess == NULL)
 {
  ClosePipeHandles ();
  return false;
 }

 CloseHandle(pi.hThread);

 StdOutThread = new TStdOutThread (true); // Create StdOut Thread
 StdOutThread->StdOutRead = StdOutRead;
 StdOutThread->OnStdOut = StdOutFunc;
 StdErrThread = new TStdErrThread (true); // Create StdErr Thread
 StdErrThread->StdErrRead = StdErrRead;
 StdErrThread->OnStdErr = StdErrFunc;
 MonThread = new TMonThread (true);  // Create Monitoring Thread
 MonThread->ChildProcess = pi.hProcess;
 MonThread->OnChildExit = ChildExitFunc;
 StdOutThread->Resume ();
 StdErrThread->Resume ();
 MonThread->Resume ();
 childrunning = true;
 ChildProcess = pi.hProcess;
 return true;
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::Terminate (void)
{
 childrunning = false;
 ClosePipeHandles ();
 Sleep(100);
 if (StdOutThread != NULL) StdOutThread->Terminate ();
 StdOutThread = NULL;
 if (StdErrThread != NULL) StdErrThread->Terminate ();
 StdErrThread = NULL;
 if (MonThread != NULL) MonThread->Terminate ();
 MonThread = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::SendChar (char ch)
{
 DWORD bread;
 char buf[10];

 buf[0] = ch;
 buf[1] = 0;
 WriteFile(StdInWrite,buf,1,&bread,NULL); //send it to stdin
 if (ch == '\r')
 {
  buf[0] = '\n';
  WriteFile(StdInWrite,buf,1,&bread,NULL);
 }
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::SendString (AnsiString str)
{
 DWORD bread;

 WriteFile(StdInWrite,str.c_str (),str.Length (),&bread,NULL); //send it to stdin
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::StdOutFunc (char *buffer, int len)
{
 if (FOnStdOut) FOnStdOut (buffer, len);
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::StdErrFunc (char *buffer, int len)
{
 if (FOnStdErr) FOnStdErr (buffer, len);
}
//---------------------------------------------------------------------------
void __fastcall TConRedirect::ChildExitFunc (int exitcode)
{
 Terminate ();
 if (FOnChildExit) FOnChildExit (exitcode);
}
//---------------------------------------------------------------------------
bool __fastcall TConRedirect::isChildRunning (void)
{
 return (childrunning);
}
//---------------------------------------------------------------------------
//------- StdOut Read Thread
//---------------------------------------------------------------------------
__fastcall TStdOutThread::TStdOutThread(bool CreateSuspended)
	: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TStdOutThread::Execute()
{
 AnsiString tmp;
 DWORD e;

 while (!Terminated)
 {
  if (!ReadFile(StdOutRead, buffer, BUFFER_SIZE, &length, NULL) || !length)
  {
   if ((e = GetLastError()) == ERROR_BROKEN_PIPE) break; // pipe done - normal exit path.
   else
   {
    tmp.printf ("Error in StdOut Thread\nErrorcode : %lu", e);
    ShowMessage (tmp); // Something bad happened.
    break;
   }
  }
  if (length)
  {
   buffer[length] = '\0';
   Synchronize (StdOutWrap);
  }
 }
}
//---------------------------------------------------------------------------
void __fastcall TStdOutThread::StdOutWrap (void)
{
 if (FOnStdOut) FOnStdOut (buffer, length);
}
//---------------------------------------------------------------------------
//------- StdErr Read Thread
//---------------------------------------------------------------------------
__fastcall TStdErrThread::TStdErrThread(bool CreateSuspended)
	: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TStdErrThread::Execute()
{
 while (!Terminated)
 {
  if (!ReadFile(StdErrRead, buffer, BUFFER_SIZE, &length, NULL) || !length)
  {
   if (GetLastError() == ERROR_BROKEN_PIPE) break; // pipe done - normal exit path.
   else
   {
    ShowMessage ("Error int StdErr Thread"); // Something bad happened.
    break;
   }
  }
  if (length)
  {
   buffer[length] = '\0';
   Synchronize (StdErrWrap);
  }
 }
}
//---------------------------------------------------------------------------
void __fastcall TStdErrThread::StdErrWrap (void)
{
 if (FOnStdErr) FOnStdErr (buffer, length);
}
//---------------------------------------------------------------------------
//------- Child Process Monitoring Thread
//---------------------------------------------------------------------------
__fastcall TMonThread::TMonThread(bool CreateSuspended)
	: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TMonThread::Execute()
{
 while (!Terminated)
 {
  WaitForSingleObject(ChildProcess,INFINITE); // Wait until Child Process exits
  Terminate (); // Terminate this Thread
 }
 Sleep (200);
 GetExitCodeProcess (ChildProcess, &exitcode);
 Synchronize (ChildExitWrap);
}
//---------------------------------------------------------------------------
void __fastcall TMonThread::ChildExitWrap (void)
{
 if (FOnChildExit) FOnChildExit (exitcode);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -