C++ iterate processes and find out command line args of each process - c++

I have the following problem to solve (VS2012, C++)
I have to find out if a specific HTA app is running from my exe. For that, I have to find the process mshta and check if it has correct arguments (should have been started as "mshta somehta.hta"). My first attempt was to iterate over the processes/modules, which I can do now. I see mshta listed and its PID. But, I did not find the way to get the info, how it was started. Is there a way to do it?
ProcessExists(wchar_t* processName)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return false;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessNameAndID( aProcesses[i] );
}
}
return false;
}
void PrintProcessNameAndID( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
dprintf( TEXT("%s (PID: %u) %s %s\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}

I ended up to use the solution proposed here: http://www.codeproject.com/Articles/19685/Get-Process-Info-with-NtQueryInformationProcess

Related

windows EnumProcesses some process names as <unknown>

Hello I have this sample code running which uses x to print processNames and PIDS of all currently running processes. Only some of them display an actual name though, with others displaying as (as seen in my output image below)
I was wondering if this was expected behavior, and that not all processes have a name (I could see this being the case for minimal background processes), or if I was using the EnumProcesses function incorrectly.
My code is:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <tchar.h>
//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
void PrintProcessNameAndID( DWORD processID ){
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
// Get the process name.
if (NULL != hProcess ){
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ){
GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
_tprintf( TEXT("%s (PID: %u)\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
int main( void ){
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ){
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
//for ( i = 0; i < cProcesses; i++ ){
for ( i = 0; i < 3; i++ ){
if( aProcesses[i] != 0 ) {
_tprintf( TEXT("aProcesses[%u] = %u (process ID)\n"), i, aProcesses[i] );
PrintProcessNameAndID( aProcesses[i] );
ListProcessThreads( aProcesses[i] );
}
}
return 0;
}
As stated in documentation, OpenProcess fails for idle and CSRSS processes.
If the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
You have to enable SeDebugPrivilege (and also run your application with admin privileges). Moreover, if your application is compiled as 32-bit, it cannot access 64-bit processes with OpenProcess
If you just want a list of running processes, use CreateToolhelp32Snapshot to list running processes.
#define UNICODE
#include <Windows.h>
#include <stdio.h>
#include <psapi.h>
#include <tlhelp32.h>
int main()
{
wprintf(L"Start:\n");
HANDLE hndl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPMODULE, 0);
if(hndl)
{
PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) };
Process32First(hndl, &process);
do
{
wprintf(L"%8u, %s\n", process.th32ProcessID, process.szExeFile);
} while(Process32Next(hndl, &process));
CloseHandle(hndl);
}
}
Side note, it is recommended to compile the program as Unicode. Avoid _txxx macros such as _tprintf etc.

GetProcessMemoryInfo failed with error 6 Handle is invalid

I'm trying to get the list of processes running in the system using C++. I use the functions available in the Windows API (like OpenProcess & CreateToolhelp32Snapshot ) to get it done.
The problem is that the code works fine for most of the processes, but couldn't get the memory info for crucial system processes alone, I have given the seDebugPrivilege also and have run the program as administrator only.
I get the output like
File Name PID Memory Used
winlogon.exe 1248 2432 KB
fontdrvhost.exe 1308
WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)
dwm.exe 1384
WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)
svchost.exe 1448 4744 KB
My code is :
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
HANDLE hToken;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
PROCESS_MEMORY_COUNTERS pmc;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
char err[]="CreateToolhelp32Snapshot (of processes)";
printError( err );
return( FALSE );
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
char err[]="Process32First";
printError( err ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return FALSE;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
char err[]="OpenThreadToken";
printError( err );
return FALSE;
}
}
else
return FALSE;
}
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);
do
{
printf( "%-25s", pe32.szExeFile );
dwPriorityClass = 0;
SIZE_T dwMin, dwMax;
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION , FALSE, pe32.th32ProcessID );
printf("%-10d", pe32.th32ProcessID );
if(GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc)))
{
printf( "%-10d KB", pmc.PagefileUsage/1024);
} else{
char err[]="GetProcessMemoryInfo";
printError( err );
}
printf("\n");
CloseHandle(hProcess);
}while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
To get this code to work, you have to change:
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE)
to:
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)
As others have commented, to get this code to work properly, you have to:
check for and report all possible error conditions
release all resources when you are done, in this case release hToken (via CloseHandle()) and call revertToSelf() if needs be.
Other than that, it's a decent effort so thumbs up for that.
Link to SetPrivilege(), in case any future visitor needs it:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619.aspx
Happy hacking.

Kill a process with its processID

I'm trying to display all the running process along with their memory usage and provide a kill option, i've used the OpenProcess method to get the memory used by the current process. How do I kill a process with a processID?
Here is the code:
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
HANDLE hToken;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
PROCESS_MEMORY_COUNTERS pmc;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return FALSE;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
printError( TEXT("OpenThreadToken") );
return FALSE;
}
}
else
return FALSE;
}
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);
do
{
printf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
dwPriorityClass = 0;
SIZE_T dwMin, dwMax;
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION , FALSE, pe32.th32ProcessID );
if(GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc)))
{
printf( "\nPagefileUsage: %d KB", pmc.PagefileUsage/1024);
} else{
printError( TEXT("GetProcessMemoryInfo") );
}
CloseHandle(hProcess);
}while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
Since you have an hProcess to hand, you can just use that:
BOOL ok = TerminateProcess (hProcess, exit_code);
Where exit_code can be anything you like (try to make it meaningful, in case anything is waiting on the process and would like to know why it exited).
If you don't want to do it that way, you can use OpenProcess:
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE, FALSE, process_id);
if (hProcess)
{
BOOL ok = TerminateProcess (hProcess, exit_code);
CloseHandle (hProcess);
}
else
{
DWORD err = GetLastError ();
...
}
You need to check that OpenProcess() succeeded because (amongst other things), you might not have sufficient access rights, and you need to close hProcess after you're done with it, even though you've killed the process itself.
Documentation for TerminateProcess() here.

QT Windows GUI - How Open a instance only once per time without qtsingleapplication

I am developing an application in QT for Windows and I have the following problem:
1. Some users are opening multiple instances of the same application, which is not allowed.
How can I control that each user only opens the application once, without using qtsingleapplication?
A quick and a dirty way to do it would be to create a lock file. If the lock file exists and the process is active, the new instance will quit. A crude and unchecked example is given below.
bool isProcessRunning( DWORD processID, std::string processName) {
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
// Get the process name.
if ( NULL != hProcess ) {
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
}
// Compare process name with your string
bool matchFound = !_tcscmp(szProcessName, processName.c_str() );
// Release the handle to the process.
CloseHandle( hProcess );
return matchFound;
};
void lockApp() {
/*
*
* lockApp() -> None
*
* Lock app to one instance
*
* #return None
*
*/
/* Flags */
int pid = -1;
bool procRunning = true;
/* App Lock file: Name and Location */
QString lockFile = QDir::temp().filePath( "MyAppName.lock" );
// check for the lock file and see if its stale.
if ( QFileInfo( lockFile ).exists() ) {
// OK, lock exists. Now, check if it is stale!
QFile pidFile( lockFile );
pidFile.open( QFile::ReadOnly );
pid = pidFile.readAll().toInt();
pidFile.close();
// if /proc/pid doesnot exist, we have a stale lock
if( isProcessRunning( pid, "MyAppName" ) ) {
procRunning = false;
QFile::remove( lockFile );
}
}
else {
procRunning = false;
}
if ( procRunning ) {
qApp->quit();
exit( 0 );
}
QFile pidFile( lockFile );
pidFile.open( QFile::WriteOnly );
pidFile.write( qPrintable( QString::number( qApp->applicationPid() ) ) );
pidFile.close();
};
The first function was taken from here. https://stackoverflow.com/a/13635127/1233513

Get process memory information

I've been trying to get process memory information in windows, and I've been following Microsoft docs and I've got this code but it
doesn't seem to work. It is supposed to print succeeded, but it doesn't print anything at all. My debugging tells me its because hProcess = null,
but i don't understand why. Here is my current code
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include<iostream>
using namespace std;
int main()
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
for (int i = 0; i < cProcesses; i++ )
{
int processID = aProcesses[i];
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
if (NULL == hProcess)
return 2;
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
cout<<"SUCCEEDED";
}
CloseHandle( hProcess );
}
return 0;
}
You probably don't have permission to read memory of certain (privileged system) processes. Check GetLastError if you get a NULL handle back from OpenProcess.
In general checking and handling Win32 error conditions is a good practice, even if the API 'usually' works for you.