4

ターミナル サービス API にクエリを実行し、ターミナル サービス ボックスで実行中のセッションに関する状態情報を出力するプログラムを作成しました。これを行うために WTSQuerySessionInformation 関数を使用していますが、一部のデータが返されますが、ほとんどのデータが欠落しているようです...理由を知っている人はいますか?

これが私のプログラムです:

void WTSGetString( HANDLE serverHandle, DWORD sessionid, WTS_INFO_CLASS command, wchar_t* commandStr) 
{
    DWORD bytesReturned = 0;
    LPTSTR pData = NULL;
    if (WTSQuerySessionInformation(serverHandle, sessionid, command, &pData, &bytesReturned))
    {
        wprintf(L"\tWTSQuerySessionInformationW - session %d - %s returned \"%s\"\n", sessionid, commandStr, pData);    
    }
    else
    {
        wprintf(L"\tWTSQuerySessionInformationW - session %d - %s failed - error=%d - ", sessionid, commandStr, GetLastError());
        printLastError(NULL, GetLastError());
    }
    WTSFreeMemory(pData);
}


void ExtractFromWTS( HANDLE serverHandle, DWORD sessionid ) 
{

    WTSGetString(serverHandle, sessionid, WTSInitialProgram, L"WTSInitialProgram");
    WTSGetString(serverHandle, sessionid, WTSApplicationName, L"WTSApplicationName");
    WTSGetString(serverHandle, sessionid, WTSWorkingDirectory, L"WTSWorkingDirectory");
    WTSGetString(serverHandle, sessionid, WTSOEMId, L"WTSOEMId");
    WTSGetString(serverHandle, sessionid, WTSSessionId, L"WTSSessionId");
    WTSGetString(serverHandle, sessionid, WTSUserName, L"WTSUserName");
    WTSGetString(serverHandle, sessionid, WTSWinStationName, L"WTSWinStationName");
    WTSGetString(serverHandle, sessionid, WTSDomainName, L"WTSDomainName");
    WTSGetString(serverHandle, sessionid, WTSConnectState, L"WTSConnectState");
    WTSGetString(serverHandle, sessionid, WTSClientBuildNumber, L"WTSClientBuildNumber");
    WTSGetString(serverHandle, sessionid, WTSClientName, L"WTSClientName");
    WTSGetString(serverHandle, sessionid, WTSClientDirectory, L"WTSClientDirectory");
    WTSGetString(serverHandle, sessionid, WTSClientProductId, L"WTSClientProductId");
    WTSGetString(serverHandle, sessionid, WTSClientHardwareId, L"WTSClientHardwareId");
    WTSGetString(serverHandle, sessionid, WTSClientAddress, L"WTSClientAddress");
    WTSGetString(serverHandle, sessionid, WTSClientDisplay, L"WTSClientDisplay");
    WTSGetString(serverHandle, sessionid, WTSClientProtocolType, L"WTSClientProtocolType");
}

int _tmain(int argc, _TCHAR* argv[])
{
    PWTS_SESSION_INFOW ppSessionInfo = 0;
    DWORD pCount;
    if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
    {
        printLastError(L"WTSEnumerateSessions", GetLastError());
        return 1;
    }

    wprintf(L"%d WTS sessions found on host\n", pCount);

    for (unsigned int i=0; i<pCount; i++)
    {
        wprintf(L"> session=%d, stationName = %s\n", ppSessionInfo[i].SessionId, ppSessionInfo[i].pWinStationName);
        ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, ppSessionInfo[i].SessionId);
        LPWSTR sessionstr = new wchar_t[200];
        wsprintf(sessionstr, L"%d", ppSessionInfo[i].SessionId);    
    }

    return 0;
}

出力は次のとおりです。

C:\Users\Administrator\Desktop>ObtainWTSStartShell.exe empserver1
4 WTS sessions found on host
> session=0, stationName = Services
        WTSQuerySessionInformationW - session 0 - WTSInitialProgram failed - error=87 - The paramete
r is incorrect.

        WTSQuerySessionInformationW - session 0 - WTSApplicationName failed - error=87 - The paramet
er is incorrect.

        WTSQuerySessionInformationW - session 0 - WTSWorkingDirectory returned ""
        WTSQuerySessionInformationW - session 0 - WTSOEMId returned ""
        WTSQuerySessionInformationW - session 0 - WTSSessionId returned ""
        WTSQuerySessionInformationW - session 0 - WTSUserName returned ""
        WTSQuerySessionInformationW - session 0 - WTSWinStationName returned "Services"
        WTSQuerySessionInformationW - session 0 - WTSDomainName returned ""
        WTSQuerySessionInformationW - session 0 - WTSConnectState returned "♦"
        WTSQuerySessionInformationW - session 0 - WTSClientBuildNumber returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientName returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientDirectory returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientProductId returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientHardwareId returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientAddress returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientDisplay returned ""
        WTSQuerySessionInformationW - session 0 - WTSClientProtocolType returned ""
        GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
        GetShellProcessName succeseded - explorer.exe
> session=1, stationName = Console
        WTSQuerySessionInformationW - session 1 - WTSInitialProgram returned ""
        WTSQuerySessionInformationW - session 1 - WTSApplicationName returned ""
        WTSQuerySessionInformationW - session 1 - WTSWorkingDirectory returned ""
        WTSQuerySessionInformationW - session 1 - WTSOEMId returned ""
        WTSQuerySessionInformationW - session 1 - WTSSessionId returned "☺"
        WTSQuerySessionInformationW - session 1 - WTSUserName returned ""
        WTSQuerySessionInformationW - session 1 - WTSWinStationName returned "Console"
        WTSQuerySessionInformationW - session 1 - WTSDomainName returned ""
        WTSQuerySessionInformationW - session 1 - WTSConnectState returned "☺"
        WTSQuerySessionInformationW - session 1 - WTSClientBuildNumber returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientName returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientDirectory returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientProductId returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientHardwareId returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientAddress returned ""
        WTSQuerySessionInformationW - session 1 - WTSClientDisplay returned "?"
        WTSQuerySessionInformationW - session 1 - WTSClientProtocolType returned ""
        GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
        GetShellProcessName succeseded - explorer.exe
> session=3, stationName = RDP-Tcp#0
        WTSQuerySessionInformationW - session 3 - WTSInitialProgram returned ""
        WTSQuerySessionInformationW - session 3 - WTSApplicationName returned ""
        WTSQuerySessionInformationW - session 3 - WTSWorkingDirectory returned ""
        WTSQuerySessionInformationW - session 3 - WTSOEMId returned ""
        WTSQuerySessionInformationW - session 3 - WTSSessionId returned "♥"
        WTSQuerySessionInformationW - session 3 - WTSUserName returned "Administrator"
        WTSQuerySessionInformationW - session 3 - WTSWinStationName returned "RDP-Tcp#0"
        WTSQuerySessionInformationW - session 3 - WTSDomainName returned "EMPSERVER1"
        WTSQuerySessionInformationW - session 3 - WTSConnectState returned ""
        WTSQuerySessionInformationW - session 3 - WTSClientBuildNumber returned "?"
        WTSQuerySessionInformationW - session 3 - WTSClientName returned "APWADEV03"
        WTSQuerySessionInformationW - session 3 - WTSClientDirectory returned "C:\Windows\System32\m
stscax.dll"
        WTSQuerySessionInformationW - session 3 - WTSClientProductId returned "☺"
        WTSQuerySessionInformationW - session 3 - WTSClientHardwareId returned ""
        WTSQuerySessionInformationW - session 3 - WTSClientAddress returned "☻"
        WTSQuerySessionInformationW - session 3 - WTSClientDisplay returned "?"
        WTSQuerySessionInformationW - session 3 - WTSClientProtocolType returned "☻"
        GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
        GetShellProcessName succeseded - explorer.exe
> session=65536, stationName = RDP-Tcp
        WTSQuerySessionInformationW - session 65536 - WTSInitialProgram returned ""
        WTSQuerySessionInformationW - session 65536 - WTSApplicationName returned ""
        WTSQuerySessionInformationW - session 65536 - WTSWorkingDirectory returned ""
        WTSQuerySessionInformationW - session 65536 - WTSOEMId returned ""
        WTSQuerySessionInformationW - session 65536 - WTSSessionId returned ""
        WTSQuerySessionInformationW - session 65536 - WTSUserName returned ""
        WTSQuerySessionInformationW - session 65536 - WTSWinStationName returned "RDP-Tcp"
        WTSQuerySessionInformationW - session 65536 - WTSDomainName returned ""
        WTSQuerySessionInformationW - session 65536 - WTSConnectState returned "♠"
        WTSQuerySessionInformationW - session 65536 - WTSClientBuildNumber returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientName returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientDirectory returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientProductId returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientHardwareId returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientAddress returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientDisplay returned ""
        WTSQuerySessionInformationW - session 65536 - WTSClientProtocolType returned ""
        GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
        GetShellProcessName succeseded - explorer.exe

ご覧のとおり、一部のデータは有効に見えますが、すべてではありません....

4

4 に答える 4

3

うーん、答えは、これらのフィールドがターミナル サービス/RDP セッションで空であることはごく普通のことのようです。この API はもともと Citrix API であり、これらの WTS 関数のほとんどに相当する WF があります。このセッション API をより完全に実装しているように見える Citrix/IDA サーバーで実行すると、私のプログラムからより多くのデータを取得できるようです。そうは言っても、MS Remote App を使用すると、より多くのフィールドが入力されることもわかりました。しかし、本質的に私のプログラムは機能していました...

于 2010-05-13T11:02:50.083 に答える
3

WTSQuerySessionInformation は返されたデータを保持するために LPTSTR を取りますが、データは常に文字列であるとは限りません。ほとんどの場合、文字列ではないものを印刷しようとしてもうまくいきません。空/ガベージ文字列が表示されているという事実は、LPTSTR が指すバッファーが、文字列として読み取られた場合に '\0' で始まることがあり、printf が空の文字列として出力することを意味します。

代わりに、文字列の各文字を HEX 表現で出力してみてください。文字列内の各文字 (0 から bytesReturned-1 まで) を繰り返し処理し、16 進数として出力します。これにより、LPTSTR バッファーの内容がよくわかります。

于 2011-04-19T20:14:45.570 に答える
0

現在のセッションのもの以外は何も取得できませんでした。

    int _tmain(int argc, _TCHAR* argv[])
    {

        //  if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
        //  {
        ////The stuff coming back from WTSEnumerateSessions in ppSessionInfo doesn't seem to be useful. 

        if (GetSystemMetrics(SM_REMOTESESSION) == 0)
        {
            //it ain't remote.  give up.
            return 1;
        }

        DWORD bytesReturned = 0;
        LPTSTR pData = NULL;
        WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionId, &pData, &bytesReturned);
        DWORD sessionId = pData[0]; /*for lookin' at in the debugger*/
        wprintf(L"%d WTS session where you will see stuff.  CURRENT_SESSION\n", pData[0]);

        ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, pData[0]); 
        LPWSTR sessionstr = new wchar_t[200];
        wsprintf(sessionstr, L"%d", pData[0]);    

        getchar();
        return 0;
    }
于 2014-06-10T21:07:23.387 に答える
0

私たちが見つけた1つの解決策はこれです。レジストリ情報に基づく:

ここに画像の説明を入力

すべてのレジストリ キー (セッション ID) について、HKLM\Software\Citrx\Ica\Session の下のリモート レジストリにクエリを実行します。次に、各サブキー Connection から値 PublishedName を読み取ります。その後、WTSQuerySessionInformation からのセッション ID をレジストリ キー名と照合すれば完了です。

一部の PowerShell PoC コードは次のようになります。

$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', 'YOURSERVER')
$RegKey = $Reg.OpenSubKey("SOFTWARE\\Citrix\\ICA\\Session")
foreach ($sessionId in $RegKey.GetSubKeyNames())
{
    $sessionKey = $RegKey.OpenSubKey($sessionId + "\\Connection")
    if ($sessionKey -ne $null)
    {
        $sessionKey.GetValue("PublishedName")
        $sessionKey.Close()
    }
}    
$RegKey.Close()
$Reg.Close()
于 2017-02-02T13:11:04.287 に答える