Delphi6:需要知道我的应用程序是在控制台会话还是在远程桌面会话中运行

问题描述 投票:1回答:1

我不时从远程桌面客户端访问我的应用程序,我想知道它当前是否正在控制台会话或远程桌面会话中使用,如果稍后出现,并且该会话已断开连接(用户已断开连接但未注销) ),它应该将自身重定向到控制台(如Windows XP上的“ tscon.exe 0 / dest:console”一样)。现在,我正在运行Shell脚本来实现这一点(使用“ query.exe用户”和“ tscon.exe”),但希望我的Delhi6应用程序能够做到这一点。

delphi delphi-6
1个回答
3
投票
我使用以下

const SM_REMOTESESSION = $1000; if GetSystemMetrics(SM_REMOTESESSION) <> 0 then begin // you are in a remote session end

根据GetSystemMetrics的MSDN页面:SM_REMOTESESSION = 0x1000此系统指标用于终端服务环境。如果调用过程与终端服务客户端会话相关联,则返回值为非零。如果调用过程与终端服务控制台会话相关联,则返回值为0。Windows Server 2003和Windows XP:控制台会话不一定是物理控制台。有关更多信息,请参见WTSGetActiveConsoleSessionId

我在Delphi 2007中使用此函数,并且该函数在Windows单元中定义,但是我确实需要自己定义常量。我不知道Delphi 6是否已定义函数。支持的最低Windows版本是Windows 2000,因此除非您退后一步,否则您应该可以使用它。

-

要找出会话的当前状态,您需要WTSQuerySessionInformation功能。您可以使用此功能查找有关当前会话的很多信息,包括当前状态。

我在Embarcadero论坛上找到了一个条目,为我提供了起始代码。该帖子称为remote desktop question

这是您需要的一些常量和函数原型:

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;

这是正在使用的代码。我将其放在计时器中,然后将状态输出到列表框。我可以断开连接,然后重新连接,然后在列表框中看到状态更改。

有多种方法来处理加载库和函数映射调用。如果最终像这样进行轮询,则可能不应在每次调用时都加载库。我只是使用发现的示例。

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;

热门问题
推荐问题
最新问题