kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

リモートセッションであるかどうか判定する方法いろいろ

Windows Vista以降、コンソールセッションとサービスセッションは分離されてしまいました。
セッション 0 の分離 - Windows 7 対応アプリケーションの互換性
Windows Vista® および Windows Server® 2008 アプリケーション互換性解説書
私もそうだったのですが、Vista以前のOSで「セッションIDが0だったら、コンソールセッション」という判定しているコードだとはまってしまうことになります。リモート管理接続ではローカルと同じ、リモートデスクトップ機能ではリモート専用のコードという動きになってほしい場合、どうしても判定する必要があります。いや、普通に作ってたら大丈夫だろうという突込みはなしで…。
そこで改めて調べてみたのですが、リモートかローカルか判定する方法は三通り用意されています。あ、WMI経由で取得する方法もあるかもしれませんね。

GetSystemMetricsを使う

GetSystemMetrics function (Windows)

int iMetricsResult = GetSystemMetrics(SM_REMOTESESSION);

Windows 3.1時代からある伝統の関数。Windows Server 2003の管理コンソールに接続した状態ではこの関数は正しく「リモートではない」と判定します。

GetVersionEx

次はちょっと新しめのOS(Windows 2000以降かな)でしか使えない、GetVersionEx()。
GetVersionEx function (Windows)
構造体のwSuiteMaskにVER_SUITE_TERMINALが有効で、VER_SUITE_SINGLEUSERTSが無効であれば複数人が同時でアクセスしているアプリケーションサーバーモード(つまり管理接続ではない)であるということになります。

OSVERSIONINFOEX osex;

ZeroMemory(&osex, sizeof(OSVERSIONINFOEX));
osex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

BOOL bVerify = GetVersionEx((LPOSVERSIONINFO)&osex);

WTSQuerySessionInformationを使う

Windows Server 2008 R2以降の方法。ただし、これ私の手元では動きませんでした。
WTSQuerySessionInformation function (Windows)
WTSQuerySessionInformationの新しい値WTSIsRemoteSessionを使います。なぜかWINVERに0x600を定義しなくても使えてしまうのですが。
TRUEを返却するとリモートセッションであるそうなのですが、管理接続ではFALSEでした。手元にRDS-CALを入れた環境を持っていないので、だれか試してくれるとうれしいなぁ(^^;。

BOOL bIsRemote = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION,
			WTSIsRemoteSession, NULL, NULL);