하기 CreateProcess를 사용하여 VC++ Compiler를 이용,
자체 IDE 환경에서 컴파일러를 구현하는 경우,
지정된 Path에 따옴표를 하여 한 문자열로 인식되게끔하여야만,
컴파일이 되는것을 확인하였다.
^^ 음훼훼~~
#define VS2003DEVENV_PATH "\"E:/Program Files/Microsoft Visual Studio .NET 2003/Common7/IDE/devenv.com\""
xxx.h에 선언
HANDLE SpawnAndRedirect(LPCTSTR commandLine, HANDLE *hStdOutputReadPipe, LPCTSTR lpCurrentDirectory);
xxx.cpp에 사용함수와 선언부
{
// strSpawn의 내용으로, 실행시킬 full path+명령.exe parametor로 작성.
HANDLE hOutput, hProcess;
hProcess = SpawnAndRedirect(strSpawn, &hOutput, NULL);
if (!hProcess) return false;
// 종료시점 기다리기..
int fcnt=0;
m_flag=FALSE;
char buffer[1024]="";
char tbuffer[1025*3]="";
DWORD read=0;
while (ReadFile(hOutput, buffer, 1024, &read, NULL))
{
//buffer[read] = '\0';
strcat(tbuffer, buffer);
memset(buffer, 0, sizeof(buffer));
}
char *token="";
token=strtok(tbuffer,"\n");
m_flag=ErrorChk(token);
if(m_flag!=TRUE){fcnt++; AddMessage(FAIL, token);}
else CmdMsgBoxInit(PASS, token);
while(1){
token = strtok(NULL,"\n");
if(token == NULL) break;
m_flag=ErrorChk(token);
if(m_flag!=TRUE){fcnt++; AddMessage(FAIL, token);}
else AddMessage(PASS, token);
}
}
선언부..
BOOL CPG_SendDlg::ErrorChk(char *strbuf)
{
CString strmsg;
strmsg.Format("%s",strbuf);
//strmsg.MakeUpper();
int pos=strmsg.Find("Error:");
if(pos == -1) return TRUE;
return FALSE;
}
// The following function is a shortened variant of Q190351 - HOWTO: Spawn Console Processes with Redirected Standard Handles
// There is no special magic here, and this version doesn't address issues like:
// - redirecting Input handle
// - spawning 16-bits process (well, RTconsole is a 32-bit process anyway so it should solve the problem)
// - command-line limitations (unsafe 1024-char buffer)
// So you might want to use more advanced versions such as the ones you can find on CodeProject
HANDLE SpawnAndRedirect(LPCTSTR commandLine, HANDLE *hStdOutputReadPipe, LPCTSTR lpCurrentDirectory)
{
HANDLE hStdOutputWritePipe, hStdOutput, hStdError;
CreatePipe(hStdOutputReadPipe, &hStdOutputWritePipe, NULL, 0); // create a non-inheritable pipe
DuplicateHandle(GetCurrentProcess(), hStdOutputWritePipe,
GetCurrentProcess(), &hStdOutput, // duplicate the "write" end as inheritable stdout
0, TRUE, DUPLICATE_SAME_ACCESS);
DuplicateHandle(GetCurrentProcess(), hStdOutput,
GetCurrentProcess(), &hStdError, // duplicate stdout as inheritable stderr
0, TRUE, DUPLICATE_SAME_ACCESS);
CloseHandle(hStdOutputWritePipe); // no longer need the non-inheritable "write" end of the pipe
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); // (this is bad on a GUI app)
si.hStdOutput = hStdOutput;
si.hStdError = hStdError;
si.wShowWindow = SW_HIDE; // IMPORTANT: hide subprocess console window
TCHAR commandLineCopy[1024]; // CreateProcess requires a modifiable buffer
_tcscpy(commandLineCopy, commandLine);
if (!CreateProcess(NULL, commandLineCopy, NULL, NULL, TRUE,
CREATE_NEW_CONSOLE, NULL, lpCurrentDirectory, &si, &pi))
{
CloseHandle(hStdOutput);
CloseHandle(hStdError);
CloseHandle(*hStdOutputReadPipe);
*hStdOutputReadPipe = INVALID_HANDLE_VALUE;
return NULL;
}
CloseHandle(pi.hThread);
CloseHandle(hStdOutput);
CloseHandle(hStdError);
return pi.hProcess;
}