2

私のアプリケーションは、時々リモート デスクトップ クライアントからアクセスされます。

現在、コンソール セッションまたはリモート デスクトップ セッションで使用されているかどうかを知りたいです。後者の場合で、セッションが切断された (ユーザーが切断したがログオフしていない) 場合は、コンソールにリダイレクトする必要があります ( tscon.exe 0 /dest:consoleWindows XP の場合と同様)。

私は現在、それを達成するためにシェルスクリプトを実行しています ( query.exe userandを使用tscon.exe) が、代わりに私の Delhi6 アプリでそれを実行したいと考えています。

4

1 に答える 1

4

私は以下を使用します

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 ディスカッション フォーラムで、開始コードを提供するエントリを見つけました。その投稿は、リモート デスクトップの質問と呼ばれていました。

必要な定数と関数プロトタイプを次に示します。

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;
于 2013-07-11T21:24:50.573 に答える