Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The most convenient way to show a process tree with windows

6 views
Skip to first unread message

Bonita Montero

unread,
Nov 19, 2022, 6:05:34 AM11/19/22
to
Unfortunately lambdas couldn't be recursive without some tricks.

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <compare>
#include <functional>
#include <sstream>

#if defined(_MSC_VER)
#pragma warning(disable: 6319) // comma-statement with unused return-value
#endif

using namespace std;

using XHANDLE = unique_ptr<void, decltype([]( void *h ) { h&& h !=
INVALID_HANDLE_VALUE && CloseHandle( h ); }) > ;

int main( int argc, char ** )
{
try
{
auto throwSysErr = []( char const *what ) { throw system_error(
GetLastError(), system_category(), what ); };
XHANDLE xhSnapshot( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) );
xhSnapshot.get() == INVALID_HANDLE_VALUE // MSVC-bug with if in this case
&& (throwSysErr( "can't create toolhelp snapshot" ), 123 );
struct pe_t;
using process_vec = vector<pe_t>;
using process_it = vector<pe_t>::iterator;
struct pe_t
{
PROCESSENTRY32W pe;
bool root;
process_it pFirstChild, pNextChild;
};
PROCESSENTRY32W pe;
pe.dwSize = sizeof pe;
if( !Process32FirstW( xhSnapshot.get(), &pe ) )
throwSysErr( "can't enumerate processes" );
process_vec processes;
do
processes.emplace_back( pe, true, process_it(), process_it() ),
pe.dwSize = sizeof pe;
while( Process32NextW( xhSnapshot.get(), &pe ) );
if( GetLastError() != ERROR_NO_MORE_FILES )
throwSysErr( "can't enumerate processes" );
xhSnapshot.reset();
using proces_it_vec = vector<process_it>;
using process_itit = proces_it_vec::iterator;
proces_it_vec pProcesses( processes.size() );
for( size_t i = processes.size(); i--; pProcesses[i] =
processes.begin() + i );
bool sortProcessName = argc > 1;
sort( pProcesses.begin(), pProcesses.end(),
[&]( process_it pLeft, process_it pRight ) -> bool
{
DWORD
dwLeftParent = pLeft->pe.th32ParentProcessID,
dwRightParent = pRight->pe.th32ParentProcessID;
if( dwLeftParent < dwRightParent )
return true;
if( dwLeftParent > dwRightParent )
return false;
if( !sortProcessName )
return pLeft->pe.th32ProcessID < pRight->pe.th32ProcessID;
else
return _wcsicmp( pLeft->pe.szExeFile, pRight->pe.szExeFile ) < 0;
} );
for( process_it pProcess : pProcesses )
{
DWORD dwPpId = pProcess->pe.th32ProcessID;
process_itit ppChild = lower_bound( pProcesses.begin(),
pProcesses.end(), dwPpId,
[]( process_it pChildProcess, DWORD dwPpId )
{
DWORD dwChildPpId = pChildProcess->pe.th32ParentProcessID;
return dwChildPpId < dwPpId
|| dwChildPpId == dwPpId && !pChildProcess->pe.th32ProcessID;
} );
process_it pChild;
if( ppChild == pProcesses.end()
|| (pChild = *ppChild)->pe.th32ParentProcessID != dwPpId )
{
pProcess->pFirstChild = processes.end();
continue;
}
pProcess->pFirstChild = pChild;
for( ; ; )
{
pChild->root = false;
process_itit ppNextChild = ppChild + 1;
process_it pNextChild;
if( ppNextChild == pProcesses.end()
|| (pNextChild = *ppNextChild)->pe.th32ParentProcessID != dwPpId )
{
pChild->pNextChild = processes.end();
break;
}
pChild->pNextChild = pNextChild;
ppChild = ppNextChild;
pChild = *ppChild;
}
}
function<void ( process_it )> fnRecurse;
wstring strIndent;
wostringstream woss;
process_it pEnd = processes.end();
size_t n = 0;
auto recurse = [&]( process_it pFirst )
{
woss << strIndent;
pe_t &process = *pFirst;
woss << L"\"" << process.pe.szExeFile << " (" <<
process.pe.th32ProcessID << ")" << endl;
process_it pSibling = process.pFirstChild;
if( pSibling == processes.end() )
return;
strIndent.push_back( L'\t' );
do
fnRecurse( pSibling );
while( (pSibling = pSibling->pNextChild) != pEnd );
strIndent.pop_back();
};
fnRecurse = recurse;
for( process_it pProcess = processes.begin(); pProcess != pEnd;
++pProcess )
if( pProcess->root )
recurse( pProcess );
wcout << woss.str() << endl;
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}

Bonita Montero

unread,
Nov 19, 2022, 6:35:37 AM11/19/22
to
I found a trick to nearly have recursive lambdas:

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <compare>
#include <functional>
#include <sstream>

#if defined(_MSC_VER)
#pragma warning(disable: 6319) // comma-statement with unused return-value
#endif

using namespace std;

using XHANDLE = unique_ptr<void, decltype([]( void *h ) { h&& h !=
INVALID_HANDLE_VALUE && CloseHandle( h ); }) > ;

template<typename Self, typename ... Args >
void selfHelper( Self &&self, Args &&... args )
{
self( self, forward<Args>( args ) ... );
}

int main( int argc, char ** )
{
try
{
auto throwSysErr = []( char const *what ) { throw system_error(
GetLastError(), system_category(), what ); };
XHANDLE xhSnapshot( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) );
xhSnapshot.get() == INVALID_HANDLE_VALUE // MSVC-bug with if in this case
&& (throwSysErr( "can't create toolhelp snapshot" ), 123 );
struct pe_t;
using process_vec = vector<pe_t>;
using process_it = vector<pe_t>::iterator;
struct pe_t
{
PROCESSENTRY32W pe;
bool root;
process_it pFirstChild, pNextSibling;
process_itit ppSibling = lower_bound( pProcesses.begin(),
pProcesses.end(), dwPpId,
[]( process_it pChildProcess, DWORD dwPpId )
{
DWORD dwChildPpId = pChildProcess->pe.th32ParentProcessID;
return dwChildPpId < dwPpId
|| dwChildPpId == dwPpId && !pChildProcess->pe.th32ProcessID;
} );
process_it pSibling;
if( ppSibling == pProcesses.end()
|| (pSibling = *ppSibling)->pe.th32ParentProcessID != dwPpId )
{
pProcess->pFirstChild = processes.end();
continue;
}
pProcess->pFirstChild = pSibling;
for( ; ; )
{
pSibling->root = false;
process_itit ppNextSibling = ppSibling + 1;
process_it pNextSibling;
if( ppNextSibling == pProcesses.end()
|| (pNextSibling = *ppNextSibling)->pe.th32ParentProcessID != dwPpId )
{
pSibling->pNextSibling = processes.end();
break;
}
pSibling->pNextSibling = pNextSibling;
ppSibling = ppNextSibling;
pSibling = *ppSibling;
}
}
wstring strIndent;
wostringstream woss;
process_it pEnd = processes.end();
size_t n = 0;
for( process_it pProcess = processes.begin(); pProcess != pEnd;
++pProcess )
if( pProcess->root )
selfHelper( [&]( auto &&self, process_it pFirst )
{
woss << strIndent;
pe_t &process = *pFirst;
woss << L"\"" << process.pe.szExeFile << " (" <<
process.pe.th32ProcessID << ")" << endl;
process_it pSibling = process.pFirstChild;
if( pSibling == processes.end() )
return;
strIndent.push_back( L'\t' );
do
self( self, pSibling );
while( (pSibling = pSibling->pNextSibling) != pEnd );
strIndent.pop_back();
}, pProcess );
0 new messages