Click here to Skip to main content
15,499,289 members
Articles / Programming Languages / C++
Posted 15 Dec 2002


76 bookmarked

How to kill a process given a name

Rate me:
Please Sign up or sign in to vote.
4.55/5 (34 votes)
15 Dec 20023 min read
Shows how to kill a process given only a process name, and how to make it work for all Windows OS's (except 3.1)


The idea is to create a class that will kill a process given the process name, and work on every single Windows platform (except 3.1), without requiring additional redistributable components. So the tricky part here isn't actually killing the process (there's a great KB article on how to do this correctly.) The problem is that you need a PID to do that, and you don't have that intrinsically, given only a name. So the trick is now how to enumerate the processes, get the PID, and not require any additional components while we're at it.

This is actually easier than it seems, because all Windows except NT4 have ToolHelp32 API which accomplishes just that goal. NT4, however, is a pain in the behind, because it does have PSAPI to do this also, but it comes on a redistributable dll, which means additional installation hassles. So I looked on Google, and found Alex Fedotov's terrific article, which lists five different ways to skin a rabb.. er, I mean enumerate a process. Method 3 was the one I needed, so I filched it, and used it in my code. Method 3 involves ZwQuerySystemInformation, an undocumented NT API that's available for NT4, 2000, and onward.

At this point, you might go over to Google (or to NT4 DDK), discover that function, and also discover that Win2K has different internal structures used with this function than NT4. That's ok, because we don't use this on Win2K, or anything else besides NT4. Basically the idea is we try to load ToolHelp32 functions first, and only if that fails (which automatically means we're on NT4) do we try to use the Zw function.

Anyway, without further ado, here's the code. By the way, I tested it on 98, ME, NT4, 2k, and XP, different language versions too, and all seemed to work just fine. Share and enjoy. :)


I hope you'll forgive me for the laziness, but I didn't feel like making a sample project for such a small application. Really, I've written no new code here, just packaged Alex's, moliate's and Microsoft's code a little bit better. So here it is:

#include <tlhelp32.h>
// Some definitions from NTDDK and other sources

typedef LONG    NTSTATUS;
typedef LONG    KPRIORITY;

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)


#define SystemProcessesAndThreadsInformation    5

typedef struct _CLIENT_ID {
    DWORD        UniqueProcess;
    DWORD        UniqueThread;

typedef struct _UNICODE_STRING {
    USHORT        Length;
    USHORT        MaximumLength;
    PWSTR        Buffer;

typedef struct _VM_COUNTERS {
    SIZE_T        PeakVirtualSize;
    SIZE_T        VirtualSize;
    ULONG        PageFaultCount;
    SIZE_T        PeakWorkingSetSize;
    SIZE_T        WorkingSetSize;
    SIZE_T        QuotaPeakPagedPoolUsage;
    SIZE_T        QuotaPagedPoolUsage;
    SIZE_T        QuotaPeakNonPagedPoolUsage;
    SIZE_T        QuotaNonPagedPoolUsage;
    SIZE_T        PagefileUsage;
    SIZE_T        PeakPagefileUsage;

typedef struct _SYSTEM_THREADS {
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG            WaitTime;
    PVOID            StartAddress;
    CLIENT_ID        ClientId;
    KPRIORITY        Priority;
    KPRIORITY        BasePriority;
    ULONG            ContextSwitchCount;
    LONG            State;
    LONG            WaitReason;

// Note that the size of the SYSTEM_PROCESSES structure is 
// different on NT 4 and Win2K, but we don't care about it, 
// since we don't access neither IoCounters member nor 
//Threads array

typedef struct _SYSTEM_PROCESSES {
    ULONG            NextEntryDelta;
    ULONG            ThreadCount;
    ULONG            Reserved1[6];
    LARGE_INTEGER   CreateTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   KernelTime;
    UNICODE_STRING  ProcessName;
    KPRIORITY        BasePriority;
    ULONG            ProcessId;
    ULONG            InheritedFromProcessId;
    ULONG            HandleCount;
    ULONG            Reserved2[2];
    VM_COUNTERS        VmCounters;
#if _WIN32_WINNT >= 0x500
    IO_COUNTERS        IoCounters;
    SYSTEM_THREADS  Threads[1];

class CKillProcess
    //Functions loaded from Kernel32
    typedef HANDLE (WINAPI *PFCreateToolhelp32Snapshot)(
        DWORD dwFlags,       
        DWORD th32ProcessID  

    typedef BOOL (WINAPI *PFProcess32First)(
        HANDLE hSnapshot,      
        LPPROCESSENTRY32 lppe  

    typedef BOOL (WINAPI *PFProcess32Next)(
        HANDLE hSnapshot,      
        LPPROCESSENTRY32 lppe  

    // Native NT API Definitions
    typedef NTSTATUS (WINAPI * PFZwQuerySystemInformation)
    typedef HANDLE (WINAPI* PFGetProcessHeap)(VOID);
    typedef LPVOID (WINAPI* PFHeapAlloc)
    CKillProcessHelper() : FCreateToolhelp32Snapshot(NULL), 
        FProcess32First(NULL), FProcess32Next(NULL), 
        m_hKernelLib = ::LoadLibraryA("Kernel32");
        if (m_hKernelLib)  
            // Find ToolHelp functions
            FCreateToolhelp32Snapshot = 
            FProcess32First = (PFProcess32First)
            FProcess32Next = (PFProcess32Next)
        if(!FCreateToolhelp32Snapshot || 
            !FProcess32First || !FProcess32Next)
        { // i.e. we couldn't find the ToolHelp functions, 
            //so we must be on NT4. Let's load the
            // undocumented one instead.
                return; // can't do anything at all without 
            //the kernel.

            m_hNTLib = ::LoadLibraryA("ntdll.dll");
                FQuerySysInfo = 
                // load some support funcs from the kernel
                FGetProcessHeap = (PFGetProcessHeap)
                FHeapAlloc = (PFHeapAlloc)
                FHeapFree = (PFHeapFree)
    bool KillProcess(IN const char* pstrProcessName)
        DWORD dwId;
        HANDLE hProcess = FindProcess(pstrProcessName, 
        BOOL bResult;
            return false;

        // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
        // matches your process's.
            (LPARAM) dwId);
        // Wait on the handle. If it signals, great. 
        //If it times out, then you kill it.
        if(WaitForSingleObject(hProcess, 5000)
            bResult = TerminateProcess(hProcess,0);
            bResult = TRUE; 
        return bResult == TRUE;
    HANDLE FindProcess(IN const char* pstrProcessName,
        OUT DWORD& dwId)
            return NULL;

        if(FCreateToolhelp32Snapshot && FProcess32First && 
            FProcess32Next) // use toolhelpapi
            return THFindProcess(pstrProcessName, dwId);
        if(FQuerySysInfo && FHeapAlloc && 
            FGetProcessHeap && FHeapFree) // use NT api
            return NTFindProcess(pstrProcessName, dwId);
        // neither one got loaded. Strange.
        return NULL;
    HANDLE THFindProcess(IN const char* pstrProcessName, 
        OUT DWORD& dwId)
        HANDLE            hSnapShot=NULL;
        HANDLE            hResult = NULL;
        PROCESSENTRY32    processInfo;
        char*            pstrExeName;

        bool bFirst = true;
        ::ZeroMemory(&processInfo, sizeof(PROCESSENTRY32));
        processInfo.dwSize = sizeof(PROCESSENTRY32);
        hSnapShot = FCreateToolhelp32Snapshot(
            TH32CS_SNAPPROCESS, 0);
        if(hSnapShot == INVALID_HANDLE_VALUE)
            return NULL; 

        // ok now let's iterate with Process32Next until we 
        // match up the name of our process
        while((bFirst ? FProcess32First(hSnapShot, 
            &processInfo) : FProcess32Next(hSnapShot, 
            bFirst = false;
            // we need to check for path... and extract 
            // just the exe name
            pstrExeName = strrchr(processInfo.szExeFile, 
                pstrExeName = processInfo.szExeFile;
                pstrExeName++; // skip the \
            // ok now compare against our process name
            if(stricmp(pstrExeName, pstrProcessName) == 0) 
                // wee weee we found it
                // let's get a HANDLE on it
                dwId = processInfo.th32ProcessID;
        } // while(Process32Next(hSnapShot, &processInfo){
        return hResult;
    HANDLE NTFindProcess(IN const char* pstrProcessName, 
        OUT DWORD& dwId)
        HANDLE hHeap = FGetProcessHeap();
        NTSTATUS Status;
        ULONG cbBuffer = 0x8000;
        PVOID pBuffer = NULL;
        HANDLE hResult = NULL;
        // it is difficult to say a priory which size of 
        // the buffer will be enough to retrieve all 
        // information, so we startwith 32K buffer and 
        // increase its size until we get the
        // information successfully
            pBuffer = HeapAlloc(hHeap, 0, cbBuffer);
            if (pBuffer == NULL)
                return SetLastError(

            Status = FQuerySysInfo(
                pBuffer, cbBuffer, NULL);

            if (Status == STATUS_INFO_LENGTH_MISMATCH)
                HeapFree(hHeap, 0, pBuffer);
                cbBuffer *= 2;
            else if (!NT_SUCCESS(Status))
                HeapFree(hHeap, 0, pBuffer);
                return SetLastError(Status), NULL;
        while (Status == STATUS_INFO_LENGTH_MISMATCH);

        PSYSTEM_PROCESSES pProcesses = 

        for (;;)
            PCWSTR pszProcessName = 
            if (pszProcessName == NULL)
                pszProcessName = L"Idle";

            CHAR szProcessName[MAX_PATH];
            WideCharToMultiByte(CP_ACP, 0, pszProcessName, 
                -1,szProcessName, MAX_PATH, NULL, NULL);

            if(stricmp(szProcessName, pstrProcessName) 
                == 0) // found it
                dwId = pProcesses->ProcessId;

            if (pProcesses->NextEntryDelta == 0)

            // find the address of the next process 
            // structure
            pProcesses = (PSYSTEM_PROCESSES)(
                + pProcesses->NextEntryDelta);

        HeapFree(hHeap, 0, pBuffer);
        return hResult;
    // callback function for window enumeration
    static BOOL CALLBACK TerminateAppEnum( HWND hwnd, 
        LPARAM lParam )
        DWORD dwID ;

        GetWindowThreadProcessId(hwnd, &dwID) ;

        if(dwID == (DWORD)lParam)
            PostMessage(hwnd, WM_CLOSE, 0, 0) ;

        return TRUE ;
    HMODULE            m_hNTLib;
    HMODULE            m_hKernelLib;
    // ToolHelp related functions
    PFCreateToolhelp32Snapshot    FCreateToolhelp32Snapshot;
    PFProcess32First            FProcess32First;
    PFProcess32Next                FProcess32Next;
    // native NT api functions
    PFZwQuerySystemInformation    FQuerySysInfo;
    PFGetProcessHeap            FGetProcessHeap;
    PFHeapAlloc                    FHeapAlloc;
    PFHeapFree                    FHeapFree;


As I said before, this code is really a compilation of three different articles:

  • moliate's article on how to enumerate processes using ToolHelp API and PSAPI
  • Alex Fedotov's article on how to do the same, but with Zw-function
  • KB's article on how to terminate a process cleanly


(you knew it was coming...)

The code is completely, utterly, and absolutely free. Feel free to use it in private or commercial applications, modify it, sit on it, or print it out and use it for toilet paper. God knows I've ignored enough copyrights from CodeProject to have the nerve to make my own. :) One thing though -- if this code messes up your computer or puts your project seven months behind schedule, it's not my fault. None of it is my fault. Not even that "format c:" somewhere in there. Er, just kidding. :) Oh yeah, needless to say, you can't claim this code as your own. (I.E. I'd hate for someone to reprint this code, and copyright the hell out of it. Not sure if that's possible anyhow, but it would suck. Greatly.)


Probably a pointless thing to say, but if you're going to rate the article badly, at least take the time to write a comment saying how I could improve it, or what you find inadequate about it.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

GeneralTake a look on this Pin
varandas791-Mar-11 5:28
Membervarandas791-Mar-11 5:28 
GeneralMy vote of 1 Pin
varandas791-Mar-11 5:27
Membervarandas791-Mar-11 5:27 
GeneralThanks for the code Pin
beesol7-Oct-10 5:34
Memberbeesol7-Oct-10 5:34 
AnswerCompile errors Pin
Klaas11425-Aug-09 1:04
MemberKlaas11425-Aug-09 1:04 
GeneralMy vote of 2 Pin
Member 387671120-Aug-09 1:08
MemberMember 387671120-Aug-09 1:08 
GeneralFinally! Pin
Charlie Curtis14-Aug-09 11:13
MemberCharlie Curtis14-Aug-09 11:13 
QuestionTerminate a software by C++ programme ? Pin
phuocsangtn3-Jan-08 23:58
Memberphuocsangtn3-Jan-08 23:58 
AnswerRe: Terminate a software by C++ programme ? Pin
_Leo_18-Feb-08 2:58
Member_Leo_18-Feb-08 2:58 
Generala simple way:tskill.exe which is a standard windows tools located in windows\system32\ Pin
xwp29-Sep-07 4:49
Memberxwp29-Sep-07 4:49 
GeneralUbsolutely not compileable!!! Pin
Vitaly Tomilov22-Feb-07 2:51
MemberVitaly Tomilov22-Feb-07 2:51 
GeneralRe: Ubsolutely not compileable!!! [modified] Pin
rvangaal16-Mar-07 3:16
Memberrvangaal16-Mar-07 3:16 
GeneralRe: Ubsolutely not compileable!!! Pin
nova-22-Jul-07 17:38
Membernova-22-Jul-07 17:38 
GeneralRe: Ubsolutely not compileable!!! Pin
mimosa14-May-08 9:40
Membermimosa14-May-08 9:40 
Generalthe solution is usefull but could not compile in Borland C++ Builder Pin
Ali ISIKLI16-Nov-06 9:08
MemberAli ISIKLI16-Nov-06 9:08 
GeneralRe: the solution is usefull but could not compile in Borland C++ Builder Pin
nova-5-Dec-06 10:44
Membernova-5-Dec-06 10:44 
Generalthanks! very useful indeed Pin
-=Seph=-2-Aug-06 23:07
Member-=Seph=-2-Aug-06 23:07 
QuestionUNICODE version ?? Pin
hw7704119-Jul-06 4:54
Memberhw7704119-Jul-06 4:54 
AnswerRe: UNICODE version ?? Pin
Javier Tapia28-Apr-08 2:19
MemberJavier Tapia28-Apr-08 2:19 
AnswerRe: UNICODE version ?? Pin
hw7704128-Apr-08 4:54
Memberhw7704128-Apr-08 4:54 
Generalinside zip, ready for compiling (updated link) Pin
nova-20-Jun-06 18:40
Membernova-20-Jun-06 18:40 
GeneralRe: inside zip, ready for compiling (updated link) Pin
beesol7-Oct-10 5:35
Memberbeesol7-Oct-10 5:35 
GeneralHas Anyone compile with _Unicode flag Pin
bachson18-May-06 1:19
Memberbachson18-May-06 1:19 
Generalkill process with given name.. Pin
memincanan2-Sep-05 0:44
Membermemincanan2-Sep-05 0:44 
Generalkill process with given name.. Pin
memincanan2-Sep-05 0:44
Membermemincanan2-Sep-05 0:44 
GeneralProblem In Killing DLLHOST.EXE Pin
Kourosh Nosrati28-Jul-05 1:53
professionalKourosh Nosrati28-Jul-05 1:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.