[翻譯]利用C#獲取終端服務(wù)(Terminal Services)會話的閑置時間
作者:Tuuzed(土仔) 發(fā)表于:2008年2月29日
版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時請務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明。
http://www.shnenglu.com/tuuzed/archive/2008/02/29/43424.html
原著:Guy Teverovsky
翻譯:土仔Tuuzed
原文出處:Querying TS session idle time with C#
原文URL:http://blogs.microsoft.co.il/blogs/guyt/archive/2007/10/06/querying-ts-session-idle-time-with-c.aspx
本文特別聲明:原文版權(quán)歸原作者Guy Teverovsky所有,本譯文可以任意轉(zhuǎn)載, 轉(zhuǎn)載時請務(wù)必以超鏈接形式標(biāo)明原文出處、譯文出處、譯者及本聲明。
這一開始就是一個挑戰(zhàn)。我的同事正在編寫一個程序,用來獲取遠(yuǎn)程計算機終端服務(wù)會話的閑置時間。剛開始,我們想到的是利用WMI(譯注WMI:Windows Management Instrumentation管理規(guī)范),但是那里沒有有價值的信息,因此我們開始在Win32 API(譯注API:Application Programming Interface應(yīng)用程序接口)里查找。首先,“Terminal Services API”字樣令我們覺得有希望,同時里面的WTSQuerySessionInformation函數(shù)也引起了我的注意,可是,接下來對WTS_INFO_CLASS枚舉類型的注釋不得不使得我們又要回到Google中了:
后來,我找到一個看似有些意思的API函數(shù):WinStationQueryInformationW. 可是這個函數(shù)有些問題:
1. 這是一個內(nèi)部函數(shù),它在Winsta.dll內(nèi)部實現(xiàn),不像其他已公開的WTS API函數(shù)是在wtsapi32.dll內(nèi)部;
2. 該函數(shù)的返回值(一個結(jié)構(gòu)):WINSTATIONQUERYINFORMATIONW,該結(jié)構(gòu)的代碼在MSDN上沒有任何資料;
3. MSDN上的資料說,查詢的句柄(handle)通常只能是SERVERNAME_CURRENT。這就意味著你不能查詢遠(yuǎn)程的終端服務(wù)器(盡管如此,通過用depends.exe(譯注:Visual Studio自帶的工具)查看終端服務(wù)管理器(Terminal Services Manager)的EXE文件,該管理器也大量地在使用這個函數(shù))。
我決定試一試,看能否解決以上的問題:
1. “這是一個內(nèi)部函數(shù)”——嗯……沒辦法,已經(jīng)沒有其他方法能夠得到我想要的信息了,這是唯一的選擇。
2. “WINSTATIONQUERYINFORMATIONW結(jié)構(gòu)的代碼沒有公開”——這是最棘手的問題。看了它在Platform SDK的winternl.h文件中的定義后,我相當(dāng)失望:
顯然,這是不夠的……我設(shè)法找到了這部分結(jié)構(gòu)的C++代碼,轉(zhuǎn)用C#定義如下:
3. “MSDN上的資料說,我們只能在本地機器上使用這個函數(shù)”——但是這里隱含了些線索……這個函數(shù)與WTS API記載在了一起,而且你可以通過一個函數(shù)獲得終端服務(wù)(TS)的句柄(handle):WTSOpenServer。所以,接下來我要做的就是利用WTSOpenServer()函數(shù)獲取遠(yuǎn)程終端服務(wù)的句柄(handle),然后利用WinStationQueryInformationW()函數(shù)得到我想要的信息。
把上面的做一個總述:
需要的結(jié)構(gòu)(structures)/枚舉類型(enums):
DLL文件導(dǎo)入(DLLImports):
我們將得到通俗易懂的信息:
將難處理的FILETIME類型轉(zhuǎn)為DateTime類型:
有用的代碼:
只需簡單地調(diào)用WTSQuerySessionInfo("servername", <Session ID>)就行了。
總結(jié):
就如大家看到的一樣,在所有步驟完成后,我們還是沒有得到我們想要的“會話閑置時間(Session Idle Time)”。其實,根據(jù)下面的簡單規(guī)則就能很容易地把它計算出來:
※ 如果會話是斷開(disconnected)狀態(tài),閑置時間=當(dāng)前時間-斷開時間(Idle Time = CurrentTime - DisconnectTime)
※ 如果會話是活動的(alive)狀態(tài),閑置時間=當(dāng)前時間-最后輸入時間(Idle Time = CurrentTime - LastInputTime)