Esempio n. 1
0
 public void ShowMe()
 {
     SimpleLogHelper.Debug("Call shortcut to invoke quick window.");
     _vmSearchBox.DispNameFilter = "";
     if (SystemConfig.Instance.QuickConnect.Enable)
     {
         if (_isHidden == true)
         {
             lock (_closeLocker)
             {
                 if (_isHidden == true)
                 {
                     var p        = ScreenInfoEx.GetMouseSystemPosition();
                     var screenEx = ScreenInfoEx.GetCurrentScreenBySystemPosition(p);
                     this.Top  = screenEx.VirtualWorkingAreaCenter.Y - this.Height / 2;
                     this.Left = screenEx.VirtualWorkingAreaCenter.X - this.Width / 2;
                     this.Show();
                     this.Visibility = Visibility.Visible;
                     this.Activate();
                     this.Topmost = true;  // important
                     this.Topmost = false; // important
                     this.Focus();         // important
                     TbKeyWord.Focus();
                     _isHidden = false;
                     _vmSearchBox.PopupSelectionsIsOpen = false;
                     _vmSearchBox.PopupActionsIsOpen    = false;
                 }
             }
         }
     }
 }
Esempio n. 2
0
        public void ShowRemoteHost(uint serverId)
        {
            Debug.Assert(serverId > 0);
            Debug.Assert(GlobalData.Instance.ServerList.Any(x => x.Id == serverId));
            var server = GlobalData.Instance.ServerList.First(x => x.Id == serverId);

            // update last conn time
            server.LastConnTime = DateTime.Now;
            Server.AddOrUpdate(server);

            // is connected now! activate it then return.
            if (server.OnlyOneInstance && _protocolHosts.ContainsKey(serverId.ToString()))
            {
                if (_protocolHosts[serverId.ToString()].ParentWindow is TabWindow t)
                {
                    var s = t.Vm?.Items?.First(x => x.Content?.ProtocolServer?.Id == serverId);
                    if (s != null)
                    {
                        t.Vm.SelectedItem = s;
                    }
                    t.Activate();
                }
                return;
            }

            // create new remote session
            TabWindow tab = null;

            try
            {
                if (server.IsConnWithFullScreen())
                {
                    // for those people using 2+ monitors in different scale factors, we will try "mstsc.exe" instead of "PRemoteM".
                    if (Screen.AllScreens.Length > 1 &&
                        server is ProtocolServerRDP rdp &&
                        rdp.RdpFullScreenFlag == ERdpFullScreenFlag.EnableFullAllScreens)
                    {
                        int factor = (int)(new ScreenInfoEx(Screen.PrimaryScreen).ScaleFactor * 100);
                        // check if screens are in different scale factors
                        bool differentScaleFactorFlag = Screen.AllScreens.Select(screen => (int)(new ScreenInfoEx(screen).ScaleFactor * 100)).Any(factor2 => factor != factor2);
                        if (differentScaleFactorFlag || true)
                        {
                            var tmp         = Path.GetTempPath();
                            var rdpFileName = $"{rdp.DispName}_{rdp.Port}_{rdp.UserName}";
                            var invalid     = new string(Path.GetInvalidFileNameChars()) +
                                              new string(Path.GetInvalidPathChars());
                            rdpFileName = invalid.Aggregate(rdpFileName, (current, c) => current.Replace(c.ToString(), ""));
                            var rdpFile = Path.Combine(tmp, rdpFileName + ".rdp");
                            try
                            {
                                File.WriteAllText(rdpFile, rdp.ToRdpConfig().ToString());
                                var p = new Process
                                {
                                    StartInfo =
                                    {
                                        FileName               = "cmd.exe",
                                        UseShellExecute        = false,
                                        RedirectStandardInput  = true,
                                        RedirectStandardOutput = true,
                                        RedirectStandardError  = true,
                                        CreateNoWindow         = true
                                    }
                                };
                                p.Start();
                                p.StandardInput.WriteLine("mstsc -admin \"" + rdpFile + "\"");
                                p.StandardInput.WriteLine("exit");
                            }
                            finally
                            {
                                // delete tmp rdp file, ETA 10s
                                var t = new Task(() =>
                                {
                                    Thread.Sleep(1000 * 10);
                                    if (File.Exists(rdpFile))
                                    {
                                        File.Delete(rdpFile);
                                    }
                                });
                                t.Start();
                            }
                            return;
                        }
                    }


                    var host = ProtocolHostFactory.Get(server);
                    host.OnClosed            += OnProtocolClose;
                    host.OnFullScreen2Window += OnFullScreen2Window;
                    AddProtocolHost(host);
                    MoveProtocolHostToFullScreen(host.ConnectionId);
                    host.Conn();
                    SimpleLogHelper.Debug($@"Start Conn: {server.DispName}({server.GetHashCode()}) by host({host.GetHashCode()}) with full");
                }
                else
                {
                    switch (SystemConfig.Instance.General.TabMode)
                    {
                    case EnumTabMode.NewItemGoesToGroup:
                        // work in tab by group mode
                        if (_tabWindows.Any(x => x.Value.Vm.Tag == server.GroupName))
                        {
                            tab = _tabWindows.First(x => x.Value.Vm.Tag == server.GroupName).Value;
                        }
                        break;

                    case EnumTabMode.NewItemGoesToProtocol:
                        // work in tab by protocol mode
                        if (_tabWindows.Any(x => x.Value.Vm.Tag == server.ProtocolDisplayName))
                        {
                            tab = _tabWindows.First(x => x.Value.Vm.Tag == server.ProtocolDisplayName).Value;
                        }
                        break;

                    default:
                        // work in tab by latest tab mode
                        if (!string.IsNullOrEmpty(_lastTabToken) && _tabWindows.ContainsKey(_lastTabToken))
                        {
                            tab = _tabWindows[_lastTabToken];
                        }
                        break;
                    }

                    if (tab == null)
                    {
                        var token = DateTime.Now.Ticks.ToString();
                        AddTab(new TabWindow(token));
                        tab = _tabWindows[token];
                        tab.Show();
                        _lastTabToken = token;

                        if (SystemConfig.Instance.General.TabMode == EnumTabMode.NewItemGoesToGroup)
                        {
                            tab.Vm.Tag = server.GroupName;
                        }
                        else if (SystemConfig.Instance.General.TabMode == EnumTabMode.NewItemGoesToProtocol)
                        {
                            tab.Vm.Tag = server.ProtocolDisplayName;
                        }
                    }
                    tab.Activate();
                    var size = tab.GetTabContentSize();
                    var host = ProtocolHostFactory.Get(server, size.Width, size.Height);
                    host.OnClosed            += OnProtocolClose;
                    host.OnFullScreen2Window += OnFullScreen2Window;
                    host.ParentWindow         = tab;
                    tab.Vm.Items.Add(new TabItemViewModel()
                    {
                        Content = host,
                        Header  = server.DispName,
                    });
                    tab.Vm.SelectedItem = tab.Vm.Items.Last();
                    host.Conn();
                    _protocolHosts.Add(host.ConnectionId, host);
                    SimpleLogHelper.Debug($@"Start Conn: {server.DispName}({server.GetHashCode()}) by host({host.GetHashCode()}) with Tab({tab.GetHashCode()})");
                    SimpleLogHelper.Debug($@"ProtocolHosts.Count = {_protocolHosts.Count}, FullWin.Count = {_host2FullScreenWindows.Count}, _tabWindows.Count = {_tabWindows.Count}");
                }
            }
            catch (Exception e)
            {
                CloseEmpytTab();
                SimpleLogHelper.Error(e);
                MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Esempio n. 3
0
        public void MoveProtocolHostToFullScreen(string connectionId)
        {
            if (_protocolHosts.ContainsKey(connectionId))
            {
                var host = _protocolHosts[connectionId];

                // remove from old parent
                TabWindow tab = null;
                {
                    var tabs = _tabWindows.Values.Where(x => x.Vm.Items.Any(y => y.Content == host)).ToArray();
                    if (tabs.Length > 0)
                    {
                        tab = tabs.First();
                        foreach (var t in tabs)
                        {
                            var items = t.Vm.Items.ToArray().Where(x => x.Content == host);
                            foreach (var item in items.ToArray())
                            {
                                t.Vm.Items.Remove(item);
                                if (t.Vm.Items.Count > 0)
                                {
                                    t.Vm.SelectedItem = tab.Vm.Items.First();
                                }
                                SimpleLogHelper.Debug($@"Remove host({host.GetHashCode()}) from tab({t.GetHashCode()})");
                            }
                        }
                    }
                }



                FullScreenWindow full;
                if (_host2FullScreenWindows.ContainsKey(connectionId))
                {
                    full = _host2FullScreenWindows[connectionId];
                    full.LastTabToken = "";
                    // full screen placement
                    if (tab != null)
                    {
                        var screenEx = ScreenInfoEx.GetCurrentScreen(tab);
                        full.Top          = screenEx.VirtualWorkingAreaCenter.Y - full.Height / 2;
                        full.Left         = screenEx.VirtualWorkingAreaCenter.X - full.Width / 2;
                        full.LastTabToken = _lastTabToken;
                    }
                    full.Show();
                    full.SetProtocolHost(host);
                    host.ParentWindow = full;
                    host.GoFullScreen();
                }
                else
                {
                    // move to full
                    full = new FullScreenWindow {
                        LastTabToken = ""
                    };

                    // full screen placement
                    ScreenInfoEx screenEx;
                    if (tab != null)
                    {
                        screenEx          = ScreenInfoEx.GetCurrentScreen(tab);
                        full.LastTabToken = _lastTabToken;
                    }
                    else if (host.ProtocolServer is ProtocolServerRDP rdp &&
                             rdp.RdpFullScreenFlag == ERdpFullScreenFlag.EnableFullScreen &&
                             rdp.AutoSetting.FullScreenLastSessionScreenIndex >= 0 &&
                             rdp.AutoSetting.FullScreenLastSessionScreenIndex < Screen.AllScreens.Length)
                    {
                        screenEx = ScreenInfoEx.GetCurrentScreen(rdp.AutoSetting.FullScreenLastSessionScreenIndex);
                    }
                    else
                    {
                        screenEx = ScreenInfoEx.GetCurrentScreen(App.Window);
                    }
                    full.WindowStartupLocation = WindowStartupLocation.Manual;
                    full.Top  = screenEx.VirtualWorkingAreaCenter.Y - full.Height / 2;
                    full.Left = screenEx.VirtualWorkingAreaCenter.X - full.Width / 2;
                    full.SetProtocolHost(host);
                    host.ParentWindow = full;
                    full.Loaded      += (sender, args) => { host.GoFullScreen(); };
                    full.Show();
                    AddFull(full);
                }
Esempio n. 4
0
        private void App_OnStartup(object sender, StartupEventArgs startupEvent)
        {
            try
            {
                {
                    var appDateFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), SystemConfig.AppName);
                    if (!Directory.Exists(appDateFolder))
                    {
                        Directory.CreateDirectory(appDateFolder);
                    }
                    var logFilePath = Path.Combine(appDateFolder, "PRemoteM.log.md");
                    SimpleLogHelper.LogFileName = logFilePath;
                }

                #region single-instance app
                var startupMode = PRM.Core.Ulits.StartupMode.Normal;
                if (startupEvent.Args.Length > 0)
                {
                    System.Enum.TryParse(startupEvent.Args[0], out startupMode);
                }
                if (startupMode == PRM.Core.Ulits.StartupMode.SetSelfStart)
                {
                    SetSelfStartingHelper.SetSelfStart();
                    Environment.Exit(0);
                }
                if (startupMode == PRM.Core.Ulits.StartupMode.UnsetSelfStart)
                {
                    SetSelfStartingHelper.UnsetSelfStart();
                    Environment.Exit(0);
                }
                _singleAppMutex = new Mutex(true, PipeName, out var isFirst);
                if (!isFirst)
                {
                    try
                    {
                        var client = new NamedPipeClientStream(PipeName);
                        client.Connect();
                        StreamReader reader = new StreamReader(client);
                        StreamWriter writer = new StreamWriter(client);
                        writer.WriteLine("ActivateMe");
                        writer.Flush();
                        client.Dispose();
                    }
                    catch (Exception e)
                    {
                        SimpleLogHelper.Warning(e);
                    }

                    Environment.Exit(0);
                }
                else
                {
                    Task.Factory.StartNew(() =>
                    {
                        NamedPipeServerStream server = null;
                        while (true)
                        {
                            server?.Dispose();
                            server = new NamedPipeServerStream(PipeName);
                            SimpleLogHelper.Debug("NamedPipeServerStream.WaitForConnection");
                            server.WaitForConnection();

                            try
                            {
                                var reader = new StreamReader(server);
                                var line   = reader.ReadLine();
                                if (!string.IsNullOrEmpty(line))
                                {
                                    SimpleLogHelper.Debug("NamedPipeServerStream get: " + line);
                                    if (line == "ActivateMe")
                                    {
                                        if (App.Window != null)
                                        {
                                            Dispatcher.Invoke(() =>
                                            {
                                                if (App.Window.WindowState == WindowState.Minimized)
                                                {
                                                    App.Window.WindowState = WindowState.Normal;
                                                }
                                                App.Window.ActivateMe();
                                            });
                                        }
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                SimpleLogHelper.Warning(e);
                            }
                        }
                    });
                }
                #endregion


#if DEBUG
                Shawn.Ulits.ConsoleManager.Show();
#endif

                #region system check & init


                #region Init
                {
                    var appDateFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), SystemConfig.AppName);
                    if (!Directory.Exists(appDateFolder))
                    {
                        Directory.CreateDirectory(appDateFolder);
                    }
                    SimpleLogHelper.LogFileName = Path.Combine(appDateFolder, "PRemoteM.log.md");
                    var iniPath = Path.Combine(appDateFolder, SystemConfig.AppName + ".ini");
                    if (Environment.CurrentDirectory.IndexOf(@"C:\Windows") < 0)
                    {
                        if (File.Exists(SystemConfig.AppName + ".ini") ||
                            IOPermissionHelper.HasWritePermissionOnDir("./"))
                        {
                            iniPath = SystemConfig.AppName + ".ini";
                        }
                    }
                    var ini = new Ini(iniPath);
                    //if (!File.Exists(iniPath))
                    //{
                    //    // TODO if ini is not existed, then it would be a new user, open guide to set db path
                    //}

                    // Set default folder path
                    SystemConfigLanguage.LanguageJsonDir = Path.Combine(appDateFolder, SystemConfigLanguage.LanguageJsonDir);
                    PuttyColorThemes.ThemeRegFileFolder  = Path.Combine(appDateFolder, PuttyColorThemes.ThemeRegFileFolder);

                    var language     = new SystemConfigLanguage(this.Resources, ini);
                    var general      = new SystemConfigGeneral(ini);
                    var quickConnect = new SystemConfigQuickConnect(ini);
                    var theme        = new SystemConfigTheme(this.Resources, ini);
                    var dataSecurity = new SystemConfigDataSecurity(ini);


                    //if (!File.Exists(dataSecurity.DbPath))
                    //{
                    //    // TODO db is not existed, then tell our user to create new one or select a new one.
                    //}

                    // config create instance (settings & langs)
                    SystemConfig.Init();
                    SystemConfig.Instance.General      = general;
                    SystemConfig.Instance.Language     = language;
                    SystemConfig.Instance.QuickConnect = quickConnect;
                    SystemConfig.Instance.DataSecurity = dataSecurity;
                    SystemConfig.Instance.Theme        = theme;

                    // server data holder init.
                    GlobalData.Init();

                    // remote window pool init.
                    RemoteWindowPool.Init();
                }
                #endregion

                // kill putty process
                foreach (var process in Process.GetProcessesByName(PuttyHost.PuttyExeName.ToLower().Replace(".exe", "")))
                {
                    try
                    {
                        process.Kill();
                    }
                    catch
                    {
                    }
                }



                #endregion


                #region app start
                // main window init
                {
                    Window         = new MainWindow();
                    ShutdownMode   = ShutdownMode.OnMainWindowClose;
                    MainWindow     = Window;
                    Window.Closed += (o, args) => { AppOnClose(); };
                    if (!SystemConfig.Instance.General.AppStartMinimized)
                    {
                        ActivateWindow();
                    }

                    // check if Db is ok
                    var res = SystemConfig.Instance.DataSecurity.CheckIfDbIsOk();
                    if (!res.Item1)
                    {
                        SimpleLogHelper.Info("Start with 'SystemConfigPage' by 'ErroFlag'.");
                        MessageBox.Show(res.Item2, SystemConfig.Instance.Language.GetText("messagebox_title_error"));
                        ActivateWindow();
                        Window.VmMain.CmdGoSysOptionsPage.Execute(typeof(SystemConfigDataSecurity));
                    }
                    else
                    {
                        // load data
                        GlobalData.Instance.ServerListUpdate();
                    }
                }


                // task tray init
                InitTaskTray();


                // quick search init
                InitQuickSearch();
                #endregion
            }
            catch (Exception ex)
            {
                SimpleLogHelper.Fatal(ex.Message, ex.StackTrace);
#if DEBUG
                MessageBox.Show(ex.Message);
                MessageBox.Show(ex.StackTrace);
#endif
                AppOnClose(-1);
            }
        }
Esempio n. 5
0
        public void ShowRemoteHost(uint id)
        {
            Debug.Assert(id > 0);
            Debug.Assert(GlobalData.Instance.ServerList.Any(x => x.Id == id));
            var server = GlobalData.Instance.ServerList.First(x => x.Id == id);

            // update last conn time
            server.LastConnTime = DateTime.Now;
            Server.AddOrUpdate(server);

            // start conn
            if (server.OnlyOneInstance && _protocolHosts.ContainsKey(id.ToString()))
            {
                _protocolHosts[id.ToString()].ParentWindow?.Activate();
                return;
            }

            TabWindow tab = null;

            try
            {
                if (server.IsConnWithFullScreen())
                {
                    // for those people using 2+ monitor which are in different scale factors, we will try "mstsc.exe" instead of "PRemoteM".
                    if (Screen.AllScreens.Length > 1 &&
                        server is ProtocolServerRDP rdp &&
                        rdp.RdpFullScreenFlag == ERdpFullScreenFlag.EnableFullAllScreens)
                    {
                        int factor = (int)(new ScreenInfoEx(Screen.PrimaryScreen).ScaleFactor * 100);
                        // check if screens are in different scale factors
                        bool differentScaleFactorFlag = Screen.AllScreens.Select(screen => (int)(new ScreenInfoEx(screen).ScaleFactor * 100)).Any(factor2 => factor != factor2);
                        if (differentScaleFactorFlag)
                        {
                            var tmp     = Path.GetTempPath();
                            var dp      = rdp.DispName;
                            var invalid = new string(Path.GetInvalidFileNameChars()) +
                                          new string(Path.GetInvalidPathChars());
                            dp = invalid.Aggregate(dp, (current, c) => current.Replace(c.ToString(), ""));
                            var rdpFile = Path.Combine(tmp, dp + ".rdp");
                            try
                            {
                                File.WriteAllText(rdpFile, rdp.ToRdpConfig().ToString());
                                var p = new Process
                                {
                                    StartInfo =
                                    {
                                        FileName               = "cmd.exe",
                                        UseShellExecute        = false,
                                        RedirectStandardInput  = true,
                                        RedirectStandardOutput = true,
                                        RedirectStandardError  = true,
                                        CreateNoWindow         = true
                                    }
                                };
                                p.Start();
                                p.StandardInput.WriteLine("mstsc -admin " + rdpFile);
                                p.StandardInput.WriteLine("exit");
                            }
                            catch (Exception)
                            {
                                throw;
                            }
                            finally
                            {
                                var t = new Task(() =>
                                {
                                    Thread.Sleep(1000 * 10);
                                    if (File.Exists(rdpFile))
                                    {
                                        File.Delete(rdpFile);
                                    }
                                });
                                t.Start();
                            }
                            return;
                        }
                    }


                    var host = ProtocolHostFactory.Get(server);
                    host.OnClosed            += OnProtocolClose;
                    host.OnFullScreen2Window += OnFullScreen2Window;
                    AddProtocolHost(host);
                    MoveProtocolHostToFullScreen(host.ConnectionId);
                    host.Conn();
                    SimpleLogHelper.Debug($@"Start Conn: {server.DispName}({server.GetHashCode()}) by host({host.GetHashCode()}) with full");
                }
                else
                {
                    if (!string.IsNullOrEmpty(_lastTabToken) && _tabWindows.ContainsKey(_lastTabToken))
                    {
                        tab = _tabWindows[_lastTabToken];
                    }
                    else
                    {
                        var token = DateTime.Now.Ticks.ToString();
                        AddTab(new TabWindow(token));
                        tab = _tabWindows[token];
                        tab.Show();
                        _lastTabToken = token;
                    }
                    tab.Activate();
                    var size = tab.GetTabContentSize();
                    var host = ProtocolHostFactory.Get(server, size.Width, size.Height);
                    host.OnClosed            += OnProtocolClose;
                    host.OnFullScreen2Window += OnFullScreen2Window;
                    host.ParentWindow         = tab;
                    tab.Vm.Items.Add(new TabItemViewModel()
                    {
                        Content = host,
                        Header  = server.DispName,
                    });
                    tab.Vm.SelectedItem = tab.Vm.Items.Last();
                    host.Conn();
                    _protocolHosts.Add(host.ConnectionId, host);
                    SimpleLogHelper.Debug($@"Start Conn: {server.DispName}({server.GetHashCode()}) by host({host.GetHashCode()}) with Tab({tab.GetHashCode()})");
                    SimpleLogHelper.Debug($@"ProtocolHosts.Count = {_protocolHosts.Count}, FullWin.Count = {_host2FullScreenWindows.Count}, _tabWindows.Count = {_tabWindows.Count}");
                }
            }
            catch (Exception e)
            {
                if (tab?.Vm != null && (tab.Vm?.Items?.Count ?? 0) == 0)
                {
                    CloseTabWindow(tab.Vm.Token);
                }
                SimpleLogHelper.Error(e);
                MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Esempio n. 6
0
        private void InitRdp(double width = 0, double height = 0)
        {
            _rdp.CreateControl();
            #region server info
            // server info
            _rdp.Server   = _rdpServer.Address;
            _rdp.UserName = _rdpServer.UserName;
            _rdp.AdvancedSettings2.RDPPort = _rdpServer.GetPort();
            var secured = (MSTSCLib.IMsTscNonScriptable)_rdp.GetOcx();
            secured.ClearTextPassword = _rdpServer.GetDecryptPassWord();
            _rdp.FullScreenTitle      = _rdpServer.DispName + " - " + _rdpServer.SubTitle;
            #endregion


            // enable CredSSP, will use CredSsp if the client supports.
            _rdp.AdvancedSettings7.EnableCredSspSupport = true;
            _rdp.AdvancedSettings2.EncryptionEnabled    = 1;
            _rdp.AdvancedSettings5.AuthenticationLevel  = 0;
            _rdp.AdvancedSettings5.EnableAutoReconnect  = true;
            // setting PublicMode to false allows the saving of credentials, which prevents
            _rdp.AdvancedSettings6.PublicMode               = false;
            _rdp.AdvancedSettings5.EnableWindowsKey         = 1;
            _rdp.AdvancedSettings5.GrabFocusOnConnect       = true;
            _rdp.AdvancedSettings2.keepAliveInterval        = 1000 * 60 * 5; // 1000 = 1000 ms
            _rdp.AdvancedSettings2.overallConnectionTimeout = 600;           // The new time, in seconds. The maximum value is 600, which represents 10 minutes.
            //// ref: https://docs.microsoft.com/en-us/windows/win32/termserv/imsrdpclientadvancedsettings6-connecttoadministerserver
            //_rdp.AdvancedSettings7.ConnectToAdministerServer = true;

            #region Others

            // enable CredSSP, will use CredSsp if the client supports.
            _rdp.AdvancedSettings9.EnableCredSspSupport = true;

            //- 0: If server authentication fails, connect to the computer without warning (Connect and don't warn me)
            //- 1: If server authentication fails, don't establish a connection (Don't connect)
            //- 2: If server authentication fails, show a warning and allow me to connect or refuse the connection (Warn me)
            //- 3: No authentication requirement specified.
            _rdp.AdvancedSettings9.AuthenticationLevel = 0;

            // setting PublicMode to false allows the saving of credentials, which prevents
            _rdp.AdvancedSettings9.PublicMode          = false;
            _rdp.AdvancedSettings9.EnableAutoReconnect = true;


            // - 0 Apply key combinations only locally at the client computer.
            // - 1 Apply key combinations at the remote server.
            // - 2 Apply key combinations to the remote server only when the client is running in full-screen mode. This is the default value.
            _rdp.SecuredSettings3.KeyboardHookMode = 2;

            #endregion

            #region conn bar
            _rdp.AdvancedSettings6.DisplayConnectionBar            = _rdpServer.IsFullScreenWithConnectionBar;
            _rdp.AdvancedSettings6.ConnectionBarShowPinButton      = true;
            _rdp.AdvancedSettings6.PinConnectionBar                = false;
            _rdp.AdvancedSettings6.ConnectionBarShowMinimizeButton = true;
            _rdp.AdvancedSettings6.ConnectionBarShowRestoreButton  = true;
            _rdp.AdvancedSettings6.BitmapVirtualCache32BppSize     = 48;
            #endregion

            #region Redirect

            _rdp.AdvancedSettings9.RedirectDrives     = _rdpServer.EnableDiskDrives;
            _rdp.AdvancedSettings9.RedirectClipboard  = _rdpServer.EnableClipboard;
            _rdp.AdvancedSettings9.RedirectPrinters   = _rdpServer.EnablePrinters;
            _rdp.AdvancedSettings9.RedirectPOSDevices = _rdpServer.EnablePorts;
            _rdp.AdvancedSettings9.RedirectSmartCards = _rdpServer.EnableSmartCardsAndWinHello;

            if (_rdpServer.EnableKeyCombinations)
            {
                // - 0 Apply key combinations only locally at the client computer.
                // - 1 Apply key combinations at the remote server.
                // - 2 Apply key combinations to the remote server only when the client is running in full-screen mode. This is the default value.
                _rdp.SecuredSettings3.KeyboardHookMode = 1;
            }
            else
            {
                _rdp.SecuredSettings3.KeyboardHookMode = 0;
            }

            if (_rdpServer.EnableSounds)
            {
                // - 0 Redirect sounds to the client. This is the default value.
                // - 1 Play sounds at the remote computer.
                // - 2 Disable sound redirection; do not play sounds at the server.
                _rdp.SecuredSettings3.AudioRedirectionMode = 0;
                // - 0 (Audio redirection is enabled and the option for redirection is "Bring to this computer". This is the default mode.)
                // - 1 (Audio redirection is enabled and the option is "Leave at remote computer". The "Leave at remote computer" option is supported only when connecting remotely to a host computer that is running Windows Vista. If the connection is to a host computer that is running Windows Server 2008, the option "Leave at remote computer" is changed to "Do not play".)
                // - 2 (Audio redirection is enabled and the mode is "Do not play".)
                _rdp.AdvancedSettings6.AudioRedirectionMode = 0;

                // - 0 Dynamic audio quality. This is the default audio quality setting. The server dynamically adjusts audio output quality in response to network conditions and the client and server capabilities.
                // - 1 Medium audio quality. The server uses a fixed but compressed format for audio output.
                // - 2 High audio quality. The server provides audio output in uncompressed PCM format with lower processing overhead for latency.
                _rdp.AdvancedSettings8.AudioQualityMode = 0;
            }
            else
            {
                // - 2 Disable sound redirection; do not play sounds at the server.
                _rdp.SecuredSettings3.AudioRedirectionMode  = 2;
                _rdp.AdvancedSettings6.AudioRedirectionMode = 2;
            }

            if (_rdpServer.EnableAudioCapture)
            {
                // indicates whether the default audio input device is redirected from the client to the remote session
                _rdp.AdvancedSettings8.AudioCaptureRedirectionMode = true;
            }
            else
            {
                _rdp.AdvancedSettings8.AudioCaptureRedirectionMode = false;
            }
            #endregion


            #region Display

            ReadScaleFactor();
            _rdp.SetExtendedProperty("DesktopScaleFactor", _primaryScaleFactor);
            _rdp.SetExtendedProperty("DeviceScaleFactor", (uint)100);
            if (_rdpServer.RdpWindowResizeMode == ERdpWindowResizeMode.Stretch ||
                _rdpServer.RdpWindowResizeMode == ERdpWindowResizeMode.StretchFullScreen)
            {
                _rdp.AdvancedSettings2.SmartSizing = true;
            }
            // to enhance user experience, i let the form handled full screen
            _rdp.AdvancedSettings6.ContainerHandledFullScreen = 1;

            if (_rdpServer.RdpFullScreenFlag != ERdpFullScreenFlag.EnableFullAllScreens)
            {
                switch (_rdpServer.RdpWindowResizeMode)
                {
                case ERdpWindowResizeMode.Stretch:
                case ERdpWindowResizeMode.Fixed:
                    _rdp.DesktopWidth  = (int)(_rdpServer.RdpWidth / (_primaryScaleFactor / 100.0));
                    _rdp.DesktopHeight = (int)(_rdpServer.RdpHeight / (_primaryScaleFactor / 100.0));
                    break;

                case ERdpWindowResizeMode.StretchFullScreen:
                case ERdpWindowResizeMode.FixedFullScreen:
                    var screenSize = GetScreenSize();
                    _rdp.DesktopWidth  = (int)(screenSize.Width);
                    _rdp.DesktopHeight = (int)(screenSize.Height);
                    break;

                case ERdpWindowResizeMode.AutoResize:
                default:
                    if (width > 100 && height > 100)
                    {
                        _rdp.DesktopWidth  = (int)(width * (_primaryScaleFactor / 100.0));
                        _rdp.DesktopHeight = (int)(height * (_primaryScaleFactor / 100.0));
                    }
                    else
                    {
                        _rdp.DesktopWidth  = (int)(800 * (_primaryScaleFactor / 100.0));
                        _rdp.DesktopHeight = (int)(600 * (_primaryScaleFactor / 100.0));
                    }
                    break;
                }
            }



            switch (_rdpServer.RdpFullScreenFlag)
            {
            case ERdpFullScreenFlag.Disable:
                base.CanFullScreen = false;
                break;

            case ERdpFullScreenFlag.EnableFullScreen:
                base.CanFullScreen = true;
                if (_rdpServer.IsConnWithFullScreen || (_rdpServer.AutoSetting?.FullScreenLastSessionIsFullScreen ?? false))
                {
                    var screenSize = GetScreenSize();
                    _rdp.DesktopWidth  = (int)(screenSize.Width);
                    _rdp.DesktopHeight = (int)(screenSize.Height);
                    _rdp.FullScreen    = true;
                }
                break;

            case ERdpFullScreenFlag.EnableFullAllScreens:
                base.CanFullScreen = true;
                if (Screen.AllScreens.Length == 1)
                {
                    var screenSize = GetScreenSize();
                    _rdp.DesktopWidth  = (int)(screenSize.Width);
                    _rdp.DesktopHeight = (int)(screenSize.Height);
                }
                ((IMsRdpClientNonScriptable5)_rdp.GetOcx()).UseMultimon = true;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            #endregion

            #region Performance
            // ref: https://docs.microsoft.com/en-us/windows/win32/termserv/imsrdpclientadvancedsettings-performanceflags
            int nDisplayPerformanceFlag = 0;
            if (_rdpServer.DisplayPerformance != EDisplayPerformance.Auto)
            {
                _rdp.AdvancedSettings9.BandwidthDetection = false;
                // ref: https://docs.microsoft.com/en-us/windows/win32/termserv/imsrdpclientadvancedsettings7-networkconnectiontype
                // CONNECTION_TYPE_MODEM (1 (0x1)) Modem (56 Kbps)
                // CONNECTION_TYPE_BROADBAND_LOW (2 (0x2)) Low-speed broadband (256 Kbps to 2 Mbps) CONNECTION_TYPE_SATELLITE (3 (0x3)) Satellite (2 Mbps to 16 Mbps, with high latency)
                // CONNECTION_TYPE_BROADBAND_HIGH (4 (0x4)) High-speed broadband (2 Mbps to 10 Mbps) CONNECTION_TYPE_WAN (5 (0x5)) Wide area network (WAN) (10 Mbps or higher, with high latency)
                // CONNECTION_TYPE_LAN (6 (0x6)) Local area network (LAN) (10 Mbps or higher)
                _rdp.AdvancedSettings8.NetworkConnectionType = 1;
                switch (_rdpServer.DisplayPerformance)
                {
                case EDisplayPerformance.Auto:
                    break;

                case EDisplayPerformance.Low:
                    // 8,16,24,32
                    _rdp.ColorDepth          = 8;
                    nDisplayPerformanceFlag += 0x00000001;    //TS_PERF_DISABLE_WALLPAPER;      Wallpaper on the desktop is not displayed.
                    nDisplayPerformanceFlag += 0x00000002;    //TS_PERF_DISABLE_FULLWINDOWDRAG; Full-window drag is disabled; only the window outline is displayed when the window is moved.
                    nDisplayPerformanceFlag += 0x00000004;    //TS_PERF_DISABLE_MENUANIMATIONS; Menu animations are disabled.
                    nDisplayPerformanceFlag += 0x00000008;    //TS_PERF_DISABLE_THEMING ;       Themes are disabled.
                    nDisplayPerformanceFlag += 0x00000020;    //TS_PERF_DISABLE_CURSOR_SHADOW;  No shadow is displayed for the cursor.
                    nDisplayPerformanceFlag += 0x00000040;    //TS_PERF_DISABLE_CURSORSETTINGS; Cursor blinking is disabled.
                    break;

                case EDisplayPerformance.Middle:
                    _rdp.ColorDepth          = 16;
                    nDisplayPerformanceFlag += 0x00000001;    //TS_PERF_DISABLE_WALLPAPER;      Wallpaper on the desktop is not displayed.
                    nDisplayPerformanceFlag += 0x00000002;    //TS_PERF_DISABLE_FULLWINDOWDRAG; Full-window drag is disabled; only the window outline is displayed when the window is moved.
                    nDisplayPerformanceFlag += 0x00000004;    //TS_PERF_DISABLE_MENUANIMATIONS; Menu animations are disabled.
                    nDisplayPerformanceFlag += 0x00000008;    //TS_PERF_DISABLE_THEMING ;       Themes are disabled.
                    nDisplayPerformanceFlag += 0x00000020;    //TS_PERF_DISABLE_CURSOR_SHADOW;  No shadow is displayed for the cursor.
                    nDisplayPerformanceFlag += 0x00000040;    //TS_PERF_DISABLE_CURSORSETTINGS; Cursor blinking is disabled.
                    nDisplayPerformanceFlag += 0x00000080;    //TS_PERF_ENABLE_FONT_SMOOTHING;        Enable font smoothing.
                    nDisplayPerformanceFlag += 0x00000100;    //TS_PERF_ENABLE_DESKTOP_COMPOSITION ;  Enable desktop composition.

                    break;

                case EDisplayPerformance.High:
                    _rdp.ColorDepth          = 32;
                    nDisplayPerformanceFlag += 0x00000080;    //TS_PERF_ENABLE_FONT_SMOOTHING;        Enable font smoothing.
                    nDisplayPerformanceFlag += 0x00000100;    //TS_PERF_ENABLE_DESKTOP_COMPOSITION ;  Enable desktop composition.
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            SimpleLogHelper.Debug("RdpInit: DisplayPerformance = " + _rdpServer.DisplayPerformance + ", flag = " + Convert.ToString(nDisplayPerformanceFlag, 2));
            _rdp.AdvancedSettings9.PerformanceFlags = nDisplayPerformanceFlag;

            #endregion
        }