利用未公开API获取终端会话闲置时间(Idle Time)和登入时间(Logon Time)
作者:Tuuzed(土仔)   发表于:2008年3月3日23:12:38 
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.cppblog.com/tuuzed/archive/2008/03/03/43631.html


可能很多人都知道NT系统的query user命令,命令返回“使用者名称 工作阶段名称 识别码 状态 闲置时间 登入时间”。如图:

微软给出了获取终端会话的重要API(见Terminal Services API Functions),与获取当前终端会话功能有关的API有:WTSEnumerateSessionsWTSQuerySessionInformation

WTSEnumerateSessions:顾名思义就是列出所有的Session,返回一个WTS_SESSION_INFO结构,结构存储了SessionId,WinStationName,State(包括Active、Disconnected等状态)。

WTSQuerySessionInformation:这个和上面的API有些不同,它只能通过SessionId来查询Session的详细信息,可获取例如用于连接终端客户端工具的ClientName、ClientDirectory等,比WTSEnumerateSessions功能丰富。

按照MSDN上说的,WTSQuerySessionInformation还可以获取IdleTime、LogonTime、IncomingBytes、OutgoingBytes等信息,可惜,标明是“This value is not used.”,要使用的话必须在Windows Server 2008和Windows Vista SP1下使用,局限性太大了。只好自己上Goolge上搜索一下了,在国外的论坛中,大部分人对于获取Idle Time都是说在WIN2008或VISTA才支持。那么WIN2000、2003里的query命令是怎么获得登入时间的?这里面肯定有什么没有公开的API在里面!果然,我找到了Guy Teverovsky的BLOG,它给出的答案(《Querying TS session idle time with C#》译文:《[翻译]利用C#获取终端服务(Terminal Services)会话的闲置时间》)和我预想的差不错——所要的信息在在Winsta.dll内的一个未公开API函数WinStationQueryInformationW返回的结构WINSTATIONQUERYINFORMATIONW里面。

要想使用WinStationQueryInformationW必须知道其中两个重要的参数WinStationInformation(枚举类型)值和WINSTATIONINFORMATIONW结构内容。在VS2005对上述两个值有定义(winternl.h):

typedef enum _WINSTATIONINFOCLASS {
    WinStationInformation = 8
} WINSTATIONINFOCLASS; 
typedef struct _WINSTATIONINFORMATIONW {
    BYTE Reserved2[70];
    ULONG LogonId;
    BYTE Reserved3[1140];
} WINSTATIONINFORMATIONW, * PWINSTATIONINFORMATIONW; 

第一个值很清楚了,是8。而后一个结构,保留位达1140位,这里有太多未知的信息了。还好那位牛人给出了C#的定义,我把它转成C++的结构定义:

typedef struct _WINSTATIONQUERYINFORMATION
{
    char Reserved1[72];
    unsigned int SessionId;
    char Reserved2[4];
    FILETIME ConnectTime;
    FILETIME DisconnectTime;
    FILETIME LastInputTime;
    FILETIME LogonTime;
    char Reserved3[1096];
    FILETIME CurrentTime;
} WINSTATIONQUERYINFORMATION, *PWINSTATIONQUERYINFORMATION; 

定义完这个结构,工作已经有眉目了。下面就是载入Winsta.dll内那个未公开的API函数,顺便包装了一下:

BOOL WINAPI WinStationQueryInformation(HANDLE hServer, DWORD SessionId, DWORD InfoClass, LPVOID Buffer, DWORD BufferLength, LPDWORD Count)
{
    typedef BOOL (WINAPI *PROCPTR)(HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD);
    static HMODULE hModule = NULL;
    static PROCPTR proc = NULL;
    hModule = LoadLibrary("winsta.dll");
    if (hModule == NULL)
    {
        return FALSE;
    } 

    if (proc == NULL)
    {
        proc = (PROCPTR) GetProcAddress(hModule, "WinStationQueryInformationW");
    } 

    if (proc == NULL)
    {
        return FALSE;
    } 

    return proc(hServer, SessionId, InfoClass, Buffer, BufferLength, Count);

这样,只要直接调用自己的WinStationQueryInformation来间接调用DLL里面的WinStationQueryInformationW就可以了。登入时间Logon Time是可以直接获取的,而闲置时间的获取就要参考当前会话的状态了:如果会话是断开(Disconnected)状态,闲置时间=当前时间-断开时间(Idle Time = CurrentTime - DisconnectTime);如果会话是活动的(alive)状态,闲置时间=当前时间-最后输入时间(Idle Time = CurrentTime - LastInputTime)。

已经做出来了一个DEMO,看截图:

这是我做的一个ROOKIT工具的截图,其中就包括有对终端会话的管理等。在这次编程后,给我感触最深的就是国外大虾解决问题的方法与国内的我们有很大的不同,他们善于从多角度来解决问题,独自解决问题后再总结,是利用网络资源而不是依赖网络资源。

利用未公开API获取终端会话闲置时间(Idle Time)和登入时间(Logon Time)的更多相关文章

  1. CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视

    一.需求无论何时,当你在Explorer窗口中创建.删除或重命名一个文件夹/文件,或者插入拔除移动存储器时,Windows总是能非常快速地更新它所有的视图.有时候我们的程序中也需要这样的功能,以便当用 ...

  2. 利用KEGG的API获取基因对应的pathway 信息

    KEGG 官网提供了API, 可以方便的访问KEGG 数据库中的内容,链接如下: http://www.kegg.jp/kegg/rest/keggapi.html 利用API可以得到某一个基因参与的 ...

  3. 软件看门狗--别让你地程序无响应(使用未公开API函数IsHungAppWindow,知识点较全)

    正文一.概述一些重要的程序,必须让它一直跑着:而且还要时时关心它的状态——不能让它出现死锁现象.当然,如果一个主程序会出现死锁,肯定是设计或者编程上的失误.我们首要做的事是,把这个Bug揪出来.但如果 ...

  4. 利用百度词典API和Volley网络库开发的android词典应用

     关于百度词典API的说明,地址在这里:百度词典API介绍 关于android网络库Volley的介绍说明,地址在这里:Android网络通信库Volley 首先我们看下大体的界面布局!

  5. QQ登入(5)获取空间相册,新建相册,上传图片到空间相册

    ///////////////////////////////////////////////////////////////////// 获取相册列表:必须先授权登入 1.1.  String mA ...

  6. [翻译]利用C#获取终端服务(Terminal Services)会话的闲置时间

    [翻译]利用C#获取终端服务(Terminal Services)会话的闲置时间 作者:Tuuzed(土仔)   发表于:2008年2月29日版权声明:可以任意转载,转载时请务必以超链接形式标明文章原 ...

  7. 利用腾讯企业邮箱开放API获取账户未读邮件数初探

    公司一直使用腾讯提供的免费企业邮箱服务,今天用管理员帐户登录后发现,原来现在腾讯的企业邮箱也开放了部分API 你可以通过开放接口实现以下功能: 数据同步 数据同步可以帮助你同步部门成员信息,你还可以创 ...

  8. 劳动节脑洞大开!利用Debug API 获取 加壳客户端的MD5值

    系统 : Windows xp 程序 : 某游戏客户端 程序下载地址 :不提供 要求 : 远程注入 & 获取MD5值 使用工具 : vc++6.0 & OD 案例说明: 该游戏客户端对 ...

  9. 利用百度地图API,获取经纬度坐标

    利用百度地图API,获取经纬度坐标 代码很简单,但在网上没找到现成的获取地图经纬度的页面. 就是想,给当前页面传递一个经纬度,自动定位到此经纬度.然后可以重新选择,选择完返回经纬度. 效果如下: 源代 ...

随机推荐

  1. java 随机数的生成

    生成10个不小于100000的6位数 public static void main(String[] args) { Random random = new Random(); for (int i ...

  2. Light OJ 1318 Strange Game 组合数+高速幂+分解因子

    长度为l的用k种字符组成的字符串有k^l中 当中m个字符要不同样 那就是k^l*C(l, m)*(k-1)^m 有反复 要除以2 可是你mod n了 不能直接除 n不一定是素数 所以不能乘以逆元 所以 ...

  3. c++,初始化列表

    类对象的构造顺序是这样的: a.分配内存,调用构造函数时,隐式/显示的初始化各数据成员 b.进入构造函数后在构造函数中执行一般计算 1.初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内 ...

  4. 基于visual Studio2013解决C语言竞赛题之1043求末尾0个数

       题目 解决代码及点评 /* 43. 求n!的末尾有多少个零.可以通过检查n!含有多少个10的因数来求它末尾零的个数. 因为10=2×5,在n!中含有2的因数显然多于含有5的因数. 一 ...

  5. c++中一个类所占用的空间

    看到阿里的一道笔试题: #pragma pack(2) class A { int i; union U { char buff[13]; int i; }u; void foo() { } type ...

  6. 在Ubuntu下编译Assimp库

    在Ubuntu下编译Assimp库 怎样在Ubuntu下编译Assimp库?这是我曾经编译成功后做的笔记,供參考. 1.去以下的站点去下载Assimp库: http://assimp.sourcefo ...

  7. 树——axure线框图部件库介绍

    终于到最后一个组件的介绍了!到这里基础的应用应该算完成了!  1. 拖动树组件,到页面编辑区域  2.添加节点,可以添加子节点也可以在该节点的前后添加平级节点  3. 编辑节点图标 做好上面的那一步, ...

  8. 当向计算机中存入一个float类型的数值2.2 后,在从计算机中读出输出,这时2.2 的值已经发生了变化(转)

    problom : 'f1' value hava been changed when output. reason : the binary repersentation of 2.2f is : ...

  9. java WEB Response重定向和缓存控制

    package cn.com; import java.io.IOException; import javax.servlet.ServletException; import javax.serv ...

  10. Swift - 多线程实现方式(1) - NSThread

    1,Swift继续使用Object-C原有的一套线程,包括三种多线程编程技术: (1)NSThread (2)Cocoa NSOperation(NSOperation和NSOperationQueu ...