Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I use the following </p> <pre><code>const SM_REMOTESESSION = $1000; if GetSystemMetrics(SM_REMOTESESSION) &lt;&gt; 0 then begin // you are in a remote session end </code></pre> <p>Per the MSDN page for <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx" rel="nofollow">GetSystemMetrics</a>:<br> SM_REMOTESESSION = 0x1000<br> This system metric is used in a Terminal Services environment. If the calling process is associated with a Terminal Services client session, the return value is nonzero. If the calling process is associated with the Terminal Services console session, the return value is 0. Windows Server 2003 and Windows XP: The console session is not necessarily the physical console. For more information, see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383835%28v=vs.85%29.aspx" rel="nofollow">WTSGetActiveConsoleSessionId</a>.</p> <p>I am using this in Delphi 2007 and the function is defined in the Windows unit, but I did need to define the constant myself. I don't know if Delphi 6 has the function defined. The Minimum supported windows version was Windows 2000 so you should be able to use it unless you are going way back.</p> <p>--</p> <p>To find out the current state of the session you need the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383838%28v=vs.85%29.aspx" rel="nofollow">WTSQuerySessionInformation</a> function. You can use this function to find out a lot of information on the current session including the current state. </p> <p>I found an entry in the Embarcadero Discussion Forums that gave me the starting code. That post was called <a href="https://forums.embarcadero.com/thread.jspa?threadID=80662" rel="nofollow">remote desktop question</a>.</p> <p>Here are some constants and function prototypes you will need:</p> <pre><code> const WTS_CURRENT_SERVER_HANDLE: THandle = 0; WTS_CURRENT_SESSION: DWORD = DWORD(-1); type WTS_INFO_CLASS = ( WTSInitialProgram, WTSApplicationName, WTSWorkingDirectory, WTSOEMId, WTSSessionId, WTSUserName, WTSWinStationName, WTSDomainName, WTSConnectState, WTSClientBuildNumber, WTSClientName, WTSClientDirectory, WTSClientProductId, WTSClientHardwareId, WTSClientAddress, WTSClientDisplay, WTSClientProtocolType, WTSIdleTime, WTSLogonTime, WTSIncomingBytes, WTSOutgoingBytes, WTSIncomingFrames, WTSOutgoingFrames, WTSClientInfo, WTSSessionInfo, WTSSessionInfoEx, WTSConfigInfo, WTSValidationInfo, WTSSessionAddressV4, WTSIsRemoteSession ); WTS_CONNECTSTATE_CLASS = ( WTSActive, // User logged on to WinStation WTSConnected, // WinStation connected to client WTSConnectQuery, // In the process of connecting to client WTSShadow, // Shadowing another WinStation WTSDisconnected, // WinStation logged on without client WTSIdle, // Waiting for client to connect WTSListen, // WinStation is listening for connection WTSReset, // WinStation is being reset WTSDown, // WinStation is down due to error WTSInit); // WinStation in initialization TWTSQuerySessionInformationFunction = function(hServer: THandle; SessionId: DWORD; WTSInfoClass: WTS_INFO_CLASS; var ppBuffer: Pointer; var pBytesReturned: DWORD): BOOL; stdcall; TWTSFreeMemoryProcedure = procedure(pMemory: Pointer); stdcall; </code> </pre> <p>And here is the code in use. I put this in a timer and output the state to a list box. I could disconnect and then reconnect and see the state change in the list box.</p> <p>There are different ways to handle the load library and function mapping call. Probably should not load library on every call if you end up polling like this. I just used the example I found.</p> <pre><code> function TForm3.GetTSClientState: WTS_CONNECTSTATE_CLASS; var LibHandle: HMODULE; WTSQuerySessionInformation: TWTSQuerySessionInformationFunction; WTSFreeMemory: TWTSFreeMemoryProcedure; ClientState: Pointer; cBytesReturned: DWORD; begin LibHandle := LoadLibrary('wtsapi32.dll'); if LibHandle &lt;&gt; 0 then begin try @WTSQuerySessionInformation := GetProcAddress(LibHandle, 'WTSQuerySessionInformationA'); @WTSFreeMemory := GetProcAddress(LibHandle, 'WTSFreeMemory'); if Assigned(WTSQuerySessionInformation) and Assigned(WTSFreeMemory) then begin if WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, ClientState, cBytesReturned) then try result := WTS_CONNECTSTATE_CLASS(ClientState^); finally WTSFreeMemory(ClientState); end; end; finally FreeLibrary(LibHandle); end; end; end; procedure TForm3.Timer1Timer(Sender: TObject); var State: WTS_CONNECTSTATE_CLASS; begin ListBox1.AddItem(GetTSClientName, nil); State := GetTSClientState; case State of WTSActive: ListBox1.AddItem('WTSActive', nil); WTSConnected: ListBox1.AddItem('WTSConnected', nil); WTSConnectQuery: ListBox1.AddItem('WTSConnectQuery', nil); WTSShadow: ListBox1.AddItem('WTSShadow', nil); WTSDisconnected: ListBox1.AddItem('WTSDisconnected', nil); WTSIdle: ListBox1.AddItem('WTSIdle', nil); WTSListen: ListBox1.AddItem('WTSListen', nil); WTSReset: ListBox1.AddItem('WTSReset', nil); WTSDown: ListBox1.AddItem('WTSDown', nil); WTSInit: ListBox1.AddItem('WTSInit', nil); end; end; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload