2014-04-08 32 views
6

Làm cách nào để nhận thông tin nếu một sợi bị treo với SuspendThread(). Không có API nào cung cấp thông tin này. API chụp nhanh công cụ giúp rất hạn chế. Có rất nhiều thông tin gây hiểu lầm trên internet và cũng trên StackOverflow. Một số người trên StackOverflow thậm chí nói rằng điều này là không thể.Cách nhận trạng thái chủ đề (ví dụ: bị tạm ngưng), bộ nhớ + mức sử dụng CPU, thời gian bắt đầu, mức độ ưu tiên, v.v.

Những người khác đăng giải pháp yêu cầu Windows 7. Nhưng tôi cần mã để hoạt động trên XP.

Trả lời

8

Tôi tự tìm thấy câu trả lời. Tôi đã viết một lớp cProcInfo rằng có được rất nhiều thông tin về quá trình và chủ đề như:

  1. Quy trình và chủ đề định danh
  2. Nhận Biết Quá Chánh
  3. Process Name
  4. ưu tiên
  5. Bối cảnh tắc
  6. Địa chỉ
  7. Trạng thái (đang chạy, đang chờ, bị tạm dừng, v.v ..)
  8. Date and Time khi quá trình và chủ đề được bắt đầu
  9. Thời gian trong chế độ Kernel
  10. Thời gian trong chế độ tài
  11. Sử dụng bộ nhớ
  12. đếm Xử lý
  13. Trang Lỗi

My lớp hoạt động trên Windows 2000, XP, Vista, 7, 8 ...

Mã sau đây cho thấy cách thức để xác định xem các chủ đề 640 trong quá trình 1948 được supended:

Main() 
{ 
    cProcInfo i_Proc; 
    DWORD u32_Error = i_Proc.Capture(); 
    if (u32_Error) 
    { 
     printf("Error 0x%X capturing processes.\n", u32_Error); 
     return 0; 
    } 

    SYSTEM_PROCESS* pk_Proc = i_Proc.FindProcessByPid(1948); 
    if (!pk_Proc) 
    { 
     printf("The process does not exist.\n"); 
     return 0; 
    } 

    SYSTEM_THREAD* pk_Thread = i_Proc.FindThreadByTid(pk_Proc, 640); 
    if (!pk_Thread) 
    { 
     printf("The thread does not exist.\n"); 
     return 0; 
    } 

    BOOL b_Suspend; 
    i_Proc.IsThreadSuspended(pk_Thread, &b_Suspend); 

    if (b_Suspend) printf("The thread is suspended.\n"); 
    else   printf("The thread is not suspended.\n"); 
    return 0; 
} 

Lớp học của tôi đầu tiên chụp tất cả đang chạy processes và threads với NtQuerySystemInformation() và sau đó tìm kiếm các thông tin về các chủ đề yêu cầu.

Bạn có thể dễ dàng thêm chức năng tìm kiếm quy trình theo tên. (pk_Proc->usName)

Đây là lớp học của tôi. Nó chỉ là một tệp tiêu đề:

#pragma once 

#include <winternl.h> 
#include <winnt.h> 

typedef LONG NTSTATUS; 

#define STATUS_SUCCESS    ((NTSTATUS) 0x00000000) 
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004) 

enum KWAIT_REASON 
{ 
    Executive, 
    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 
}; 

enum THREAD_STATE 
{ 
    Running = 2, 
    Waiting = 5, 
}; 

#pragma pack(push,8) 

struct CLIENT_ID 
{ 
    HANDLE UniqueProcess; // Process ID 
    HANDLE UniqueThread; // Thread ID 
}; 

// http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/thread.htm 
// Size = 0x40 for Win32 
// Size = 0x50 for Win64 
struct SYSTEM_THREAD 
{ 
    LARGE_INTEGER KernelTime; 
    LARGE_INTEGER UserTime; 
    LARGE_INTEGER CreateTime; 
    ULONG   WaitTime; 
    PVOID   StartAddress; 
    CLIENT_ID  ClientID;   // process/thread ids 
    LONG   Priority; 
    LONG   BasePriority; 
    ULONG   ContextSwitches; 
    THREAD_STATE ThreadState; 
    KWAIT_REASON WaitReason; 
}; 

struct VM_COUNTERS // virtual memory of process 
{ 
    ULONG_PTR PeakVirtualSize; 
    ULONG_PTR VirtualSize; 
    ULONG  PageFaultCount; 
    ULONG_PTR PeakWorkingSetSize; 
    ULONG_PTR WorkingSetSize; 
    ULONG_PTR QuotaPeakPagedPoolUsage; 
    ULONG_PTR QuotaPagedPoolUsage; 
    ULONG_PTR QuotaPeakNonPagedPoolUsage; 
    ULONG_PTR QuotaNonPagedPoolUsage; 
    ULONG_PTR PagefileUsage; 
    ULONG_PTR PeakPagefileUsage; 
}; 

// http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/process.htm 
// See also SYSTEM_PROCESS_INROMATION in Winternl.h 
// Size = 0x00B8 for Win32 
// Size = 0x0100 for Win64 
struct SYSTEM_PROCESS 
{ 
    ULONG   NextEntryOffset; // relative offset 
    ULONG   ThreadCount; 
    LARGE_INTEGER WorkingSetPrivateSize; 
    ULONG   HardFaultCount; 
    ULONG   NumberOfThreadsHighWatermark; 
    ULONGLONG  CycleTime; 
    LARGE_INTEGER CreateTime; 
    LARGE_INTEGER UserTime; 
    LARGE_INTEGER KernelTime; 
    UNICODE_STRING ImageName; 
    LONG   BasePriority; 
    PVOID   UniqueProcessId; 
    PVOID   InheritedFromUniqueProcessId; 
    ULONG   HandleCount; 
    ULONG   SessionId; 
    ULONG_PTR  UniqueProcessKey; 
    VM_COUNTERS VmCounters; 
    ULONG_PTR  PrivatePageCount; 
    IO_COUNTERS IoCounters; // defined in winnt.h 
}; 

#pragma pack(pop) 

typedef NTSTATUS (WINAPI* t_NtQueryInfo)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); 

class cProcInfo 
{ 
public: 
    cProcInfo() 
    { 
     #ifdef WIN64 
      assert(sizeof(SYSTEM_THREAD) == 0x50 && sizeof(SYSTEM_PROCESS) == 0x100); 
     #else 
      assert(sizeof(SYSTEM_THREAD) == 0x40 && sizeof(SYSTEM_PROCESS) == 0xB8); 
     #endif 

     mu32_DataSize = 1000; 
     mp_Data  = NULL; 
     mf_NtQueryInfo = NULL; 
    } 
    virtual ~cProcInfo() 
    { 
     if (mp_Data) LocalFree(mp_Data); 
    } 

    // Capture all running processes and all their threads. 
    // returns an API or NTSTATUS Error code or zero if successfull 
    DWORD Capture() 
    { 
     if (!mf_NtQueryInfo) 
     { 
      mf_NtQueryInfo = (t_NtQueryInfo)GetProcAddress(GetModuleHandleA("NtDll.dll"), "NtQuerySystemInformation"); 
      if (!mf_NtQueryInfo) 
       return GetLastError(); 
     } 

     // This must run in a loop because in the mean time a new process may have started 
     // and we need more buffer than u32_Needed !! 
     while (true) 
     { 
      if (!mp_Data) 
      { 
       mp_Data = (BYTE*)LocalAlloc(LMEM_FIXED, mu32_DataSize); 
       if (!mp_Data) 
        return GetLastError(); 
      } 

      ULONG u32_Needed = 0; 
      NTSTATUS s32_Status = mf_NtQueryInfo(SystemProcessInformation, mp_Data, mu32_DataSize, &u32_Needed); 

      if (s32_Status == STATUS_INFO_LENGTH_MISMATCH) // The buffer was too small 
      { 
       mu32_DataSize = u32_Needed + 4000; 
       LocalFree(mp_Data); 
       mp_Data = NULL; 
       continue; 
      } 
      return s32_Status; 
     } 
    } 

    // Searches a process by a given Process Identifier 
    // Capture() must have been called before! 
    SYSTEM_PROCESS* FindProcessByPid(DWORD u32_PID) 
    { 
     if (!mp_Data) 
     { 
      assert(mp_Data); 
      return NULL; 
     } 

     SYSTEM_PROCESS* pk_Proc = (SYSTEM_PROCESS*)mp_Data; 
     while (TRUE) 
     { 
      if ((DWORD)(DWORD_PTR)pk_Proc->UniqueProcessId == u32_PID) 
       return pk_Proc; 

      if (!pk_Proc->NextEntryOffset) 
       return NULL; 

      pk_Proc = (SYSTEM_PROCESS*)((BYTE*)pk_Proc + pk_Proc->NextEntryOffset); 
     } 
    } 

    SYSTEM_THREAD* FindThreadByTid(SYSTEM_PROCESS* pk_Proc, DWORD u32_TID) 
    { 
     if (!pk_Proc) 
     { 
      assert(pk_Proc); 
      return NULL; 
     } 

     // The first SYSTEM_THREAD structure comes immediately after the SYSTEM_PROCESS structure 
     SYSTEM_THREAD* pk_Thread = (SYSTEM_THREAD*)((BYTE*)pk_Proc + sizeof(SYSTEM_PROCESS)); 

     for (DWORD i=0; i<pk_Proc->ThreadCount; i++) 
     { 
      if (pk_Thread->ClientID.UniqueThread == (HANDLE)(DWORD_PTR)u32_TID) 
       return pk_Thread; 

      pk_Thread++; 
     } 
     return NULL; 
    } 

    DWORD IsThreadSuspended(SYSTEM_THREAD* pk_Thread, BOOL* pb_Suspended) 
    { 
     if (!pk_Thread) 
      return ERROR_INVALID_PARAMETER; 

     *pb_Suspended = (pk_Thread->ThreadState == Waiting && 
         pk_Thread->WaitReason == Suspended); 
     return 0; 
    } 

private: 
    BYTE*   mp_Data; 
    DWORD  mu32_DataSize; 
    t_NtQueryInfo mf_NtQueryInfo; 
}; 

// Based on the 32 bit code of Sven B. Schreiber on: 
// http://www.informit.com/articles/article.aspx?p=22442&seqNum=5 
+0

Gọi 'SYSTEM_PROCESS * pk_Proc = i_Proc.FindProcessByPid (1948); 'với PID xác định không thành công (trả về 0) trên hệ thống Win 8.1 x64 của tôi. 'Capture()' đã thành công. –

+0

Có thể bạn phải đặt gói #pragma (8) xung quanh định nghĩa cấu trúc cho 64 bit không? Bạn nên điều tra thêm chi tiết! Bước duy nhất thông qua mã! – Elmue

+0

Bạn muốn chỉ ra rằng định nghĩa _undocumented_ code & struct này chỉ dành cho x86. Đó là một thiết kế xấu. Nó phải được cập nhật với các định nghĩa 64 bit chính xác. [Ở đây] (http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/thread.htm) và [tại đây] (http://www.geoffchappell.com/studies/windows /km/ntoskrnl/api/ex/sysinfo/process.htm) là thông tin thêm. – ahmd0

Các vấn đề liên quan