tomaschku
Goto Top

Status eines oder aller Prozesse herausfinden

Hallo alle zusammen!

Ich arbeite mit Visual Studio 2017 in C++ unter Windows 10.
Ich habe mir das Grundgerüst eines Programm geschrieben, aber da ich durch googeln nicht weiterkam, frage ich euch mal.

Nähmlich:
Ich würde gern wissen, welche(r) Prozess(e) diesen Status haben. (Mit "dieser" meine ich z.B.: Angehalten, Wird ausgeführt,...)

Als Beispiel:
Der Prozess ShellExperienceHost.exe ist immer gestartet unter dem Status "Angehalten", aber der Status ändert
sich zu "Wird ausgeführt", wenn man die Windowstaste drückt (Also das Menü aufpoppt).

Ich wäre froh, wenn es eine Möglichkeit gibt, von allen Prozessen die herauszupicken, die dem Status X entsprechen und dann z.B.: diese zu beenden oder anzuzeigen.
Aber ich kann auch, wie im Beispiel, einen Prozess auswählen und dessen Status überprüfen.

Wenn möglich würde ich gerne keine externen Dateien verwenden.

LG,
tomaschku

Content-ID: 356910

Url: https://administrator.de/contentid/356910

Ausgedruckt am: 21.11.2024 um 23:11 Uhr

134464
134464 03.12.2017 aktualisiert um 22:17:18 Uhr
Goto Top
Folgende Win32 Funktion sollte dir weiterhelfen

https://msdn.microsoft.com/en-us/library/windows/desktop/hh448381(v=vs.8 ...

Enthalten in "windows.h"

For-Schleife über alle Prozesse und Status checken.
rubberman
rubberman 04.12.2017 um 08:07:11 Uhr
Goto Top
Geht per NtQuerySystemInformation. Wie genau, muss ich mich auch erst einlesen. (Vielleicht habe ich heute Abend etwas Zeit.) Ganz so einfach wird das nicht, denn grundsätzlich kann ein Prozess bspw. nicht suspended sein, alle seine Threads aber shon, was dann zum Ergebnis hat dass der Prozess quasi "angehalten" ist. NtQuerySystemInformation liefert auch die Informationen zu den einzelnen Threads eines Prozesses, die Verarbeitung ist aber (wie immer bei der WinAPI) eher C-Style und nicht gerade schön...

Steffen
134464
134464 04.12.2017 um 12:49:08 Uhr
Goto Top
rubberman
rubberman 04.12.2017 um 12:55:18 Uhr
Goto Top
Den Thread hatte ich auch schon gefunden. Die "handgeschrieben" structs und enums sind aber falsch bzw. nicht up-to-date. Wie gesagt, ich werden da mal was draus machen ...

Steffen
tomaschku
tomaschku 04.12.2017 aktualisiert um 17:08:01 Uhr
Goto Top
Danke für die Rückmeldung!
Ich werde mir die Links mal anschauen und wenn ich die Lösung hab, stelle ich sie auch gleich rein.

P.S.: Ich nutze 64-Bit.

Gruß,
tomaschku
134464
134464 04.12.2017, aktualisiert am 05.12.2017 um 08:12:55 Uhr
Goto Top
Nur für die Powershell-Fraktion, ein Oneliner:
get-Process | select Name,@{n='State';e={$_.Threads.Threadstate | select -Unique}},@{n='Reason';e={$_.Threads.WaitReason | select -Unique}} | ?{$_.Name -ne 'System' -and $_.State -contains 'Wait' -and $_.Reason -contains 'Suspended'}  
rubberman
rubberman 04.12.2017, aktualisiert am 05.12.2017 um 16:24:47 Uhr
Goto Top
Schau mal ob das mit VS läuft. Konnte nur mit MinGW testen.
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>

#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif

#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600

#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS

#include <winternl.h>
#include <ntstatus.h>


struct proc_info
{
  std::wstring name;
  unsigned process_id;
  bool suspended;
};


using process_vector = std::vector<proc_info>;


struct process_state
{
  process_state();
  ~process_state() noexcept;

  void update();
  process_vector get_suspended() const;
  void print() const;

private:
  process_vector m_proc_infos;

  void get();
};


int main(int argc, char* argv)
{
  std::wcout << L"~~~~~~~~ All:\n";  
  process_state p_state;
  p_state.print();

  std::wcout << L"~~~~~~~~ Suspended:\n";  
  process_vector susp{p_state.get_suspended()};
  for (const auto& elem : susp)
    std::wcout << elem.name << L'\t' << elem.process_id << std::endl;  

  return 0;
}


typedef NTSTATUS (WINAPI *tNTQSI)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);

process_state::process_state()
{
  get();
}

process_state::~process_state() noexcept
{
}

void process_state::update()
{
  get();
}

process_vector process_state::get_suspended() const
{
  process_vector susp;
  for (const auto& elem : m_proc_infos)
  {
    if (elem.suspended)
      susp.push_back(elem);
  }
  return susp;
}

void process_state::print() const
{
  const std::ios_base::fmtflags former_flags{std::wcout.flags()};
  std::wcout << std::boolalpha;
  for (const auto& elem : m_proc_infos)
  {
    std::wcout << elem.name << L'\n'  
               << L"Process ID: " << elem.process_id << L'\n'  
               << L"Suspended:  " << elem.suspended << L'\n' << std::endl;  
  }
  std::wcout.flags(former_flags);
}

void process_state::get()
{
  m_proc_infos.clear();

  tNTQSI fpNTQSI{reinterpret_cast<tNTQSI>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"))};  

  if (fpNTQSI == NULL)
    throw std::runtime_error{"function NtQuerySystemInformation not found"};  

  HANDLE hHeap{GetProcessHeap()};
  ULONG cbBuffer{1048576UL};
  LPVOID pBuffer{};

  if ((pBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBuffer)) == NULL)
    throw std::runtime_error{"bad memory allocation"};  

  if (fpNTQSI(SystemProcessInformation, pBuffer, cbBuffer, &cbBuffer) == STATUS_INFO_LENGTH_MISMATCH)
  {
    HeapFree(hHeap, 0, pBuffer);
    throw std::runtime_error{"insufficient memory allocated"};  
  }

  PSYSTEM_PROCESS_INFORMATION pProc{reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(pBuffer)};

  for (;;)
  {
    if (reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId) > static_cast<ULONG_PTR>(4UL))
    {
      m_proc_infos.push_back({std::wstring{pProc->ImageName.Buffer, static_cast<size_t>(pProc->ImageName.Length)}.c_str(), static_cast<unsigned>(reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId)), false});

      PSYSTEM_THREADS pThreads{reinterpret_cast<PSYSTEM_THREADS>(pProc + 1)};
      for (ULONG i{}; i < pProc->NumberOfThreads; ++pThreads, ++i)
      {
        if (pThreads->State == StateWait && pThreads->WaitReason == Suspended)
        {
          m_proc_infos.back().suspended = true;
          break;
        }
      }
    }

    if (pProc->NextEntryOffset == 0UL)
      break;

    pProc = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>((reinterpret_cast<LPBYTE>(pProc)) + pProc->NextEntryOffset);
  }

  HeapFree(hHeap, 0, pBuffer);
}
Steffen

EDIT Update Type-Casts für 64Bit Prozessoren
tomaschku
tomaschku 05.12.2017 um 18:10:40 Uhr
Goto Top
Ich habe versucht, den Code zu kompilieren, habe aber folgende Fehler erhalten:

Nr.142   E0020   "PSYSTEM_THREADS" Bezeichner nicht definiert  
Nr.142   C2065   "PSYSTEM_THREADS" nichtdeklarierter Bezeichner  
Nr.142   C2146   "pThreads" Fehlendes Semicolon  
Nr.142   C2065   "pThreads" nichtdeklarierter Bezeichner  
Nr.142   C2061   "PSYSTEM_THREADS" Bezeichner  
Nr.143 & Nr.145   C2065   "pThreads" nichtdeklarierter Bezeichner  
Nr.145   C2227   "->State" und "->WaitReason" muss sich ein Zeiger auf Klassen-/Struktur-/... Typ befinden  
Nr.153   C2043   "break" Schlüsselwort ungültig //{} Bei If vergessen?  
Nr.158   C2065   "hHeap" und "pBuffer" nichtdeklarierter Bezeichner  
Nr.158   C4430   Fehlender Typspezifizirierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.  
Nr.158   C2365   "HeapFree" Erneute Definition; vorherige Definition war "Funktion". //Eig. ein Funktionsaufruf?  
Nr.159   C2059   "}" Syntaxfehler  
Nr.159   C2143   ";" vor "}" Syntaxfehler  

Trotzdem vielen Dank! face-smile
rubberman
Lösung rubberman 05.12.2017 aktualisiert um 23:31:13 Uhr
Goto Top
Hmm. Dann machen wir die Deklarationen eben wieder von Hand.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>

#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif

#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600

#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS

#include <ntstatus.h>


struct proc_info
{
  std::wstring name;
  unsigned process_id;
  bool suspended;
};


using process_vector = std::vector<proc_info>;


struct process_state
{
  process_state();
  ~process_state() noexcept;

  void update();
  process_vector get_suspended() const;
  void print() const;

private:
  process_vector m_proc_infos;

  void get();
};


int main(int argc, char* argv)
{
  std::wcout << L"~~~~~~~~ All:\n";  
  process_state p_state;
  p_state.print();

  std::wcout << L"~~~~~~~~ Suspended:\n";  
  process_vector susp{p_state.get_suspended()};
  for (const auto& elem : susp)
    std::wcout << elem.name << L'\t' << elem.process_id << std::endl;  

  return 0;
}


typedef enum _SYSTEM_INFORMATION_CLASS {
  SystemBasicInformation = 0,
  SystemProcessorInformation = 1,
  SystemPerformanceInformation = 2,
  SystemTimeOfDayInformation = 3,
  SystemProcessInformation = 5,
  SystemProcessorPerformanceInformation = 8,
  SystemHandleInformation = 16,
  SystemPagefileInformation = 18,
  SystemInterruptInformation = 23,
  SystemExceptionInformation = 33,
  SystemRegistryQuotaInformation = 37,
  SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;

typedef enum _THREAD_STATE {
  StateInitialized = 0,
  StateReady, StateRunning, StateStandby, StateTerminated,
  StateWait, StateTransition,
  StateUnknown
} THREAD_STATE;

typedef enum _KWAIT_REASON {
  Executive = 0,
  FreePage, PageIn, PoolAllocation, DelayExecution,
  Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn,
  WrPoolAllocation, WrDelayExecution, WrSuspended,
  WrUserRequest, WrEventPair, WrQueue, WrLpcReceive,
  WrLpcReply, WrVirtualMemory, WrPageOut, WrRendezvous,
  Spare2, Spare3, Spare4, Spare5, Spare6, WrKernel,
  MaximumWaitReason
} KWAIT_REASON;

typedef struct _UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
} UNICODE_STRING;

typedef LONG KPRIORITY;

typedef struct _VM_COUNTERS {
  SIZE_T PeakVirtualSize;
  SIZE_T VirtualSize;
  ULONG PageFaultCount;
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
} VM_COUNTERS, *PVM_COUNTERS;

typedef struct _CLIENT_ID {
  HANDLE UniqueProcess;
  HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef struct _SYSTEM_PROCESS_INFORMATION {
  ULONG NextEntryOffset;
  ULONG NumberOfThreads;
  LARGE_INTEGER Reserved[3];
  LARGE_INTEGER CreateTime;
  LARGE_INTEGER UserTime;
  LARGE_INTEGER KernelTime;
  UNICODE_STRING ImageName;
  KPRIORITY BasePriority;
  HANDLE UniqueProcessId;
  HANDLE InheritedFromUniqueProcessId;
  ULONG HandleCount;
  ULONG SessionId;
  ULONG PageDirectoryBase;
  VM_COUNTERS VirtualMemoryCounters;
  SIZE_T PrivatePageCount;
  IO_COUNTERS IoCounters;
} SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION;

typedef struct _SYSTEM_THREADS
{
  LARGE_INTEGER KernelTime;
  LARGE_INTEGER UserTime;
  LARGE_INTEGER CreateTime;
  ULONG WaitTime;
  PVOID StartAddress;
  CLIENT_ID ClientId;
  KPRIORITY Priority;
  KPRIORITY BasePriority;
  ULONG ContextSwitchCount;
  THREAD_STATE State;
  KWAIT_REASON WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;

typedef NTSTATUS (WINAPI *tNTQSI)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);

process_state::process_state()
{
  get();
}

process_state::~process_state() noexcept
{
}

void process_state::update()
{
  get();
}

process_vector process_state::get_suspended() const
{
  process_vector susp;
  for (const auto& elem : m_proc_infos)
  {
    if (elem.suspended)
      susp.push_back(elem);
  }
  return susp;
}

void process_state::print() const
{
  const std::ios_base::fmtflags former_flags{std::wcout.flags()};
  std::wcout << std::boolalpha;
  for (const auto& elem : m_proc_infos)
  {
    std::wcout << elem.name << L'\n'  
               << L"Process ID: " << elem.process_id << L'\n'  
               << L"Suspended:  " << elem.suspended << L'\n' << std::endl;  
  }
  std::wcout.flags(former_flags);
}

void process_state::get()
{
  m_proc_infos.clear();

  tNTQSI fpNTQSI{reinterpret_cast<tNTQSI>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"))};  

  if (fpNTQSI == NULL)
    throw std::runtime_error{"function NtQuerySystemInformation not found"};  

  HANDLE hHeap{GetProcessHeap()};
  ULONG cbBuffer{1048576UL};
  LPVOID pBuffer{};

  if ((pBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBuffer)) == NULL)
    throw std::runtime_error{"bad memory allocation"};  

  if (fpNTQSI(SystemProcessInformation, pBuffer, cbBuffer, &cbBuffer) == STATUS_INFO_LENGTH_MISMATCH)
  {
    HeapFree(hHeap, 0, pBuffer);
    throw std::runtime_error{"insufficient memory allocated"};  
  }

  PSYSTEM_PROCESS_INFORMATION pProc{reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(pBuffer)};

  for (;;)
  {
    if (reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId) > static_cast<ULONG_PTR>(4UL))
    {
      m_proc_infos.push_back({std::wstring{pProc->ImageName.Buffer, static_cast<size_t>(pProc->ImageName.Length)}.c_str(), static_cast<unsigned>(reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId)), false});

      PSYSTEM_THREADS pThreads{reinterpret_cast<PSYSTEM_THREADS>(pProc + 1)};
      for (ULONG i{}; i < pProc->NumberOfThreads; ++pThreads, ++i)
      {
        if (pThreads->State == StateWait && pThreads->WaitReason == Suspended)
        {
          m_proc_infos.back().suspended = true;
          break;
        }
      }
    }

    if (pProc->NextEntryOffset == 0UL)
      break;

    pProc = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>((reinterpret_cast<LPBYTE>(pProc)) + pProc->NextEntryOffset);
  }

  HeapFree(hHeap, 0, pBuffer);

  std::sort(m_proc_infos.begin(), m_proc_infos.end(), (const auto& a, const auto& b) { return lstrcmpiW(a.name.c_str(), b.name.c_str()) < 0; });
}
Steffen
tomaschku
tomaschku 06.12.2017 um 18:23:51 Uhr
Goto Top
Vielen Dank!!!
Diesmal hat es funktioniert.
Hat mir sehr geholfen! face-monkeyface-monkey

tomachku
rubberman
Lösung rubberman 06.12.2017 aktualisiert um 23:46:59 Uhr
Goto Top
(EDIT Während du geantwortet hast, war ich noch am Verfassen dieses Posts. Hoffe es hilft trotzdem noch ...)

Mittlerweile konnte ich auch mit VS testen. Rennt. Weil mein ...
Zitat von @rubberman:
... nicht gerade schön...
... von oben maßlos untertrieben war, macht es wohl Sinn den ganze WinAPI Mist auszulagern und ein bisschen Struktur rein zu bringen. Auf diese Weise wird dein Hauptcode wieder übersichtlich und du kannst dort sauberes C++ schreiben. Der unschöne Code ist dann in der Implementierung (was üblicherweise auch in anderen Bibliotheken der Fall ist). Die typedef enums und typedef structs in der Implementierung entstammen der winternl.h von mingw-w64 und sind ohne Copyright in der Public Domain veröffentlicht. Somit ist die Verwendung hier problemlos möglich.


process_state.h
#ifndef PROCESS_STATE_H_INCLUDED__
#define PROCESS_STATE_H_INCLUDED__

#include <string>
#include <vector>


// member type of the process_vector
struct proc_info
{
  std::wstring name;       // process name
  unsigned     process_id; // process ID
  bool         suspended;  // true if at least one of the threads of the process was suspended
};


using process_vector = std::vector<proc_info>;


struct process_state
{
  // constructor, during construction proc_info data of all currently running processes will be collected
  process_state();

  // destructor
  ~process_state() noexcept;

  // update proc_info data of all currently running processes
  void update();

  // return a copy of the collected data, sorted by name
  process_vector get_all() const;

  // return the collected data of all suspended processes, sorted by name
  process_vector get_suspended() const;

  // return the collected data of all not-suspended processes, sorted by name
  process_vector get_not_suspended() const;

  // return the collected data of all processes with the specified name (not case-sensitive)
  process_vector get_by_name(const std::wstring& name) const;

  // return the collected data of processes with with the specified name (not case-sensitive) in the specified vector
  process_vector get_by_name(const std::wstring& name, const process_vector& p_info) const;

  // return the collected data of all processes with the specified process ID
  process_vector get_by_id(const unsigned& process_id) const;

  // return the collected data of processes with the specified process ID in the specified vector
  process_vector get_by_id(const unsigned& process_id, const process_vector& p_info) const;

  // print the collected data, sorted by name
  void print() const;

  // print the collected data in the specified vector
  void print(const process_vector& p_info) const;

private:
  process_vector m_proc_infos;
  void get();
};


// terminate the process with the specified process ID
bool terminate_process(const unsigned& process_id);


#endif // PROCESS_STATE_H_INCLUDED__


process_state.cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include "process_state.h"  

#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif

#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600

#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS

#include <ntstatus.h>

typedef enum _SYSTEM_INFORMATION_CLASS
{
  SystemBasicInformation = 0,
  SystemProcessorInformation = 1,
  SystemPerformanceInformation = 2,
  SystemTimeOfDayInformation = 3,
  SystemProcessInformation = 5,
  SystemProcessorPerformanceInformation = 8,
  SystemHandleInformation = 16,
  SystemPagefileInformation = 18,
  SystemInterruptInformation = 23,
  SystemExceptionInformation = 33,
  SystemRegistryQuotaInformation = 37,
  SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;

typedef enum _THREAD_STATE
{
  StateInitialized = 0,
  StateReady, StateRunning, StateStandby, StateTerminated,
  StateWait, StateTransition,
  StateUnknown
} THREAD_STATE;

typedef enum _KWAIT_REASON
{
  Executive = 0,
  FreePage, PageIn, PoolAllocation, DelayExecution,
  Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn,
  WrPoolAllocation, WrDelayExecution, WrSuspended,
  WrUserRequest, WrEventPair, WrQueue, WrLpcReceive,
  WrLpcReply, WrVirtualMemory, WrPageOut, WrRendezvous,
  Spare2, Spare3, Spare4, Spare5, Spare6, WrKernel,
  MaximumWaitReason
} KWAIT_REASON;

typedef LONG KPRIORITY;

typedef struct _UNICODE_STRING
{
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
} UNICODE_STRING;

typedef struct _VM_COUNTERS
{
  SIZE_T PeakVirtualSize;
  SIZE_T VirtualSize;
  ULONG PageFaultCount;
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
} VM_COUNTERS, *PVM_COUNTERS;

typedef struct _CLIENT_ID
{
  HANDLE UniqueProcess;
  HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef struct _SYSTEM_PROCESS_INFORMATION
{
  ULONG NextEntryOffset;
  ULONG NumberOfThreads;
  LARGE_INTEGER Reserved[3];
  LARGE_INTEGER CreateTime;
  LARGE_INTEGER UserTime;
  LARGE_INTEGER KernelTime;
  UNICODE_STRING ImageName;
  KPRIORITY BasePriority;
  HANDLE UniqueProcessId;
  HANDLE InheritedFromUniqueProcessId;
  ULONG HandleCount;
  ULONG SessionId;
  ULONG PageDirectoryBase;
  VM_COUNTERS VirtualMemoryCounters;
  SIZE_T PrivatePageCount;
  IO_COUNTERS IoCounters;
} SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION;

typedef struct _SYSTEM_THREADS
{
  LARGE_INTEGER KernelTime;
  LARGE_INTEGER UserTime;
  LARGE_INTEGER CreateTime;
  ULONG WaitTime;
  PVOID StartAddress;
  CLIENT_ID ClientId;
  KPRIORITY Priority;
  KPRIORITY BasePriority;
  ULONG ContextSwitchCount;
  THREAD_STATE State;
  KWAIT_REASON WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;

typedef NTSTATUS (WINAPI *tNTQSI)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);

process_state::process_state()
{
  get();
}

process_state::~process_state() noexcept
{
}

void process_state::update()
{
  get();
}

process_vector process_state::get_all() const
{
  return m_proc_infos;
}

process_vector process_state::get_suspended() const
{
  process_vector susp;
  for (const auto& elem : m_proc_infos)
  {
    if (elem.suspended)
      susp.push_back(elem);
  }
  return susp;
}

process_vector process_state::get_not_suspended() const
{
  process_vector nsusp;
  for (const auto& elem : m_proc_infos)
  {
    if (!elem.suspended)
      nsusp.push_back(elem);
  }
  return nsusp;
}

process_vector process_state::get_by_name(const std::wstring& name) const
{
  return get_by_name(name, m_proc_infos);
}

process_vector process_state::get_by_name(const std::wstring& name, const process_vector& p_info) const
{
  process_vector collected;
  auto it{p_info.cbegin()}, found{p_info.cend()};
  do
  {
    found = std::find_if(it, p_info.cend(), [name](const auto& elem) { return lstrcmpiW(elem.name.c_str(), name.c_str()) == 0; });
    if (found != p_info.cend())
    {
      collected.push_back(*found);
      it = ++found;
    }
  } while (found != p_info.cend());

  return collected;
}

process_vector process_state::get_by_id(const unsigned& process_id) const
{
  return get_by_id(process_id, m_proc_infos);
}

process_vector process_state::get_by_id(const unsigned& process_id, const process_vector& p_info) const
{
  process_vector collected;
  auto found{std::find_if(p_info.cbegin(), p_info.cend(), [process_id](const auto& elem) { return elem.process_id == process_id; })};
  if (found != p_info.cend())
    collected.push_back(*found);

  return collected;
}

void process_state::print() const
{
  print(m_proc_infos);
}

void process_state::print(const process_vector& p_info) const
{
  const std::ios_base::fmtflags former_flags{std::wcout.flags()};
  std::wcout << std::boolalpha;
  for (const auto& elem : p_info)
  {
    std::wcout << elem.name << L'\n'  
               << L"Process ID: " << elem.process_id << L'\n'  
               << L"Suspended:  " << elem.suspended << L'\n' << std::endl;  
  }
  std::wcout.flags(former_flags);
}

void process_state::get()
{
  m_proc_infos.clear();

  tNTQSI fpNTQSI{reinterpret_cast<tNTQSI>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"))};  

  if (fpNTQSI == NULL)
    throw std::runtime_error{"function NtQuerySystemInformation not found"};  

  HANDLE hHeap{GetProcessHeap()};
  ULONG cbBuffer{1048576UL};
  LPVOID pBuffer{};

  if ((pBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBuffer)) == NULL)
    throw std::runtime_error{"bad memory allocation"};  

  if (fpNTQSI(SystemProcessInformation, pBuffer, cbBuffer, &cbBuffer) == STATUS_INFO_LENGTH_MISMATCH)
  {
    HeapFree(hHeap, 0, pBuffer);
    throw std::runtime_error{"insufficient memory allocated"};  
  }

  PSYSTEM_PROCESS_INFORMATION pProc{reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(pBuffer)};

  for (;;)
  {
    if (reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId) > static_cast<ULONG_PTR>(4UL))
    {
      m_proc_infos.push_back({std::wstring{pProc->ImageName.Buffer, static_cast<size_t>(pProc->ImageName.Length)}.c_str(), static_cast<unsigned>(reinterpret_cast<ULONG_PTR>(pProc->UniqueProcessId)), false});

      PSYSTEM_THREADS pThreads{reinterpret_cast<PSYSTEM_THREADS>(pProc + 1)};
      for (ULONG i{}; i < pProc->NumberOfThreads; ++pThreads, ++i)
      {
        if (pThreads->State == StateWait && pThreads->WaitReason == Suspended)
        {
          m_proc_infos.back().suspended = true;
          break;
        }
      }
    }

    if (pProc->NextEntryOffset == 0UL)
      break;

    pProc = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>((reinterpret_cast<LPBYTE>(pProc)) + pProc->NextEntryOffset);
  }

  HeapFree(hHeap, 0, pBuffer);

  std::sort(m_proc_infos.begin(), m_proc_infos.end(), (const auto& a, const auto& b) { return lstrcmpiW(a.name.c_str(), b.name.c_str()) < 0; });
}

bool terminate_process(const unsigned& process_id)
{
  HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, process_id);
  if (hProc == NULL)
    return false;

  BOOL ret = TerminateProcess(hProc, 0);
  if (ret != FALSE)
    WaitForSingleObject(hProc, INFINITE);

  CloseHandle(hProc);
  return ret != FALSE;
}

Beide Dateien fügst du deinem Projekt hinzu und includierst "process_state.h". Im Header-Code habe ich ein paar Kommentare hinterlassen. Wie du siehst habe ich noch ein paar Memberfunktionen hinzugefügt, sowie eine Funktion zum Killen eines Prozesses per Prozess ID, was eine deiner fett gedruckten Anforderungen war.

Zum Testen:
#include <iostream>
#include "process_state.h" 


int main(int argc, char* argv)
{
  process_state p_state;

  std::wcout << L"\n~~~~~~~~ All: ~~~~~~~~~~~~~~~~~~\n";  
  p_state.print();

  std::wcout << L"\n~~~~~~~~ Suspended: ~~~~~~~~~~~~\n";  
  p_state.print(p_state.get_suspended());

  std::wcout << L"\n~~~~~~~~ Not Suspended: ~~~~~~~~\n";  
  p_state.print(p_state.get_not_suspended());

  std::wcout << L"\n~~~~~~~~ Notepad processes: ~~~~~\n";  
  p_state.print(p_state.get_by_name(L"Notepad.exe"));  

  return 0;
}

Steffen
tomaschku
tomaschku 06.12.2017 aktualisiert um 19:20:19 Uhr
Goto Top
Danke, dass du mir das extra noch einmal überarbeitet hast, besonders die Kommentare im Code!

P.S.:
Hoffe es hilft trotzdem noch ...
Wenn ich eine Frage habe, dann warte ich eigentlich eh immer, bis die letzte Antwort ca. 3 Tage her ist. Ich hab gerade die Email gelesen und dachte, ich schreibe mal ne Antwort, um nicht unhöflich zu wirken. (Also Fragen und nie antworten.)

Mittlerweile konnte ich auch mit VS testen.
Hat die Installation denn lange gedauert? face-wink

tomaschku
rubberman
rubberman 06.12.2017 um 20:14:42 Uhr
Goto Top
[OT]
Zitat von @tomaschku:
(Also Fragen und nie antworten.)
Finde ich gut, dass du das nicht so hältst. Ich helfe gern, aber irgend ein Feedback (positiv oder negativ) erwarte ich schon...

Zitat von @tomaschku:
Hat die Installation denn lange gedauert? face-wink
Hehe, ja tatsächlich. Hatte VS bereits installiert, ist aber nicht mehr gelaufen, da sich mein Win10 seit dem Fall Creators Update selbst degeneriert. Regulär deinstallieren hat auch nicht funktioniert, sodass ich mich erst mal händisch durch Dateisystem und Registry kämpfen musste, bevor ich neu installieren konnte.
Hab bald Urlaub, dann mache ich die Kiste platt und setze Windows neu auf ...

Steffen
[/OT]
tomaschku
tomaschku 06.12.2017 um 20:57:32 Uhr
Goto Top
Zitat von @rubberman:
Hehe, ja tatsächlich
Hab's mir schon gedacht. War bei mir auch so und musste neu Anfangen.

Gruß,
tomaschku