WTS APIs(Windows终端服务API)获取进程信息

WTS APIs(Windows终端服务API)获取进程信息
 Windows XP 有一个新特性叫做“快速用户转换——Fast User Switching”,这个特性允许多个用户同时在一台机器上登陆。当一个用户登陆后,另一个用户启动的进程仍然能够运行。这个神奇的特性所倚仗的是 WTS APIs。如果你想了解更多有关 WTS 的内容,可以参考 MSJ Oct99 的一篇文章:“Windows NT和 Windows 2000 终端服务APIs介绍”,作者是 Frank Kim。
  Windows XP为每一个登陆用户创建一个WTS会话(Session)。每个运行进程总是与这样一个Session关联。Windows XP的任务管理器允许你列出进程清单,不论是针对所有会话的还是仅仅针对自己的会话,任务管理器对话框的进程标签中有一个"显示所有用户的进程"复选框可 以对此进行选择



  如果你想了解某个进程隶属的 session ID,可以调用 kernel32.dll 输出的一个 API 函数 ProcessIdToSessionId。给定一个进程的ID,他返回相应的 session ID。有趣的是这个 API 函数不是由 wtsapi32.dll 输出的,而是出自于 kernel32.dll,前者是所有 Windows 终端服务 APIs 的输出动态库。实际上,即使 Windows 终端服务没有运行起来,Windows 2000 和 Windows XP 都将 session ID 存储在 PEB 中。
  注意 Windows NT 既不在 PEB 中存储 session ID,也不从 kernel32.dll 中输出 ProcessIdToSessionId 函数。当你调用 ProcessIdToSessionId,而 WTS 又没有运行,这时其返回值总是0。
  除了允许你列出打开的会话之外,WTS 还有一个 API 用于枚举运行的进程,其实现方式与 PSAPI 和 TOOLHELP32 的实现方式是不同的。WTS枚举 APIs 函数的第一个参数都是一个服务器句柄。WTS_CURRENT_SERVER_HANDLE 用于当前的机器。第二个参数是保留参数,值应该为0。第三个参数希望的版本,其值应该是1。最后两个参数用于存放返回的信息。一个用于存放会话数或进程 数。另一个是结构数组的指针,结构可以是描述会话信息的结构,也可以是描述进程信息的结构。就看你是使用哪个枚举API,是枚举会话还是枚举进程。因为数 组的存储空间是由 WTS 分配的,你必须要记住用 WTSFreeMemory 释放这个空间。
下面是描述会话的结构:WTS_SESSION_INFO:

typedef struct _WTS_SESSION_INFO{    DWORD SessionId;    LPTSTR pWinStationName;    WTS_CONNECTSTATE_CLASS State;} WTS_SESSION_INFO, * PWTS_SESSION_INFO;  结构中除了会话的 SessionId,还有会话名 pWinStationName,当前会话的名字是“console”,而其它的会话是无名的。当前的会话状态为 WTSActive,其它则为 WTSDisconnected。

下面是描述进程的结构 WTS_PROCESS_ INFO:

typedef struct _WTS_PROCESS_INFO {    DWORD SessionId;    DWORD ProcessId;    LPTSTR pProcessName;    PSID pUserSid;} WTS_PROCESS_INFO, * PWTS_PROCESS_INFO;  SessionId 与 ProcessIdToSessionId 所要找的值一样,ProcessId 不用说了,是进程ID。最后一个成员 pUserSid 指向安全标示符,描述用户账号,用户正是在这个账号下运行进程。使用 LookupAccountSid,你可以获得从 pUserSid 中获得用户名。这个信息已经可以通过 CProcess 类中的 GetProcessOwner 获得,但它是通过进程记号(token),而不是通过 WTS。某些情况下,即便由 WTSEnumerateProcesses 控制对它的提供,要想获得进程记号也是不可能的,这就是在 Windows XP 环境下要用 WTS API 而不用 PSAPI 或 TOOLHELP32 的缘故



VB代码例子:

Option Explicit

Private Const WTS_CURRENT_SERVER_HANDLE = 0&

Private Type WTS_PROCESS_INFO
   SessionID As Long
   ProcessID As Long
   pProcessName As Long
   pUserSid As Long
End Type

Private Declare Function WTSEnumerateProcesses _
   Lib "wtsapi32.dll" Alias "WTSEnumerateProcessesA" _
   (ByVal hServer As Long, ByVal Reserved As Long, _
   ByVal Version As Long, ByRef ppProcessInfo As Long, _
   ByRef pCount As Long _
   ) As Long

Private Declare Sub WTSFreeMemory Lib "wtsapi32.dll" _
   (ByVal pMemory As Long)

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
   (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Command1_Click()
   GetWTSProcesses
End Sub

Private Function GetStringFromLP(ByVal StrPtr As Long) As String
   Dim b As Byte
   Dim tempStr As String
   Dim bufferStr As String
   Dim Done As Boolean

   Done = False
   Do
      ' Get the byte/character that StrPtr is pointing to.
      CopyMemory b, ByVal StrPtr, 1
      If b = 0 Then  ' If you've found a null character, then you're done.
         Done = True
      Else
         tempStr = Chr$(b)  ' Get the character for the byte's value
         bufferStr = bufferStr & tempStr 'Add it to the string
               
         StrPtr = StrPtr + 1  ' Increment the pointer to next byte/char
      End If
   Loop Until Done
   GetStringFromLP = bufferStr
End Function

Private Sub Form_Load()
   ListView1.View = lvwReport
   Command1.Caption = "Refresh"

'Add the Column Headers for your ListView Control
   ListView1.ColumnHeaders.Add 1, "SessionID", "Session ID"
   ListView1.ColumnHeaders.Add 2, "ProcessID", "Process ID"
   ListView1.ColumnHeaders.Add 3, "ProcessName", "Process Name"
   ListView1.ColumnHeaders.Add 4, "UserID", "User ID"

   GetWTSProcesses
End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As _
                                  MSComctlLib.ColumnHeader)
' When a ColumnHeader object is clicked, the ListView control is
' sorted by the subitems of that column.
' Set the SortKey to the Index of the ColumnHeader - 1
   ListView1.SortKey = ColumnHeader.Index - 1
' Set Sorted to True to sort the list.
   ListView1.Sorted = True
End Sub

Private Sub GetWTSProcesses()
   Dim RetVal As Long
   Dim Count As Long
   Dim i As Integer
   Dim lpBuffer As Long
   Dim p As Long
   Dim udtProcessInfo As WTS_PROCESS_INFO
   Dim itmAdd As ListItem

   ListView1.ListItems.Clear
   RetVal = WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, _
                                  0&, _
                                  1, _
                                  lpBuffer, _
                                  Count)
   If RetVal Then ' WTSEnumerateProcesses was successful
      p = lpBuffer
      For i = 1 To Count
' Count is the number of Structures in the buffer
' WTSEnumerateProcesses returns a pointer, so copy it to a
' WTS_PROCESS_INO UDT so you can access its members
         
         CopyMemory udtProcessInfo, ByVal p, LenB(udtProcessInfo)
        
' Add items to the ListView control
         Set itmAdd = ListView1.ListItems.Add(i, , _
                     CStr(udtProcessInfo.SessionID))
         itmAdd.SubItems(1) = CStr(udtProcessInfo.ProcessID)
' Since pProcessName contains a pointer, call GetStringFromLP to get the
' variable length string it points to
         itmAdd.SubItems(2) = GetStringFromLP(udtProcessInfo.pProcessName)
         itmAdd.SubItems(3) = CStr(udtProcessInfo.pUserSid)

' Increment to next WTS_PROCESS_INO structure in the buffer
         p = p + LenB(udtProcessInfo)
      Next i

      Set itmAdd = Nothing
      WTSFreeMemory lpBuffer   'Free your memory buffer
   Else
      ' Error occurred calling WTSEnumerateProcesses
      ' Check Err.LastDllError for error code
      MsgBox "Error occurred calling WTSEnumerateProcesses.  " & _
      "Check the Platform SDK error codes in the MSDN Documentation" _
      & " for more information.", vbCritical, "Error " & Err.LastDllError
   End If
End Sub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值