远程桌面连接 - C# 事件

7

有一个小问题。

我们使用 Netgear 提供的互联网 VPN,让教职员工可以通过远程桌面连接从家里访问学校网络。

他们使用浏览器登录 VPN,然后点击其中一个远程服务器,就可以进入远程桌面连接。

但是人们经常遇到一个大问题,就是无法正确退出。似乎他们总是忘记如何退出。所有用户所做的就是在 RDC 客户端上点击关闭按钮,这并不会将他们注销。

我们正在构建一个程序来解决这个问题。想法是“挂钩”远程桌面 API,然后检查会话是否已断开连接,如果是,则注销用户。

该程序将作为服务或物理最小化的 EXE 在后台运行。

我们将使用 C# 进行构建。那么,有没有人知道可以使用 .NET 4 调用的 RDC 事件?这些事件将允许我们知道用户何时关闭会话。

如果您需要更多信息,请告诉我。

谢谢


请查看MSDN中的WM_WTSSESSION_CHANGE消息:http://msdn.microsoft.com/zh-cn/library/aa383828%28VS.85%29.aspx - Treb
只需配置终端服务以注销断开的会话即可。 - Jf Beaulac
2个回答

7
明白了。
呼叫。
SystemEvents.SessionSwitch += new SessionSwitchEventHandle SystemEvents_SessionSwitch);

那么

        static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
    {
        if (e.Reason == SessionSwitchReason.RemoteDisconnect || e.Reason == SessionSwitchReason.ConsoleDisconnect)
        {
            // Log off the user...

        }
        else
        {
            // Physical Logon
        }
    }

只是出于好奇,该事件仅触发运行应用程序的用户,还是任何断开机器的用户? - Joachim Isaksson
我认为只有运行应用程序的用户。因此,我将使用组策略在他们登录远程服务器时运行它,然后当他们关闭rdp会话时,它应该启动应用程序。 - x06265616e
如果我使用远程桌面登录/注销,也会收到此事件。由于某种原因,在使用TeamViewer时不会发生此事件。遗憾的是,SystemParameters.IsRemoteSessionSystemParameters.IsRemoteControlled都没有提供真实值。 - Harald Coppoolse

1

这比上面的答案更好。

        public Form1()
    {
        InitializeComponent();

        if (!WTSRegisterSessionNotification(this.Handle, NOTIFY_FOR_THIS_SESSION))
        {
            Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
        }
    }

    [DllImport("user32.dll")]
    public static extern int ExitWindowsEx(int uFlags, int dwReason);

    [DllImport("WtsApi32.dll")]
    private static extern bool WTSRegisterSessionNotification(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)]int dwFlags);

    [DllImport("WtsApi32.dll")]
    private static extern bool WTSUnRegisterSessionNotification(IntPtr hWnd);

    // constants that can be passed for the dwFlags parameter
    const int NOTIFY_FOR_THIS_SESSION = 0;
    const int NOTIFY_FOR_ALL_SESSIONS = 1;

    // message id to look for when processing the message (see sample code)
    const int WM_WTSSESSION_CHANGE = 0x2b1;

    // WParam values that can be received: 
    const int WTS_CONSOLE_CONNECT = 0x1; // A session was connected to the console terminal.
    const int WTS_CONSOLE_DISCONNECT = 0x2; // A session was disconnected from the console terminal.
    const int WTS_REMOTE_CONNECT = 0x3; // A session was connected to the remote terminal.
    const int WTS_REMOTE_DISCONNECT = 0x4; // A session was disconnected from the remote terminal.
    const int WTS_SESSION_LOGON = 0x5; // A user has logged on to the session.
    const int WTS_SESSION_LOGOFF = 0x6; // A user has logged off the session.
    const int WTS_SESSION_LOCK = 0x7; // A session has been locked.
    const int WTS_SESSION_UNLOCK = 0x8; // A session has been unlocked.
    const int WTS_SESSION_REMOTE_CONTROL = 0x9; // A session has changed its remote controlled status.

    protected override void OnHandleDestroyed(EventArgs e)
    {
        // unregister the handle before it gets destroyed
        WTSUnRegisterSessionNotification(this.Handle);
        base.OnHandleDestroyed(e);
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_WTSSESSION_CHANGE)
        {
            int value = m.WParam.ToInt32();
            if (value == WTS_REMOTE_DISCONNECT)
            {
                ExitWindowsEx(4, 0); // Logout the user on disconnect
            }
            else if (value == WTS_REMOTE_CONNECT)
            {
                MessageBox.Show("Welcome to the VPN. There is no need to Logout anymore, as when you close this session it will automatically log you out");
            }
        }
        base.WndProc(ref m);
    }

这种方法相比于其他答案有什么优势呢?我认为答案是(a)你不需要引用任何额外的DLL,(b)你可以更精确地控制你要监听的内容。 - RB.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接