개발/VC++

[스크랩] MFC 프로세스 실행, 프로세스 죽이기, 죽인 프로세스 PID

99iberty 2021. 7. 19. 23:29

https://ychcom.tistory.com/entry/MFC-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8B%A4%ED%96%89-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%A3%BD%EC%9D%B4%EA%B8%B0-%EC%A3%BD%EC%9D%B8-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-PID

 

MFC 프로세스 실행, 프로세스 죽이기, 죽인 프로세스 PID

typedef struct _STARTUPINFO { DWORD cb; // 구조체의 변수의 크기(byte)를 전달 LPTSTR lpReserved; // LPTSTR lpDesktop; // 어플리케이션 동작시 바탕화면 이름 대체(NULL이면 현재 데스크탑) LPTSTR lpTitle;..

ychcom.tistory.com

 

typedef struct _STARTUPINFO {
  DWORD  cb;						// 구조체의 변수의 크기(byte)를 전달
  LPTSTR lpReserved;				// 
  LPTSTR lpDesktop;					// 어플리케이션 동작시 바탕화면 이름 대체(NULL이면 현재 데스크탑)
  LPTSTR lpTitle;					// 타이틀 바 제목 (NULL이면 프로세스의 파일명이 타이틀이 됨)
  DWORD  dwX;						// 시작될 프로세스 윈도우 x좌표
  DWORD  dwY;						// 시작될 프로세스 윈도우 y좌표
  DWORD  dwXSize;					/* 윈도우 가로 길이, 세로 길이
  DWORD  dwYSize;					 지정하지 않으면 CW_USEDEFAULT로 실행 */
  DWORD  dwXCountChars;				/* 콘솔 어플리케이션이 실행 중이다가 자식프로세스 생성시
  DWORD  dwYCountChars;				자식 프로세스 x,y 너비를 지정*/
  DWORD  dwFillAttribute;			// 백그라운드 색깔 설정
  DWORD  dwFlags;					// 실행될 프로세스에 지정할 플래그
/*
 STARTF_FORCEONFEEDBACK : 프로세스 수행 상태에 따라 마우스 커서 변경
 STARTF_FORCEOFFEEDBACK : 프로세스가 실행되고 2초동안 마우스 커서가 모래시계(?) 상태
 STARTF_PREVENTPINNING : 작업 표시줄에 표시되지 않는 프로세스 생성
 STARTF_RUNFULLSCREEN : 전체화면으로 시작
 STARTF_TITLEISAPPID : lpTitle 파라미터의 값이 작업표시줄과 시작 메뉴의 이름이 됨
 + STARTF_TITLEISLINKNAME과 같이 사용될 수 없음
 STARTF_TITLEISLINKNAME : lpTitle 파라미터(프로세스 이름)가 단축 아이콘의 이름이 됨
 + STARTF_TITLEISAPPID와 같이 사용될 수 없음
 STARTF_USECOUNTCHARS : dwXCountChars, dwYCountChars 파라미터를 사용
 STARTF_USEPOSITION : dwX, dwY 파라미터를 사용
 STARTF_USEFILLATTRIBUTE : dwFillAttributes 파라미터를 사용
 STARTF_USEHOTKEY : hStdInput 파라미터를 사용
 + STARTF_USESTDHANDLES와 같이 사용될 수 없음
 STARTF_USESHOWWINDOW : wShowWindow 파라미터를 사용
 - STARTF_USESIZE : dwXSize, dwYSize 파라미터를 사용
 - STARTF_USESTDHANDLES : hStdInput, hStdOutput, hStdError 파라미터를 사용
 + STARTF_USEHOTKEY와 같이 사용될 수 없음
  */
  WORD   wShowWindow;				// CUI인지 혹은 GUI인지 설정
  WORD   cbReserved2;				// 0으로 초기화해서 사용(사용되지 않음)
  LPBYTE lpReserved2;				// NULL초기화 (사용되지 않음)
  HANDLE hStdInput;					// 콘솔 입출력에 사용할 버퍼 핸들
  HANDLE hStdOutput;				// 키보드 입력 버퍼
  HANDLE hStdError;					// 윈도우 화면 출력 버퍼
} STARTUPINFO, *LPSTARTUPINFO;

 

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;						// 프로세스 핸들
  HANDLE hThread;						// 쓰레드 핸들
  DWORD  dwProcessId;					// 프로세스 id
  DWORD  dwThreadId;					// 쓰레드 id
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

 

/*
Process A                     ------->             Process B
(부모 프로세스)           CreateProcess        (자식 프로세스)
*/
BOOL CreateProcess(
    LPCTSTR lpApplicationName,    				// 생성될 프로세스의 이름
    LPTSTR lpCommandLine,         				// 생성될 프로세스에 인자 전달(변수만 가능)
    LPSECURITY_ATTRIBUTES lpProcessAttributes, 	// 프로세스의 보안 속성 지정
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 쓰레드의 보안 속성 지정
    BOOL bInheritHandles,                   	// TRUE : 부모 프로세스가 소유하는 상속 가능한 핸들을 상속한다.
    DWORD dwCreationFlags,              		// 생성하는 프로세스의 특성을 결정짓는 옵션(우선순위)
    LPVOID lpEnvironment,                  		// 생성하는 프로세스의 Environment Block 지정  NULL : 부모 프로세스의 환경 블록 복사                                                          
    LPCTSTR lpCurrentDirectory,          		// 생성하는 프로세스의 현재 디렉터리 설정  NULL : 부모 프로세스의 현재 디렉터리                                                        
    LPSTARTUPINFO lpStartupInfo,       			// STARTUPINFO 구조체 변수 초기화한 후  변수의 포인터를 인자로 전달                                                          
    LPPROCESS_INFORMATION lpProcessInformation 	//생성하는 프로세스의 정보를 얻기 위한 인자                                                     
                                              	//PROCESS_INFORMATION 구조체 변수의 주소값을 인자로 전달
);

 

BOOL CUtil::RunProcess(CString RunFilePath, int show)
{
	// STARTUPINFO 생성하는 프로세스의 속성을 지정할 때 사용하는 구조체
	STARTUPINFO si;
	// 새로 생선된 프로세스와 스레드 정보가 있음
	PROCESS_INFORMATION pi;
	si.cb				= sizeof(STARTUPINFO);
	si.lpReserved		= NULL;
	si.lpReserved2		= NULL;
	si.cbReserved2		= 0;
	si.lpDesktop		= NULL;
	si.lpTitle			= NULL;
	si.dwFlags			= STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
	si.dwX				= 0;
	si.dwY				= 0;
	si.dwFillAttribute	= 0;
	si.wShowWindow		= show;
	CreateProcess(NULL,RunFilePath.GetBuffer(0),NULL,NULL,TRUE, NULL,NULL,NULL,&si,&pi);
	// WaitForSingleObject(pi.hProcess, INFINITE);
    // 핸들 닫기
    CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return TRUE;
}​

 

 


// 시스템 주소 공간에 상주하는 프로세스 목록 스냅샷으로 가져올때 엔트리를 설명
typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;					// 구조체 크기(byte)
  DWORD     cntUsage;				// 사용안함 0으로 설정
  DWORD     th32ProcessID;			// 프로세스 ID
  ULONG_PTR th32DefaultHeapID;		// 사용안함 0으로 설정
  DWORD     th32ModuleID;			// 사용안함 0으로 설정
  DWORD     cntThreads;				// 프로세스가 시작한 스레드 실행 수
  DWORD     th32ParentProcessID;	// 프로세스(부모 프로세스)가 생성한 프로세스 ID
  LONG      pcPriClassBase;			// 프로세스가 생성한 모든 스레드 기본 우선순위
  DWORD     dwFlags;				// 사용안함 0으로 설정
  TCHAR     szExeFile[MAX_PATH];	// 프로세스 실행 파일 이름
} PROCESSENTRY32, *PPROCESSENTRY32;

 

HANDLE OpenProcess(
  DWORD dwDesiredAccess,	// 프로세스 접근 권한
  BOOL  bInheritHandle,		// True면 프로세스가 상속에 의해 프로세스 생성, False 상속 안함 
  DWORD dwProcessId			// 오픈할 로컬 프로세스 ID
);

 

프로세스 지정 접근 권한

의미
PROCESS_ALL_ACCESS 프로세스 오브젝트에 대한 모든 가능한 접근 권한
PROCESS_CREATE_PROCESS (0x0080) 프로세스를 생성하기 위해 필요
PROCESS_CREATE_THREAD (0x0002) 스레드를 생성하기 위해 필요
PROCESS_DUP_HANDLE (0x0040) DuplicateHandle을 사용하여 핸들을 복사하기 위해 필요
PROCESS_QUERY_INFORMATION (0x0400) (see OpenProcessToken). 토큰, 종료 코드 및 우선 순위 클래스와 같은 프로세스에 대한 특정 정보를 검색하는 데 필요함 
PROCESS_QUERY_LIMITED_INFORMATION(0x1000) (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName). 프로세스 특정 정보를 탐색시 필요
PROCESS_SET_INFORMATION (0x0200) (see SetPriorityClass). 우선순위 클래스와 같은 특정 프로세스 정보에 대한 설정시 필요
PROCESS_SET_QUOTA (0x0100) SetProcessWorkingSetSize. 사용 메모리 제한 설정시 필요
PROCESS_SUSPEND_RESUME (0x0800) 프로세스를 재시작하거나 일시정시 필요
PROCESS_TERMINATE (0x0001) TerminateProcess. 사용 프로세스 제거시 필요
PROCESS_VM_OPERATION (0x0008)  (see VirtualProtectEx and WriteProcessMemory). 프로세스 주소 공간에서 작동 수행 필요
PROCESS_VM_READ (0x0010) ReadProcessMemory.사용하는 프로세스에서 메모리르 읽기 필요
PROCESS_VM_WRITE (0x0020) WriteProcessMemory.사용하는 프로세스에서 메모리에 쓰기 필요
SYNCHRONIZE(0x00100000L) wait functions 를 사용하여 프로세스 종료를 기다리는데 필요

 

BOOL CUtil::KillProcess(CString ProcessName)
{
	BOOL b = FALSE;
	HANDLE   hSnapshot  = NULL;  
    PROCESSENTRY32 pe32 = {0};  
	// 시스템 프로세서의 상태(힙, 모듈, 스레드)를 읽어 온다.
	// 성공하면 스냅샷에 대한 핸들을 반환하고, 실패하면 INVALID_HANDLE_VALUE를 반환한다. 
    hSnapshot  = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );  
	// 엔트리 구조체 사이즈
    pe32.dwSize = sizeof( PROCESSENTRY32 );
	// 엔트리에서 구성된 자료구조 가져오기
    if( Process32First( hSnapshot , &pe32 ) )  
    {  
        do   
        {  
            // printf("%20s", pe32.szExeFile);  
			if(ProcessName.Compare(pe32.szExeFile) == 0)
			// if(strcmp(pe32.szExeFile, ProcessName) == 0)
			{
				b = TRUE;
				printf("Process Found = %20s !!!\n", pe32.szExeFile);  
				//AfxMessageBox("Found Process");
				HANDLE hProcess = OpenProcess( PROCESS_TERMINATE , FALSE, pe32.th32ProcessID );
				if( hProcess )
				{
					DWORD dwExitCode;
                    /* 	BOOL WINAPI GetExitCodeProcess
						( _In_  HANDLE  hProcess, _Out_ LPDWORD lpExitCode )
					hProcess : 종료 코드를 받기 원하는 프로세스의 핸들
                    PROCESS_QUERY_INFORMATION 또는 PROCESS_QUERY_LIMITED_INFORMATION
					권한이 있어야 함.
                    lpExitCode : 프로세스 종료 상태를 받을 변수에 대한 포인터
                    실패시 0을 반환*/
					GetExitCodeProcess( hProcess, &dwExitCode);
                    /* BOOL WINAPI TerminateProcess
					(_In_ HANDLE hProcess, _In_ uExitCode)
                    hProcess : 종료할 프로세스의 핸들을 설정
                    핸들의 접근 권한은 반드시 PROCESS_TERMINATE를 가져야 함.
                    uExitCode : 프로세스 종료 코드를 설정
                    통상적으로 정상 종료 인경우 0을 비정상 종료인경우 -1을 입력*/
					TerminateProcess( hProcess, dwExitCode);
					CloseHandle(hProcess);
					//return TRUE;
				}
			}
        } while ( Process32Next( hSnapshot , &pe32 ) );  
    }  
    else  
    {  
        printf("???\n");
    }  
    CloseHandle (hSnapshot ); 
	return b;
}

TerminateProcess 함수는

Jeffery Richter 의 Programming Application for Win2k나 기타
이와 관련된 책에서는 되도록 쓰지 말도록 권고하고 있는데
리소스가 정리되지 않고 바로 죽기 때문이다. 

그래서 ExitProcess라는 함수를 사용해서 
그프로세스가 스스로 죽도록 해야한다. 

BOOL CUtil::KillProcessPid(int pid)
{
	BOOL b = FALSE;
	HANDLE   hSnapshot  = NULL;  
    PROCESSENTRY32 pe32 = {0};  
    hSnapshot  = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );  
    pe32.dwSize = sizeof( PROCESSENTRY32 );  
    if( Process32First( hSnapshot , &pe32 ) )  
    {  
        do   
        {  
            //printf("%20s", pe32.szExeFile);  
			if(pe32.th32ProcessID == pid)
//            if(strcmp(pe32.szExeFile, ProcessName) == 0)
			{
				b = TRUE;
				printf("Process Found = %20s !!!\n", pe32.szExeFile);  
				//AfxMessageBox("Found Process");
				HANDLE hProcess = OpenProcess( PROCESS_TERMINATE , FALSE, pe32.th32ProcessID );
				if( hProcess )
				{
					DWORD dwExitCode;
					GetExitCodeProcess( hProcess, &dwExitCode);
					TerminateProcess( hProcess, dwExitCode);
					CloseHandle(hProcess);
					//return TRUE;
				}
			}
        } while ( Process32Next( hSnapshot , &pe32 ) );  
    }  
    else  
    {  
        printf("???\n");
    }  
    CloseHandle (hSnapshot ); 
	return b;
}

 

// 프로세스 이름으로 PID 찾기 
int CUtil::GetStatusProcess(char *pName)
{
	int Pid  = 0;
	BOOL b = FALSE;
	HANDLE   hProcess = NULL;  
    PROCESSENTRY32 pe32 = {0};  
    hProcess = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );  
    pe32.dwSize = sizeof( PROCESSENTRY32 ); 
    // 시스템 스냅샷에 처음 발생한 프로세스에 대한 정보 검색
    if( Process32First( hProcess, &pe32 ) )  
    {  
        do   
        {  
            printf("%20s", pe32.szExeFile);  
            if(strcmp(pe32.szExeFile, pName) == 0)
			{
				b = TRUE;
				printf("Process Found = %20s !!!", pe32.szExeFile);  
				Pid = pe32.th32ProcessID;
				break;
				//AfxMessageBox("Found Process");
			}
        } while ( Process32Next( hProcess, &pe32 ) );  
    }  
    else  
    {  
        printf("???\n");
    }  
    CloseHandle (hProcess); 
	return Pid;
}

 

 

 

 

 

'개발 > VC++' 카테고리의 다른 글

[스크랩] C++ 커널 오브젝트 타입/네임 구하기  (0) 2021.07.19
[스크랩] Kernel object 와 오브젝트 핸  (0) 2021.07.19
[스크랩] 쓰레드란?  (0) 2021.07.07
[스크랩] C++ 스레드 thread  (0) 2021.06.29
MFC 흐름도  (0) 2015.03.25