Création de processus et redirection des I/O standards


La création d'un processus représente, de manière simplifiée, le lancement d'une application. Pour illustrer notre example, on va réaliser une application console qui va se charger de lancer l'application dont on lui fournira le nom en paramètre. Les I/O standards sont redirigés dans un fichier afin de récupèrer les différents messages qui pourraient être affichés sur la console.
Le fonctionnement du programme est le suivant. Un fichier d'extension CMD est créé et est composé du nom de l'application à exécuter.
La création d'un processus se fait par un appel à l'API Win32 CreateProcess. Cette fonction requiert plusieurs paramètres.
BOOL CreateProcess(
  LPCTSTR lpApplicationName,                 // name of executable module
  LPTSTR lpCommandLine,                      // command line string
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD
  BOOL bInheritHandles,                      // handle inheritance option
  DWORD dwCreationFlags,                     // creation flags
  LPVOID lpEnvironment,                      // new environment block
  LPCTSTR lpCurrentDirectory,                // current directory name
  LPSTARTUPINFO lpStartupInfo,               // startup information
  LPPROCESS_INFORMATION lpProcessInformation // process information
);
Les paramètres qui nous intéressent sont lpCommandLine et lpStartupInfo. Le premier va contenir le nom du fichier d'extension CMD créé et le second va contenir le HANDLE du fichier dans lequel sont redirigés les I/O standards. Le fichier CMD est créé sous le répertoire temp et sera détruit à la fin du programme. Le programme est écrit de tel manière que le fichier contenant le flux de données issu des I/O standards est lu et retourné en tant que chaîne de charactères afin d'être affiché.

#include "windows.h"
#include "stdio.h"
#include "atlbase.h"

BOOL CmdRun(LPSTR lpszCmd, LPSTR * lpszBuffer);
int main(int argc, TCHAR* argv[])
{

	if( argc != 2 )
	{
		printf("CreateP2 cmd\n");
		return 0;
	}

	LPSTR lpsz;
	CmdRun(argv[1], &lpsz);
	printf("%s\n", lpsz);

	return 0;
}

BOOL CmdRun(LPSTR lpszCmd, LPSTR * lpszBuffer)
{
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL bCreated = FALSE;
	SECURITY_ATTRIBUTES sa;

	memset(π, 0, sizeof(PROCESS_INFORMATION));
	memset(&si, 0, sizeof(STARTUPINFO));
	memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
	
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	char szCmdOut[255];
	sprintf(szCmdOut, "c:\\temp\\cmd%ld_out.txt", GetCurrentThreadId());
	HANDLE hFile = CreateFile(szCmdOut, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL, NULL); 
	if( hFile == INVALID_HANDLE_VALUE )
	{
		printf("CreateFile cmd_out.txt failed\n");
		return FALSE;
	}
   
	char szCmd[255];
	sprintf(szCmd, "c:\\temp\\cmd%ld.cmd", GetCurrentThreadId());
	HANDLE hCmdFile = CreateFile(szCmd, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL, NULL); 
	if( hCmdFile == INVALID_HANDLE_VALUE )
	{
		printf("CreateFile cmd.cmd failed\n");
		return FALSE;
	}
	DWORD dwSize = 0;
	WriteFile(hCmdFile, lpszCmd,strlen(lpszCmd), &dwSize,NULL);
	CloseHandle(hCmdFile);

	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESTDHANDLES;
	si.hStdOutput = hFile;
	si.hStdInput = hFile;
	si.hStdError = hFile;

	bCreated = CreateProcess(NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, π);
	if( bCreated==FALSE )
	{
		printf("CreateProcess failed\n");
		return FALSE;
	}
	WaitForSingleObject(pi.hProcess, INFINITE);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);  
	CloseHandle(hFile);

	HANDLE hReadCmdFile = CreateFile(szCmdOut, GENERIC_READ, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	dwSize=GetFileSize(hReadCmdFile,NULL);
	
	*lpszBuffer = new char[dwSize];
	memset(*lpszBuffer, 0, dwSize);
	DWORD dwRead = 0;
	ReadFile(hReadCmdFile,*lpszBuffer,dwSize,&dwRead,NULL);
	CloseHandle(hReadCmdFile);

	DeleteFile(szCmd);
	DeleteFile(szCmdOut);

	return TRUE;
}

 
© 2001 Christophe Pichaud. All rights reserved.