[Suggestion] Updating GetTargetProcessIdFromProcname

On viernes, 28 de enero de 2011 0 comentarios

There's a flaw in the current function that if the process name is not found, the last process that was checked id is returned. To fix this, I suggest the following update:

Code:
/*
Required Header Files:
   #include
   #include
   #include
*/

unsigned long GetTargetProcessIdFromProcname(const char *process)
{
   PROCESSENTRY32 pe = {0};
   HANDLE thSnapshot = {0};
   BOOL retval = false;

   // Try to create a toolhelp snapshot and verify that it was actually created
   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(thSnapshot == INVALID_HANDLE_VALUE)
   {
      MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "Loader", MB_ICONERROR);
      return 0;
   }

   // Need to have this set for the WinAPI structures
   pe.dwSize = sizeof(PROCESSENTRY32);

   // Try to get the first process
    retval = Process32First(thSnapshot, &pe);

   // While we have processes to go through
   while(retval)
   {
      // As soon as we find the process id, return it
      if(StrStrI(pe.szExeFile, process))
      {
         return pe.th32ProcessID;
      }

      // Otherwise, get try to get the next process
      retval = Process32Next(thSnapshot,&pe);
   }

   // If we get here, no process ID was found, so return no
   // process ID instead of the last process found.
   return 0;
}


That way, a check against 0 can stop improper modifications of the wrong process.

----

Next, this is a function not directed at you since this is trivia stuff for you, but just anyone else who is running into problems with multiple instances of a process.

Take for example if you had 5 notepads open, each time you ran the function, you would only get one of those instances and it would be the same one until that particular instance closed.

A little function based on GetTargetProcessIdFromProcname can be constructed to store all process entries in a vector, to which you process each one of those IDs. As a result, you can act on all instances of a process name and not just one.

Code:
/*
Required Header Files:
   #include
   #include
   #include
        #include
*/
std::vector GetProcessListByName(const char *process)
{
   PROCESSENTRY32 pe = {0};
   HANDLE thSnapshot = {0};
   BOOL retval = false;
   std::vector processList;

   // Try to create a toolhelp snapshot and verify that it was actually created
   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(thSnapshot == INVALID_HANDLE_VALUE)
   {
      MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "Loader", MB_ICONERROR);
      // (Vector is empty)
      return processList;
   }

   // Need to have this set for the WinAPI structures
   pe.dwSize = sizeof(PROCESSENTRY32);

   // Try to get the first process
    retval = Process32First(thSnapshot, &pe);

   // While we have processes to go through
   while(retval)
   {
      // As soon as we find the process id, add it to the vector
      if(StrStrI(pe.szExeFile, process))
      {
         processList.push_back(pe);
      }

      // Otherwise, get try to get the next process
      retval = Process32Next(thSnapshot,&pe);
   }

   // Return the list of processes with this name
   return processList;
}


Take note in this next example if no processes are found, the code that uses the process ids is never executed! So, it all works as it should.

Example Usage:
Code:
std::vector ids = GetProcessListByName("notepad.exe");
for(int x = 0; x < ids.size(); ++x)
{
   ULONG id = ids[x].th32ProcessID;

   //
   // Do what you normally do on 'id' now
   //
}


Most of the time all you need is the ID, but why not return the entire vector of all instances in case you need something else ;)

0 comentarios:

Publicar un comentario