실행 중인 프로세스를 외부에서 강제로 종료하는 API 함수인 TerminateProcess를
함부로 사용하기를 권장하지않는데 그이유는 이렇게 강제로 종료할 경우 링크된 DLL의
리소스가 제대로 반환되지 않아서 문제가 발생할 수 있다는 것이다.
하지만 아래와 같이 보다 안전하게 강제 종료할 수 있는 방법이 있다.
원리는 Kernel32.dll에 있는 ExitProcess라는 함수에 대한 포인터를 얻고 그것을 CreateRemoteThread를
이용해서 호출하여 그 프로세스가 스스로 죽는 효과를 만들어 내는 것이다.
사용사 주의 할 것은 CreateRemoteThread 함수가 Win9X에서는 지원되지 않는다는 것이다.
아래 예제는 explorer.exe를 강제로 종료하고 다시 시작하는 코드입니다.
win32 콘솔 프로그램이고 유니코드로 컴파일 하면 됩니다.
#include "stdafx.h"
#include "windows.h"
#include "Tlhelp32.h"
#include "Psapi.h"
HANDLE GetProcessList(LPCTSTR szFilename)
{
HANDLE hProcessSnapshot;
HANDLE hProcess;
PROCESSENTRY32 pe32;
hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
if (hProcessSnapshot == INVALID_HANDLE_VALUE)
return INVALID_HANDLE_VALUE;
pe32.dwSize = sizeof(PROCESSENTRY32);
Process32First(hProcessSnapshot, &pe32);
do
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);
if (hProcess != NULL)
{
if (_tcscmp(pe32.szExeFile, szFilename) ==0)
{
wprintf(L"Process ID of %s : %d\n", pe32.szExeFile, pe32.th32ProcessID);
return hProcess;
}
}
} while(Process32Next(hProcessSnapshot, &pe32));
return INVALID_HANDLE_VALUE;
}
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
DWORD dwTID, dwCode, dwErr = 0;
HANDLE hProcessDup = INVALID_HANDLE_VALUE;
HANDLE hRT = NULL;
HINSTANCE hKernel = GetModuleHandle(L"Kernel32");
BOOL bSuccess = FALSE;
BOOL bDup = DuplicateHandle(GetCurrentProcess(),
hProcess,
GetCurrentProcess(),
&hProcessDup,
PROCESS_ALL_ACCESS,
FALSE,
0);
if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode)
&& (dwCode == STILL_ACTIVE) )
{
FARPROC pfnExitProc;
pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)pfnExitProc,
(PVOID)uExitCode, 0, &dwTID);
if ( hRT == NULL ) dwErr = GetLastError();
}
else
{
dwErr = ERROR_PROCESS_ABORTED;
}
if ( hRT )
{
WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
CloseHandle(hRT);
bSuccess = TRUE;
}
if ( bDup )
CloseHandle(hProcessDup);
if ( !bSuccess )
SetLastError(dwErr);
return bSuccess;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
WCHAR szExplorer[MAX_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(szExplorer, sizeof(szExplorer));
ZeroMemory( &si, sizeof( si ) );
ZeroMemory( &pi, sizeof( pi ) );
si.cb = sizeof( si );
hProcess = GetProcessList(L"explorer.exe");
if (hProcess != INVALID_HANDLE_VALUE)
{
GetModuleFileNameEx(hProcess, NULL, szExplorer, MAX_PATH);
}
else
{
_tcscpy(szExplorer, L"c:\\windows\\explorer.exe");
}
wprintf(L"Terminating %s...\n", szExplorer);
if (hProcess != INVALID_HANDLE_VALUE)
{
if (SafeTerminateProcess(hProcess, 1))
wprintf(L"Terminated %s.\n", szExplorer);
}
if (CreateProcessW( szExplorer, szExplorer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
wprintf(L"Running %s...\n", szExplorer);
//getchar();
return 0;
}