Здравствуйте.
KF>> Почему без использования батников извратно? MZ> Потому что надо написать больше сотни строк на С. только ради MZ> перенаправления вывода. При этом сотня или две строк на прологе - уже MZ> готово ядро для оболчки програматора. С засыванием базы из файла, и с MZ> запросами к базе. Еще сотня строк - и ядро железобетнное, со всеми MZ> обработками ошибок (т.е. оно не прервет операцию из за файловой ошибки MZ> или эксепшена). Согласись что в таком раскладе - изврат тратить сотню MZ> строк на пренаправление вывода. Хотя это мелочь конечно.
Утомил уже. Дарю:
#if !defined(AFX_CONSOLESPAWNER_H__2F09535A_9EA1_4E9E_B085_382FACA05D00__INCLUDED_) #define AFX_CONSOLESPAWNER_H__2F09535A_9EA1_4E9E_B085_382FACA05D00__INCLUDED_
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ConsoleSpawner.h : header file //
///////////////////////////////////////////////////////////////////////////// // CConsoleSpawner window
class CConsoleSpawner : public CEdit { // Construction public: CConsoleSpawner();
// Attributes public: HANDLE m_hChildStdInRead; HANDLE m_hChildStdInWrite; HANDLE m_hChildStdOutRead; HANDLE m_hChildStdOutWrite; PROCESS_INFORMATION m_pi;
// Operations public: int Execute(LPCSTR szCmdLine); void GenerateBreak();
// Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CConsoleSpawner) protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL
// Implementation public: CBrush m_brush; virtual ~CConsoleSpawner();
// Generated message map functions protected: //{{AFX_MSG(CConsoleSpawner) afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); afx_msg void OnDestroy(); //}}AFX_MSG
DECLARE_MESSAGE_MAP()
void TraceLine(const char* szFormat, ...); };
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CONSOLESPAWNER_H__2F09535A_9EA1_4E9E_B085_382FACA05D00__INCLUDED_)
// ConsoleSpawner.cpp : implementation file //
#include "stdafx.h" #include "crossflasher.h" #include "ConsoleSpawner.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif
///////////////////////////////////////////////////////////////////////////// // CConsoleSpawner
CConsoleSpawner::CConsoleSpawner() { m_hChildStdInRead = NULL; m_hChildStdInWrite = NULL; m_hChildStdOutRead = NULL; m_hChildStdOutWrite = NULL; memset(&m_pi, 0, sizeof(m_pi)); }
CConsoleSpawner::~CConsoleSpawner() { }
BEGIN_MESSAGE_MAP(CConsoleSpawner, CEdit) //{{AFX_MSG_MAP(CConsoleSpawner) ON_WM_CTLCOLOR_REFLECT() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// // CConsoleSpawner message handlers
HBRUSH CConsoleSpawner::CtlColor(CDC* pDC, UINT nCtlColor) { return (HBRUSH)m_brush.GetSafeHandle(); }
void CConsoleSpawner::PreSubclassWindow() { CEdit::PreSubclassWindow(); m_brush.CreateSolidBrush(GetSysColor(COLOR_WINDOW)); }
void CConsoleSpawner::OnDestroy() { CEdit::OnDestroy(); m_brush.DeleteObject(); }
/**************************************************************************** * Функция : CConsoleSpawner::Execute() * Назначение : Запуск приложения и перехват его вывода в присабклассенный * editbox * Автор : Алексей Краснов * Создана : 12.05.2003 17:27:54 * Параметры : * LPCSTR szCmdLine - командная строка * Возвращает : int - код возврата запущенного приложения или -1 в случае, * если возникла ошибка в другом месте ****************************************************************************/ int CConsoleSpawner::Execute(LPCSTR szCmdLine) { // очищаем окно вывода SetWindowText("");
SECURITY_ATTRIBUTES sa;
// создаем анонимные пайпы memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE;
// стандартный ввод if (!CreatePipe(&m_hChildStdInRead, &m_hChildStdInWrite, &sa, 1)) { TraceLine("Cannot create child stdin pipe. Error 0x%08X.\r\n", GetLastError()); return -1; }
// стандартный вывод if (!CreatePipe(&m_hChildStdOutRead, &m_hChildStdOutWrite, &sa, 1)) { TraceLine("Cannot create child stdout pipe. Error 0x%08X.\r\n", GetLastError()); return -1; }
// запускаем процесс STARTUPINFO si;
memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = m_hChildStdInRead; si.hStdOutput = m_hChildStdOutWrite; si.hStdError = m_hChildStdOutWrite;
char caBuff[MAX_PATH]; strcpy(caBuff, szCmdLine);
if (CreateProcess(NULL, caBuff, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &m_pi) == 0) { TraceLine("Cannot create child process. Error 0x%08X.\r\n", GetLastError()); return -1; }
char buff[256]; DWORD dwBytesRead, dwBytesAvail;
while (TRUE) { // проверим наличие данных в пайпе, исключив тем самым блокировку // потока при отсутствии данных if (PeekNamedPipe(m_hChildStdOutRead, buff, 1, &dwBytesRead, &dwBytesAvail, NULL) && dwBytesRead == 1) { if (dwBytesAvail > sizeof(buff)) dwBytesAvail = sizeof(buff) - 1; if (ReadFile(m_hChildStdOutRead, buff, dwBytesAvail, &dwBytesRead, NULL) && dwBytesRead == dwBytesAvail) { buff[dwBytesRead] = 0; TraceLine(buff); } }
// отрабатываем оконные сообщения MSG msg; if (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE)) AfxGetApp()->PumpMessage();
// ждем сигнала завершения процесса if (WaitForSingleObject(m_pi.hProcess, 1) == WAIT_OBJECT_0) break; }
CloseHandle(m_hChildStdInRead); m_hChildStdInRead = NULL; CloseHandle(m_hChildStdInWrite); m_hChildStdInWrite = NULL; CloseHandle(m_hChildStdOutRead); m_hChildStdOutRead = NULL; CloseHandle(m_hChildStdOutWrite); m_hChildStdOutWrite = NULL;
int nRes; GetExitCodeProcess(m_pi.hProcess, (LPDWORD)&nRes);
CloseHandle(m_pi.hProcess); CloseHandle(m_pi.hThread); memset(&m_pi, 0, sizeof(m_pi));
return nRes; }
/**************************************************************************** * Функция : CConsoleSpawner::TraceLine() * Назначение : Вывод строки с форматированием в конец присабклассенного * editbox * Автор : Алексей Краснов * Создана : 13.05.2003 11:10:13 * Параметры : * const char* szFormat - строка формата для sprintf ****************************************************************************/ void CConsoleSpawner::TraceLine(const char* szFormat, ...) { va_list arglist; va_start(arglist, szFormat); char szBuffer[512]; vsprintf(szBuffer, szFormat, arglist); int n = GetWindowTextLength(); SetSel(n, n); ReplaceSel(szBuffer); va_end(arglist); }
/**************************************************************************** * Функция : CConsoleSpawner::GenerateBreak() * Назначение : Генерирует событие Ctrl-Break для дочернего процесса * Автор : Алексей Краснов * Создана : 13.05.2003 15:51:37 ****************************************************************************/ void CConsoleSpawner::GenerateBreak() { if (m_pi.dwProcessId) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, m_pi.dwProcessId); }