views:

4578

answers:

6

I'm trying to get the process handle of, say example.exe, so I can call TerminateProcess on it. How can I do this? Notice, it doesn't have a window so FindWindow won't work.

+1  A: 

Windows has several APIs for process enumeration - see http://msdn.microsoft.com/en-us/library/ms684865%28VS.85%29.aspx

anon
+2  A: 

Check out: MSDN Article

You can use GetModuleName (I think?) to get the name and check against that.

Lloyd
Most of the GetModuleName, QueryFullProcessImage name, etc., require a handle and thus won't be of much use.Toolhelp does return process name.
Michael
+1  A: 

OpenProcess Function

From MSDN:

To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege.

aJ
I don't have the pID, only the name.
Malfist
SeDebugPrivilege is most definitely not needed for processes that are running as you. If you have access to the process via it's ACL (which you generally do for processes you create at the same integrity level as your code), you do not need SeDebugPrivilege.From same MSDN page:If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the contents of the security descriptor.
Michael
Yeah, you need to get the Process ID first by iterating processes.
aJ
+2  A: 

There are two basic techniques. The first uses PSAPI; MSDN has an example that uses EnumProcesses, OpenProcess, EnumProcessModules, and GetModuleBaseName.

The other uses Toolhelp, which I prefer. Use CreateToolhelp32Snapshot to get a snapshot of the process list, walk over it with Process32First and Process32Next, which provides module name and process ID, until you find the one you want, and then call OpenProcess to get a handle.

Rob Kennedy
+1  A: 
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>

int main( int, char *[] ) {
    PROCESSENTRY32 entry;
    entry.dwFlags = sizeof( PROCESSENTRY32 );

    HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

    if ( Process32First( snapshot, &entry ) == TRUE ) {
     while ( Process32Next( snapshot, &entry ) == TRUE ) {
      if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {  
       HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, entry.th32ProcessID );

       // Do stuff..

       CloseHandle( hProcess );
      }
     }
    }

    CloseHandle( snapshot );

    return 0;
}

Also, if you'd like to use PROCESS_ALL_ACCESS in OpenProcess, you could try this:

#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>

void EnableDebugPriv() {
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );

    LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );

    CloseHandle( hToken ); 
}

int main( int, char *[] ) {
    PROCESSENTRY32 entry;
    entry.dwFlags = sizeof( PROCESSENTRY32 );

    HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

    if ( Process32First( snapshot, &entry ) == TRUE ) {
     while ( Process32Next( snapshot, &entry ) == TRUE ) {
      if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {  
       EnableDebugPriv();

       HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID );

       // Do stuff..

       CloseHandle( hProcess );
      }
     }
    }

    CloseHandle( snapshot );

    return 0;
}
kitchen
You code will skip the first process in the system (however, first process is most likely "SYSTEM" so no user-visible bug.)
Michael
The first process is SYSTEM, so it's fine (I literally took that code straight from one of my projects) ;)
kitchen
When I attempt to act on the hProcess I get error code 6 which is ERROR_INVALID_HANDLE
Malfist
That would be because PROCESS_ALL_ACCESS is denied...
Malfist
change it to: HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION + PROCESS_VM_READ + PROCESS_TERMINATE, FALSE, entry.th32ProcessID ); and I'll give you the answer
Malfist
Changed it for you, and any future readers!
kitchen
Updated it with a way to (maybe) let you open the process with PROCESS_ALL_ACCESS.
kitchen
Shouldn't you use stricmp instead of strcmp. I could imagine that you're executable may end up as "TARGET.EXE" or even worse after been copied around in some unusual way.
rstevens
(char *)entry.szExeFile
Nick Brooks
entry.dwFlags = sizeof( PROCESSENTRY32 ); <-- errr, shouldn't this be dwSize, not dwFlags?
CyberShadow
That last comment is correct, the code sample won't run as it stands.
Dan Mitchell
Does `EnableDebugPriv()` really need to be inside the loop?
Daniel Stutzbach
+1  A: 

The following code shows how you can use toolhelp and OpenProcess to get a handle to the process. Error handling removed for brevity.

HANDLE GetProcessByName(PCWSTR name)
{
    DWORD pid = 0;

    // Create toolhelp snapshot.
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);

    // Walkthrough all processes.
    if (Process32First(snapshot, &process))
    {
        do
        {
            // Compare process.szExeFile based on format of name, i.e., trim file path
            // trim .exe if necessary, etc.
            if (MatchProcessName(process.szExeFile, name)
            {
               pid = process.th32ProcessID;
               break;
            }
        } while Process32Next(snapshot, &process);
    }

    CloseHandle(snapshot);

    if (pid != 0)
    {
         return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    }

    // Not found


       return NULL;
}
Michael