class Files_start_Dlg : public CDialog

{



//...





public:



	///////////////////////////////////////////////////////////////////////////////////////

	// это две возможности получить ProcessID: какую использовать - каждый решает сам:

	///////////////////////////////////////////////////////////////////////////////////////



	// возвращает ID процесса

	static bool getProcessId ( const char *pProgrName_in, DWORD *pth32ProcessID_out, bool bWithTraces = true );

	// возвращает ID процесса и ID thread-a

	static bool GetProcessByExeName ( CString& ExeName, DWORD& dwThreadId, DWORD& dProcId );



	//------------------------------

	// разные возможности убить запущенный процесс



	//используется taskkill.exe

	static void KillProcess_taskkill(const char* const pExeName);



	//используется отправка сообщения WM_CLOSE главному окну процесса

	static void KillProcess_sendMsg ( CString& sProcessName);



	//вызовом TerminateProcess

	static void KillProcess_terminateProc ( const CString& sProcessName);



	//создать и тут же убить процесс (зачем - другое дело :) )

	static void KillProcess_createTerminateProc ( const CString& sProcessName);



	//запустить процесс и дождаться, пока он не завершится сам

	//(аналог "start /wait" из пакетного файла)

	static bool st_RunProcessAndWaitWhenDone( const char* szApplicationName, 

							const char* szCommandLine_i = 0,

							const char* szCurrentDirectory = 0, DWORD dwdTimeOut_i = -1 );



	//получить путь к system32 (со слешем на конце)

	static CString GetSystemPATH__();

	



};



// все перечисленные вызовы функций работают, просто

// соответственно в функции может использоваться только один из способов;-)

// поэтому остальные закомментированы

void Files_start_Dlg::OnExeStop() 

{

/*

	// так можно в одном процессе сначала стартовать, а затем убить другой процесс

	CString sProcessName1 ("E:\\irina\\fs.exe");

	KillProcess_createTerminateProc ( sProcessName1 );





	// так можно убить процесс, который был запущен из другого приложения

	// вариант 1:

	CString sProcessName_msg ( "FS" );

	KillProcess_terminateProc (sProcessName_msg);



	// вариант 2:

	CString sProcessName ( "FS" );

	KillProcess_sendMsg (sProcessName);

*/

	// вариант 3

	KillProcess_taskkill ( sProcessName );

}





/////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////

// варианты для kill process:

///////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////





///////////////////////////////////////////////////////////////

// с помощью taskkill.exe

///////////////////////////////////////////////////////////////

void Files_start_Dlg::KillProcess_taskkill(const char* const pExeName)

{

	DWORD dwThreadId, dProcId;

	CString ExeName = pExeName;

	if(!GetProcessByExeName ( ExeName, dwThreadId, dProcId ) ) return;



	HANDLE hpr=0;

	hpr=::OpenProcess ( PROCESS_TERMINATE, 0, dProcId );



	if( hpr )

	{

		CString txt, sTaskKill ("taskkill.exe");



		// не всегда taskkill.exe находится в C:\\windows\\system32, поэтому для гибкости 

		// нашей программы системный путь находим программным путем

		CString sSysPath = GetSystemPATH__();



		// убиваем сам процесс и все его Children-Процессы

		txt.Format( " /c %s\%s /pid %d /f /t",sSysPath, sTaskKill, dProcId );

		

		st_RunProcessAndWaitWhenDone(sSysPath + "cmd.exe", txt);



	}

	else

	{

		DWORD nErr = GetLastError();

	}



	::TerminateProcess(hpr,0);

	::CloseHandle(hpr);

	

	return;

}





////////////////////////////////////////

// kill a process with taskkill.exe

////////////////////////////////////////

bool Files_start_Dlg::st_RunProcessAndWaitWhenDone ( const char* szApplicationName,

													 const char* szCommandLine_i,

													 const char* szCurrentDirectory,

													 DWORD dwdTimeOut_i)

{



	STARTUPINFO	StartupInfo;

	PROCESS_INFORMATION ProcessInfo;

	DWORD dwRetValue;



	::memset ( &StartupInfo, 0, sizeof(StartupInfo) );

	StartupInfo.cb = sizeof ( StartupInfo );



	CString csCommandLine = szCommandLine_i; // это обязательно, иначе испортится содержимое строки szCommandLine_i!!! 

	if( !::CreateProcess(

		szApplicationName, (char*)(const char*)csCommandLine,

		0, 0, 0, NORMAL_PRIORITY_CLASS, 0, szCurrentDirectory,

		&StartupInfo, &ProcessInfo))

	{

		// oshibka - proverjaem

		DWORD dwdErr=GetLastError(); 

		return false;

	}

	else

	{

		::CloseHandle ( ProcessInfo.hThread );

		::WaitForSingleObject ( ProcessInfo.hProcess, dwdTimeOut_i );

		::GetExitCodeProcess ( ProcessInfo.hProcess, &dwRetValue );

		::CloseHandle ( ProcessInfo.hProcess);

	}

	return true;

}





///////////////////////////////////////////////////////////////

// terminate process. the process was created in other program

///////////////////////////////////////////////////////////////

void Files_start_Dlg::KillProcess_sendMsg ( CString& sProcessName)

{

	DWORD dwThreadId, dProcId; 

	CWnd* pWnd = FindWindow ( NULL, sProcessName);

	

	// ищем ID процесса

	GetProcessByExeName ( sProcessName, dwThreadId, dProcId );



	// получаем handle процесса

	HANDLE hProc = ::OpenProcess (PROCESS_ALL_ACCESS, false, dProcId);

	if ( hProc )

	{

		UINT uExitCode = NO_ERROR;



		// это не очень корректный способ завершения процесса

		//BOOL bIsTerminated = TerminateProcess (hProc, uExitCode );

		

		// поэтому так лучше (хотя в принципе оба имеют место быть)

		::SendMessage (pWnd->m_hWnd, WM_CLOSE, 0, 0); 



		CloseHandle (hProc);

	}

}







///////////////////////////////////////////////////////////////

// terminate process. the process was created in other program (application)

///////////////////////////////////////////////////////////////

void Files_start_Dlg::KillProcess_terminateProc ( const CString& sProcessName)

{

	DWORD nProcessId = 0;



	getProcessId ( "FS.exe", &nProcessId, false);



	HANDLE hProc = ::OpenProcess (PROCESS_ALL_ACCESS, false, nProcessId);

	if ( hProc )

	{

		UINT uExitCode = NO_ERROR;

		BOOL bIsTerminated = TerminateProcess (hProc, uExitCode );

		CloseHandle (hProc);

	}

}





/////////////////////////////////////////////////

// create and terminate process in one program

/////////////////////////////////////////////////

void Files_start_Dlg::KillProcess_createTerminateProc ( const CString& sProcessName)

{

	STARTUPINFO cif;

	ZeroMemory(&cif,sizeof(STARTUPINFO) );

	PROCESS_INFORMATION pi;



	if ( CreateProcess(sProcessName,NULL,NULL,NULL,FALSE,NULL,NULL,NULL,&cif,&pi) )

	{

		TerminateProcess(pi.hProcess,NO_ERROR); 

	}

}







CString Files_start_Dlg::GetSystemPATH__()

{

	CString result = "";

	int len = MAX_PATH + 1;

	char* chSys = new char [len];



	::memset( chSys, 0, len );



	if( !::GetSystemDirectory (chSys, len) ) return "";



	result = chSys;

	result += "\\";



	delete [] chSys;

	chSys=0;



	return result;

}





////////////////////////////////////////

// get process id and thread id

////////////////////////////////////////

bool Files_start_Dlg::GetProcessByExeName ( CString& ExeName, DWORD& dwThreadId, DWORD& dProcId )

{

	CWnd* pWnd = FindWindow ( NULL, ExeName);

	dwThreadId = GetWindowThreadProcessId (pWnd->m_hWnd, &dProcId);



	return true;

}









////////////////////////////////////////

// get process id (other way)

////////////////////////////////////////



// эта функция ищет не только process id, но и все его подмодули. А возвращает только processId ( она была просто быстро подогнана для этого примера )

// и еще - здесь закомментированы все вызовы GetDlgItem(), т.к. они не будут работать из-за отсутствия полного проекта с ресурсами.

bool Files_start_Dlg::getProcessId ( const char *pProgrName_in, DWORD *pth32ProcessID_out, 

									 bool bWithTraces )

{

    HANDLE         hProcessSnap = NULL; 

    BOOL           bRet      = FALSE; 

    PROCESSENTRY32 pe32      = {0}; 

    char           sBuf[10000], sText[10000] ;

    CString        sEditText = ""; 



    char buf[100];

    DWORD th32ProcessID = 0;

 

    //  Take a snapshot of all processes in the system. 

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 



    if (hProcessSnap == INVALID_HANDLE_VALUE) 

        return (FALSE); 

 

    //  Fill in the size of the structure before using it. 

    pe32.dwSize = sizeof(PROCESSENTRY32); 

 

    //  Walk the snapshot of the processes, and for each process, 

    //  display information. 

    if (Process32First(hProcessSnap, &pe32)) 

    { 

        //DWORD         dwPriorityClass; 

        BOOL          bGotModule = FALSE; 

        MODULEENTRY32 me32       = {0}; 

        HANDLE        hModSnap = NULL;



		//GUITHREADINFO guiThr   = {0};

        BOOL          bGotGuiThread = FALSE; 

        

        THREADENTRY32 thr32   = {0};

        HANDLE        hThrSnap = NULL;

        BOOL          bGotThread = FALSE; 



        do 

        { 

            strcpy(buf, pe32.szExeFile);

            th32ProcessID = pe32.th32ProcessID; 



			// test the name of the process

			if (0 == strcmp(buf, pProgrName_in))

			{

				// only for test!

				if ( bWithTraces )

				{

					sprintf(sBuf, "ProcessName = %s	processID = %d \r\n", buf, th32ProcessID);



					//GetDlgItem(IDC_PROC_LIST_LIST)->GetWindowText(sEditText);

					strcpy(sText, sEditText);

					strcat(sText, sBuf);



					//GetDlgItem(IDC_PROC_LIST_LIST)->SetWindowText(sText); 

				}



				*pth32ProcessID_out = th32ProcessID;

                

				// only for test !

				if ( bWithTraces )

				{

					// hold all modules (dlls usw.)

					hModSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID); 

					me32.dwSize = sizeof(MODULEENTRY32); 

					bGotModule = Module32First(hModSnap, &me32);

					while (bGotModule)

					{

						bGotModule = Module32Next(hModSnap, &me32);

					}



					// hold all threads

					hThrSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pe32.th32ProcessID); 

					thr32.dwSize = sizeof(THREADENTRY32); 

					bGotThread = Thread32First(hThrSnap, &thr32);

	//                bGotGuiThread = GetGUIThreadInfo(thr32.th32ThreadID, &guiThr);

                

					while (bGotThread)

					{

						bGotThread = Thread32Next(hThrSnap, &thr32);

					}

				}	//if ( bWithTraces )



				break;

			}

            else

            {

				// only for test !

				if ( bWithTraces )

				{

					sprintf(sBuf, "ProcessName = %s	\r\n  ", buf);

					//GetDlgItem(IDC_PROC_LIST_LIST)->GetWindowText(sEditText);

					strcpy(sText, sEditText);

					strcat(sText, sBuf);



					//GetDlgItem(IDC_PROC_LIST_LIST)->SetWindowText(sText);

				}



        