Skip to content

Instantly share code, notes, and snippets.

@mmlac
Last active August 5, 2023 14:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmlac/67eb02b60bd0b8682c08dc61fab065f2 to your computer and use it in GitHub Desktop.
Save mmlac/67eb02b60bd0b8682c08dc61fab065f2 to your computer and use it in GitHub Desktop.
[C++ & C# Examples] Getting the existing processes running on the system and their modules - Written & Tested in VS2015
Getting the existing processes running on the system and their modules (in this case filtered by whether they load a
DirectX or OpenGL library).
-- ALL this code is heavily heavily copied together from answers on StackOverflow and other parts of the internet.
Because I probably went through a thousand tabs while looking up tons of minor things
(I have never coded C# before and never touched the Win API) I don't have all the sources. :(
I still want to aggregate my results here for others to benefit from.
NOTE!!! WMI & PrintProcesses will only see 32bit when running as 32bit and 64bit when running 64bit.
Might be able to fix as well with flags. See revision on how I got the flags to work in C++ and PInvoke solution.
Written & Tested in VS2015 on Win10 64bit - YMMV on other OSes, architectures and compilers.
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <list>
#include <algorithm>
#include <string>
#include <cctype>
#include <sstream>
#include <iostream>
/// Try to find in the Haystack the Needle - ignore case
bool findStringIC(const std::wstring & strHaystack, const std::wstring & strNeedle)
{
auto it = std::search(
strHaystack.begin(), strHaystack.end(),
strNeedle.begin(), strNeedle.end(),
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }
);
return (it != strHaystack.end());
}
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
int PrintModules(DWORD processID)
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
// Print the process identifier.
//printf("\n\"Process ID: %u\":[\n", processID);
// Get a handle to the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID);
if (NULL == hProcess) {
return 1;
}
WCHAR procWChar[MAX_PATH];
DWORD namelen = GetProcessImageFileName(hProcess, procWChar, sizeof(procWChar) / sizeof(*procWChar));
if (0 == namelen)
{
printf("Name was empty, skipping....");
return 1;
}
std::wstring procName = std::wstring(procWChar);
size_t lastPath = procName.find_last_of(L"\\");
procName = procName.substr(lastPath + 1, procName.length() - lastPath - 1);
// Get a list of all the modules in this process.
if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL))
{
std::wstringstream modsString;
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
// Get the full path to the module's file.
if (GetModuleFileNameEx(hProcess, hMods[i], szModName,
sizeof(szModName) / sizeof(TCHAR)))
{
std::wstring modName = std::wstring((WCHAR *)szModName);
if (findStringIC(modName, L"d3d") || findStringIC(modName, L"opengl"))
{
if (0 != i)
modsString << L" ,";
modsString << modName;
}
// Print the module name and handle value.
//if(0 != i) printf(",");
//_tprintf(TEXT("\"\t%s (0x%08X)\"\n"), szModName, hMods[i]);
}
}
if (modsString.rdbuf()->in_avail() != 0)
std::wcout << L"Process: " << procName << L": " << modsString.str() << std::endl;
}
// Release the handle to the process.
CloseHandle(hProcess);
return 0;
}
int main(void)
{
DWORD aProcesses[1024];
DWORD cbNeeded;
DWORD cProcesses;
unsigned int i;
// Get the list of process identifiers.
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return 1;
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the names of the modules for each process.
for (i = 0; i < cProcesses; i++)
{
PrintModules(aProcesses[i]);
}
return 0;
}
// MOSTLY THE ORIGINAL BELOW:
//
//#include "stdafx.h"
//#include <windows.h>
//#include <tchar.h>
//#include <stdio.h>
//#include <psapi.h>
//
//// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
//// and compile with -DPSAPI_VERSION=1
//
//int PrintModules(DWORD processID)
//{
// HMODULE hMods[1024];
// HANDLE hProcess;
// DWORD cbNeeded;
// unsigned int i;
//
// // Print the process identifier.
//
// printf("\n\"Process ID: %u\":[\n", processID);
//
// // Get a handle to the process.
//
// hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
// PROCESS_VM_READ,
// FALSE, processID);
// if (NULL == hProcess) {
// printf("]");
// return 1;
// }
//
// // Get a list of all the modules in this process.
//
// if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
// {
//
// for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
// {
// TCHAR szModName[MAX_PATH];
//
// // Get the full path to the module's file.
//
// if (GetModuleFileNameEx(hProcess, hMods[i], szModName,
// sizeof(szModName) / sizeof(TCHAR)))
// {
// // Print the module name and handle value.
// if (0 != i) printf(",");
// _tprintf(TEXT("\"\t%s (0x%08X)\"\n"), szModName, hMods[i]);
// }
// }
//
// }
//
//
//
// // Release the handle to the process.
//
// CloseHandle(hProcess);
//
// return 0;
//}
//
//int main(void)
//{
//
// DWORD aProcesses[1024];
// DWORD cbNeeded;
// DWORD cProcesses;
// unsigned int i;
//
// // Get the list of process identifiers.
//
// if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
// return 1;
//
// // Calculate how many process identifiers were returned.
//
// cProcesses = cbNeeded / sizeof(DWORD);
//
// // Print the names of the modules for each process.
// printf("{");
// for (i = 0; i < cProcesses; i++)
// {
// if (0 != i) printf(",");
// PrintModules(aProcesses[i]);
// }
// printf("}");
//
// return 0;
//}
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;
namespace Test
{
class Program
{
[DllImport("psapi")]
private static extern bool EnumProcesses(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] UInt32[] processIds,
UInt32 arraySizeBytes,
[MarshalAs(UnmanagedType.U4)] out UInt32 bytesCopied);
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModules(
IntPtr hProcess,
[Out] IntPtr lphModule,
UInt32 cb,
[MarshalAs(UnmanagedType.U4)] out UInt32 lpcbNeeded);
public enum DwFilterFlag : uint
{
LIST_MODULES_DEFAULT = 0x0, // This is the default one app would get without any flag.
LIST_MODULES_32BIT = 0x01, // list 32bit modules in the target process.
LIST_MODULES_64BIT = 0x02, // list all 64bit modules. 32bit exe will be stripped off.
LIST_MODULES_ALL = (LIST_MODULES_32BIT | LIST_MODULES_64BIT) // list all the modules
}
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModulesEx(
IntPtr hProcess,
[Out] IntPtr lphModule,
UInt32 cb,
[MarshalAs(UnmanagedType.U4)] out UInt32 lpcbNeeded,
DwFilterFlag dwff);
[DllImport("psapi.dll")]
static extern uint GetModuleFileNameEx(
IntPtr hProcess,
IntPtr hModule,
[Out] StringBuilder lpBaseName,
[In] [MarshalAs(UnmanagedType.U4)] int nSize);
[DllImport("psapi.dll")]
static extern uint GetProcessImageFileName(
IntPtr hProcess,
[Out] StringBuilder lpImageFileName,
[In] [MarshalAs(UnmanagedType.U4)] int nSize);
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
UInt32 processId
);
public static void Foo()
{
List<UInt32> procIds = Procs();
Console.WriteLine("Found {0} processes.", procIds.Count);
ProcModule(procIds);
}
private static List<UInt32> Procs()
{
List<UInt32> proclist = new List<UInt32>();
UInt32 arraySize = 120;
UInt32 arrayBytesSize = arraySize * sizeof(UInt32);
UInt32[] processIds = new UInt32[arraySize];
UInt32 bytesCopied;
bool success = EnumProcesses(processIds, arrayBytesSize, out bytesCopied);
Console.WriteLine("success={0}", success);
Console.WriteLine("bytesCopied={0}", bytesCopied);
if (!success)
{
Console.WriteLine("Boo!");
return proclist;
}
if (0 == bytesCopied)
{
Console.WriteLine("Nobody home!");
return proclist;
}
UInt32 numIdsCopied = bytesCopied >> 2; ;
if (0 != (bytesCopied & 3))
{
UInt32 partialDwordBytes = bytesCopied & 3;
Console.WriteLine("EnumProcesses copied {0} and {1}/4th DWORDS... Please ask it for the other {2}/4th DWORD",
numIdsCopied, partialDwordBytes, 4 - partialDwordBytes);
return proclist;
}
for (UInt32 index = 0; index < numIdsCopied; index++)
{
//Console.WriteLine("ProcessIds[{0}] = {1}", index, processIds[index]);
proclist.Add(processIds[index]);
}
return proclist;
}
private static void ProcModule(List<UInt32> procIds)
{
int _3dProcs = 0;
foreach (UInt32 pid in procIds)
{
List<String> modNames = new List<String>();
IntPtr procPtr = OpenProcess(ProcessAccessFlags.All, false, pid);
if( IntPtr.Zero == procPtr )
continue;
uint[] modsInt = new uint[1024];
// Setting up the variable for the second argument for EnumProcessModules
IntPtr[] hMods = new IntPtr[1024];
GCHandle gch = GCHandle.Alloc(hMods, GCHandleType.Pinned); // Don't forget to free this later
IntPtr pModules = gch.AddrOfPinnedObject();
// Setting up the rest of the parameters for EnumProcessModules
uint uiSize = (uint)(Marshal.SizeOf(typeof(IntPtr)) * (hMods.Length));
uint cbNeeded = 0;
if (EnumProcessModulesEx(procPtr, pModules, uiSize, out cbNeeded, DwFilterFlag.LIST_MODULES_ALL) == true)
{
Int32 uiTotalNumberofModules = (Int32)(cbNeeded / (Marshal.SizeOf(typeof(IntPtr))));
for (int i = 0; i < (int)uiTotalNumberofModules; i++)
{
StringBuilder strbld = new StringBuilder(1024);
GetModuleFileNameEx(procPtr, hMods[i], strbld, (int)(strbld.Capacity));
String module = strbld.ToString();
if( ContainsCaseInsensitive(module, "d3d") || ContainsCaseInsensitive(module, "opengl" ) )
modNames.Add(CutPath(module));
}
StringBuilder procName = new StringBuilder(2000);
GetProcessImageFileName(procPtr, procName, 2000);
if (modNames.Count > 0)
{
++_3dProcs;
Console.WriteLine("File: {0} Modules: {1}", CutPath(procName.ToString()), String.Join(",", modNames));
}
}
// Must free the GCHandle object
gch.Free();
}
Console.WriteLine("Processes with 3D modules loaded: {0}", _3dProcs);
}
private static bool ContainsCaseInsensitive(String paragraph, String word)
{
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
}
private static String CutPath(String path)
{
int last = path.LastIndexOf("\\");
return path.Substring(last + 1, path.Length- last - 1);
}
}
}
private void PrintProcesses()
{
List<String> printList = new List<String>();
Process[] localAll = Process.GetProcesses();
//Process[] localAll = { Process.GetProcessById(23268) };
/*TODO: This is filled on startup witheverything that has
the graphic libraries loaded and than track only what
is loaded afterwards. Maybe even do a 15sec wait
after startup to make sure everything has loaded.
Also allow to block these standard apps below. Run a
unique on the list after the initial parse.
*/
String[] ignoreProcessList = {
"GalaxyClient", "GalaxyClient Helper", "RzSynapse", "devenv",
"XDesProc", "GameOverlayUI", "Steam", "steamwebhelper",
"GameplayTimeTracker", "chrome", "firefox", "Dropbox",
"explorer", "CompanionApp", "procexp64", "notepad++",
"SkypeApp", "VeraCrypt", "SearchUI", "ShellExperienceHost",
"ScriptedSandbox64", "SetPoint", "SystemSettings",
"SkypeHost", "Microsoft.Photos", "UpdateChecker",
"ApplicationFrameHost"
};
foreach (Process p in localAll)
{
//printList.Add(String.Format("ID: {0} Name: {1}", p.Id, p.ProcessName));
if (false && ignoreProcessList.Contains(p.ProcessName))
continue;
try
{
List<String> moduleList = new List<String>();
ProcessModuleCollection pmc = p.Modules;
foreach (ProcessModule pm in pmc)
{
String name = pm.ModuleName;
//printList.Add(String.Format("{0} runs {1}", p.ProcessName, name));
if (ContainsCaseInsensitive(name, "d3d") || ContainsCaseInsensitive(name, "opengl"))
{
moduleList.Add(name);
}
}
if (moduleList.Count > 0)
printList.Add(String.Format("{0} is running {1}", p.ProcessName, String.Join(",", moduleList)));
}
catch (System.ComponentModel.Win32Exception e)
{
Console.WriteLine("W32 exception: {0} -> {1}", e.ErrorCode, e.Message);
}
catch (Exception e) { }
}
for (int i = 0; i < 10; ++i)
{
Console.WriteLine();
}
Console.WriteLine(printList.Count);
foreach (String line in printList)
{
Console.WriteLine(line);
}
}
private void UseWMIToGetProcesses()
{
HashSet<int> handle_list = new HashSet<int>();
string win32_proc_query_string = "select * from CIM_Process";
string cim_query_string = "select * from CIM_ProcessExecutable";
ManagementScope ms = new ManagementScope(@"\\localhost\root\cimv2", null);
ms.Connect();
if (ms.IsConnected)
{
ObjectQuery cim_query = new ObjectQuery(cim_query_string);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, cim_query))
{
using (ManagementObjectCollection searchResult = searcher.Get())
{
foreach (ManagementObject mo in searchResult)
{
if (ContainsCaseInsensitive(mo["Antecedent"] + "", "d3d") || ContainsCaseInsensitive((String)mo["Antecedent"], "opengl"))
{
//foreach (PropertyData pd in mo.Properties)
//{
// Console.WriteLine("{0}: {1} #### ", pd.Name, mo[pd.Name]);
//}
String dependent = (String)mo["Dependent"];
if (dependent.Contains("\""))
{
// Dependent of the form: \\<hostname>\root\cimv2:Win32_Process.Handle="23312"
int first_quot = dependent.IndexOf("\"");
int start = first_quot + 1; //skip the -"- itself
int end = dependent.Count() - 1;
int range = end - start;
String handle = dependent.Substring(start, range);
int handle_i;
if (Int32.TryParse(handle, out handle_i))
{
handle_list.Add(handle_i);
}
}
}
}
}
}
Console.WriteLine("Handles: {0}", String.Join(", ", handle_list));
//Console.WriteLine("Process count:{0}", process_count);
if (handle_list.Count > 0)
{
int cntr = 0;
StringBuilder sb = new StringBuilder(win32_proc_query_string);
sb.Append(" WHERE ");
bool first = true;
foreach (int h in handle_list)
{
if (first)
{
first = false;
}
else
{
sb.Append(" OR ");
}
sb.Append(String.Format("Handle = {0}", h));
}
Console.WriteLine("QUERY: {0}", sb.ToString());
ObjectQuery win32_proc_query = new ObjectQuery(sb.ToString());
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, win32_proc_query))
{
using (ManagementObjectCollection searchResult = searcher.Get())
{
foreach (ManagementObject mo in searchResult)
{
++cntr;
//foreach (PropertyData pd in mo.Properties)
//{
// Console.WriteLine("{0}: {1} #### ", pd.Name, mo[pd.Name]);
//}
Console.WriteLine("Cap: " + mo["Caption"] + " Desc: " + mo["Description"] + " ExecPath: " + mo["ExecutablePath"] + " CreatDate: " + mo["CreationDate"]);
}
}
}
Console.WriteLine("Counters: handle_list: {0} - cntr: {1}", handle_list.Count(), cntr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment