Swing アプリが Windows RDP セッションから実行されているかどうかを検出するにはどうすればよいですか?
Java のみのソリューションが推奨されますが、アプリは Windows 上で実行されることが保証されているため、シェルアウトしても問題ありません。
上記の答えはうまくいくかもしれませんが、不必要に複雑に思えます。Windows の「sessionname」環境変数を読み取るだけで、RDP セッションを検出できます。この環境変数の値は、通常のローカル セッションでは「Console」になります。RDP セッションの場合、「RDP」というフレーズが含まれます。それを確認するだけなら簡単です。
public static boolean isRemoteDesktopSession() {
System.getenv("sessionname").contains("RDP");
}
Windows7 64bitで動作確認済みです。この手法で気付いた問題の 1 つは、System.getenv() から読み込まれた環境変数の値が、JVM の起動後に変更されないように見えることです。そのため、JVM プロセスがコンソール セッションによって開始された後、RDP セッションによってアクセスされた場合、System.getenv("sessionname") をさらに呼び出すと、引き続き「Console」が返されます。
これを実現するには、ネイティブの Windows ライブラリを呼び出す必要があると思います。次のようなことを試してください:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.*;
import com.sun.jna.examples.win32.Kernel32;
...
public static boolean isLocalSession() {
Kernel32 kernel32;
IntByReference pSessionId;
int consoleSessionId;
Kernel32 lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
pSessionId = new IntByReference();
if (lib.ProcessIdToSessionId(lib.GetCurrentProcessId(), pSessionId)) {
consoleSessionId = lib.WTSGetActiveConsoleSessionId();
return (consoleSessionId != 0xFFFFFFFF && consoleSessionId == pSessionId.getValue());
} else return false;
}
その奇妙に見える条件は、 WTSGetActiveConsoleSessionIdconsoleSessionId
のドキュメントからのもので、次のように書かれています。
戻り値
物理コンソールに接続されているセッションのセッション ID。物理コンソールにセッションが接続されていない場合 (たとえば、物理コンソール セッションが接続中または切断中の場合)、この関数は 0xFFFFFFFF を返します。
NativeCallを試してみてください(http://johannburkard.de/software/nativecall/)
必要なのは、クラスパスに2つのjarと1つのDLLだけです。
簡単なテスト:
import java.io.IOException;
import com.eaio.nativecall.*;
public class WindowsUtils {
public static final int SM_REMOTESESSION = 4096; // remote session
public static boolean isRemote() throws SecurityException, UnsatisfiedLinkError,
UnsupportedOperationException, IOException
{
NativeCall.init();
IntCall ic = null;
ic = new IntCall("user32", "GetSystemMetrics");
int rc = ic.executeCall(new Integer(SM_REMOTESESSION));
if (ic != null) ic.destroy();
return (rc > 0);
}
public static void main(String ... args) throws Exception {
System.out.println(WindowsUtils.isRemote());
}
}