Frage

Ich habe ein Programm geschrieben, das die Terminaldienste-API abfragen sollten und einige Statusinformationen über die Sitzungen auf einem Terminaldienste laufen auszudrucken boxen. Ich verwende die WTSQuerySessionInformation Funktion, dies zu tun und es wird einige Daten zurückkehrt, aber die meisten Daten scheint zu fehlen ... Weiß jemand, warum?

Hier ist mein Programm:

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;
}

Und hier ist die Ausgabe:

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

Wie Sie sehen können, sehen einige der Daten gültig, aber nicht alle ....

War es hilfreich?

Lösung 2

Hmm, scheint die Antwort zu sein, dass es ziemlich normal ist für diese Felder leer auf einem Terminal Services / RDP-Sitzung zu sein. Diese API war ursprünglich ein Citrix-API und es gibt eine WF entspricht den meisten dieser WTS-Funktion. Sie scheinen viel mehr Daten von meinem Programm zu erhalten, wenn sie auf einem Citrix / IDA-Server ausgeführt wird, die diese Sitzung API viel mehr in vollem Umfang umzusetzen erscheint. Having said that, ich sah auch mehrere Felder ausgefüllt werden, wenn MS Remote App verwenden. Jedoch im Wesentlichen meines Programm arbeitet ...

Andere Tipps

Auch wenn WTSQuerySessionInformation eine LPTSTR nimmt die zurückgegebenen Daten zu halten, sind die Daten nicht immer ein String. Der Versuch, printf etwas, das kein String in den meisten Fällen nicht sehr gut funktionieren. Die Tatsache, dass Sie leer / Müll Saiten Mittel sind zu sehen, dass manchmal der Puffer durch die LPTSTR beginnt wies mit einem ‚\ 0‘, wenn als String lesen, die printf als leere Zeichenfolge gedruckt wird.

Stattdessen versucht jedes Zeichen der Zeichenfolge in HEX Darstellung ausdrucken. Iterieren durch jedes Zeichen in der Zeichenfolge (0 bis bytesReturned-1) und als hex drucken. Das gibt Ihnen eine bessere Vorstellung davon, was in dem LPTSTR Puffer.

Ich denke, WTSQuerySessionInformation Sie braucht Privilegien zu erhalten, zuerst richtig, um alle Daten zurück?

Ich habe nie in der Lage, etwas zu bekommen, aber das aktuelle Sitzung Zeug.

    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;
    }

Eine Lösung fanden wir das ist. Base auf Registry-Informationen:

Sie abfragen, um die Remote-Registrierung unter HKLM \ Software \ Citrx \ Ica \ Session für alle Registrierungsschlüssel (die die Session-IDs sind). Dann lesen Sie sie PublishedName von jedem Unterschlüssel Anschlusswert. Danach können Sie die Session-ID von WTSQuerySessionInformation gegen den Registrierungsschlüssel Namen übereinstimmen und Sie sind fertig.

Einige Code Powershell PoC würde wie folgt aussehen:

$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()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top