我用下面的
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 <> 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;