diff --git a/Directory.Packages.props b/Directory.Packages.props index 3e71b499..512653c3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,8 +5,8 @@ $(NoWarn);NU1507 - - + + @@ -17,7 +17,7 @@ - + diff --git a/mRemoteNG/App/Info/GeneralAppInfo.cs b/mRemoteNG/App/Info/GeneralAppInfo.cs index 77c021fc..ee352faa 100644 --- a/mRemoteNG/App/Info/GeneralAppInfo.cs +++ b/mRemoteNG/App/Info/GeneralAppInfo.cs @@ -15,7 +15,9 @@ namespace mRemoteNG.App.Info { public const string UrlHome = "https://mremoteng.org"; public const string UrlDonate = "https://mremoteng.org/contribute"; - public const string UrlForum = "https://www.reddit.com/r/mRemoteNG"; + public const string UrlForum = "https://github.com/orgs/mRemoteNG/discussions"; + public const string UrlChat = "https://app.element.io/#/room/#mremoteng:matrix.org"; + public const string UrlCommunity = "https://www.reddit.com/r/mRemoteNG"; public const string UrlBugs = "https://github.com/mRemoteNG/mRemoteNG/issues/new"; public const string UrlDocumentation = "https://mremoteng.readthedocs.io/en/latest/"; public static readonly string ApplicationVersion = Application.ProductVersion; diff --git a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializer.cs b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializer.cs index 8b8f3cc7..8b38f6ef 100644 --- a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializer.cs +++ b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializer.cs @@ -29,7 +29,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider) { XAttribute attribute = new(XName.Get("Protected"), ""); - string plainText = rootNodeInfo.Password ? "ThisIsProtected" : "ThisIsNotProtected"; + string plainText = (rootNodeInfo.PasswordString != rootNodeInfo.DefaultPassword) ? "ThisIsProtected" : "ThisIsNotProtected"; System.Security.SecureString encryptionPassword = rootNodeInfo.PasswordString.ConvertToSecureString(); attribute.Value = cryptographyProvider.Encrypt(plainText, encryptionPassword); return attribute; diff --git a/mRemoteNG/Connection/ConnectionInitiator.cs b/mRemoteNG/Connection/ConnectionInitiator.cs index 7f8db040..6aeca46b 100644 --- a/mRemoteNG/Connection/ConnectionInitiator.cs +++ b/mRemoteNG/Connection/ConnectionInitiator.cs @@ -320,7 +320,8 @@ namespace mRemoteNG.Connection ConnectionWindow connectionForm = conForm ?? Runtime.WindowList.FromString(connectionPanel) as ConnectionWindow; if (connectionForm == null) - connectionForm = _panelAdder.AddPanel(connectionPanel); + // Don't show the panel immediately - it will be shown when first tab is added + connectionForm = _panelAdder.AddPanel(connectionPanel, showImmediately: false); else connectionForm.Show(FrmMain.Default.pnlDock); diff --git a/mRemoteNG/Language/Language.Designer.cs b/mRemoteNG/Language/Language.Designer.cs index fbcbaf71..d69a9c50 100644 --- a/mRemoteNG/Language/Language.Designer.cs +++ b/mRemoteNG/Language/Language.Designer.cs @@ -213,15 +213,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to About. - /// - internal static string About { - get { - return ResourceManager.GetString("About", resourceCulture); - } - } - /// /// Looks up a localized string similar to Hidden. /// @@ -735,15 +726,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Check for Updates. - /// - internal static string CheckForUpdates { - get { - return ResourceManager.GetString("CheckForUpdates", resourceCulture); - } - } - /// /// Looks up a localized string similar to Check for updates at startup. /// @@ -1708,15 +1690,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Donate. - /// - internal static string Donate { - get { - return ResourceManager.GetString("Donate", resourceCulture); - } - } - /// /// Looks up a localized string similar to Do not play. /// @@ -2585,15 +2558,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to mRemoteNG Help. - /// - internal static string HelpContents { - get { - return ResourceManager.GetString("HelpContents", resourceCulture); - } - } - /// /// Looks up a localized string similar to High. /// @@ -3116,6 +3080,87 @@ namespace mRemoteNG.Resources.Language { } } + /// + /// Looks up a localized string similar to About. + /// + internal static string MenuItem_About { + get { + return ResourceManager.GetString("MenuItem_About", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mR Chat. + /// + internal static string MenuItem_Chat { + get { + return ResourceManager.GetString("MenuItem_Chat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Check for Updates. + /// + internal static string MenuItem_CheckForUpdates { + get { + return ResourceManager.GetString("MenuItem_CheckForUpdates", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Community. + /// + internal static string MenuItem_Community { + get { + return ResourceManager.GetString("MenuItem_Community", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Donate. + /// + internal static string MenuItem_Donate { + get { + return ResourceManager.GetString("MenuItem_Donate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mRemoteNG Help. + /// + internal static string MenuItem_HelpContents { + get { + return ResourceManager.GetString("MenuItem_HelpContents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Report an Issue. + /// + internal static string MenuItem_ReportIssue { + get { + return ResourceManager.GetString("MenuItem_ReportIssue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Support Forum. + /// + internal static string MenuItem_SupportForum { + get { + return ResourceManager.GetString("MenuItem_SupportForum", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Website. + /// + internal static string MenuItem_Website { + get { + return ResourceManager.GetString("MenuItem_Website", resourceCulture); + } + } + /// /// Looks up a localized string similar to Message. /// @@ -5640,15 +5685,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Report a Bug. - /// - internal static string ReportBug { - get { - return ResourceManager.GetString("ReportBug", resourceCulture); - } - } - /// /// Looks up a localized string similar to Reset layout. /// @@ -5739,6 +5775,24 @@ namespace mRemoteNG.Resources.Language { } } + /// + /// Looks up a localized string similar to Do you want to save the changes made to the options?. + /// + internal static string SaveOptionsBeforeClosing { + get { + return ResourceManager.GetString("SaveOptionsBeforeClosing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Discard. + /// + internal static string Discard { + get { + return ResourceManager.GetString("Discard", resourceCulture); + } + } + /// /// Looks up a localized string similar to SaveConnectionsOnExit. /// @@ -6315,15 +6369,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Support Forum. - /// - internal static string SupportForum { - get { - return ResourceManager.GetString("SupportForum", resourceCulture); - } - } - /// /// Looks up a localized string similar to Switch to Notifications panel on:. /// @@ -7108,15 +7153,6 @@ namespace mRemoteNG.Resources.Language { } } - /// - /// Looks up a localized string similar to Website. - /// - internal static string Website { - get { - return ResourceManager.GetString("Website", resourceCulture); - } - } - /// /// Looks up a localized string similar to WebView2InitializationFailed. /// diff --git a/mRemoteNG/Language/Language.cs-CZ.resx b/mRemoteNG/Language/Language.cs-CZ.resx index 9fa17507..a324506e 100644 --- a/mRemoteNG/Language/Language.cs-CZ.resx +++ b/mRemoteNG/Language/Language.cs-CZ.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + O Aplikaci @@ -712,7 +712,7 @@ Otevírám nový prázdný soubor seznamu spojení. Nový panel spojení - + Vyhledat aktualizace @@ -733,7 +733,7 @@ Otevírám nový prázdný soubor seznamu spojení. Smazat vnější nástroj... - + Přispějte @@ -751,7 +751,7 @@ Otevírám nový prázdný soubor seznamu spojení. &Nápověda - + Nápověda mRemoteNG @@ -793,7 +793,7 @@ Otevírám nový prázdný soubor seznamu spojení. Přejmonovat záložku tabu - + Nahlásit chybu @@ -823,7 +823,7 @@ Otevírám nový prázdný soubor seznamu spojení. Spustit (VNC) chat - + Diskuzní fórum podpory @@ -838,7 +838,7 @@ Otevírám nový prázdný soubor seznamu spojení. Pouze prohlížet (VNC) - + Webová stránka diff --git a/mRemoteNG/Language/Language.de.resx b/mRemoteNG/Language/Language.de.resx index c12f1f3c..eaf5cbf3 100644 --- a/mRemoteNG/Language/Language.de.resx +++ b/mRemoteNG/Language/Language.de.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Über @@ -698,7 +698,7 @@ Starte mit neuer Datei. Verbindungs-Panel hinzufügen - + Suche nach Updates @@ -719,7 +719,7 @@ Starte mit neuer Datei. Entfernen - + Spenden @@ -737,7 +737,7 @@ Starte mit neuer Datei. &Hilfe - + Hilfe @@ -779,7 +779,7 @@ Starte mit neuer Datei. Tab umbenennen - + Fehler melden @@ -809,7 +809,7 @@ Starte mit neuer Datei. Chat starten (VNC) - + Forum @@ -824,7 +824,7 @@ Starte mit neuer Datei. View-Only-Modus - + Webseite diff --git a/mRemoteNG/Language/Language.el.resx b/mRemoteNG/Language/Language.el.resx index ace2cfb2..456b4941 100644 --- a/mRemoteNG/Language/Language.el.resx +++ b/mRemoteNG/Language/Language.el.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Σχετικά με diff --git a/mRemoteNG/Language/Language.es.resx b/mRemoteNG/Language/Language.es.resx index 4dc12c48..c3e70b6e 100644 --- a/mRemoteNG/Language/Language.es.resx +++ b/mRemoteNG/Language/Language.es.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Acerca de @@ -625,7 +625,7 @@ Arrancando con un nuevo archivo de conexiones. Agregar Panel de Conexión - + Comprobar Actualizaciones @@ -646,7 +646,7 @@ Arrancando con un nuevo archivo de conexiones. Borrar Herramienta Externa... - + Donar @@ -664,7 +664,7 @@ Arrancando con un nuevo archivo de conexiones. &Ayuda - + Ayuda de mRemoteNG @@ -706,7 +706,7 @@ Arrancando con un nuevo archivo de conexiones. Renombrar Pestaña - + Informar de un Bug @@ -736,7 +736,7 @@ Arrancando con un nuevo archivo de conexiones. Comenzar Chat (VNC) - + Foro de Soporte @@ -751,7 +751,7 @@ Arrancando con un nuevo archivo de conexiones. Solo Ver (VNC) - + Sitio Web diff --git a/mRemoteNG/Language/Language.fr.resx b/mRemoteNG/Language/Language.fr.resx index 88d73f50..e68e89d1 100644 --- a/mRemoteNG/Language/Language.fr.resx +++ b/mRemoteNG/Language/Language.fr.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + À propos @@ -719,7 +719,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour Ajouter un panneau de connexion - + Rechercher les mises à jour @@ -740,7 +740,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour Supprimer l'outil externe... - + Faire un don @@ -758,7 +758,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour &Aide - + Aide mRemoteNG @@ -800,7 +800,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour Renommer l'onglet - + Signaler un bug @@ -830,7 +830,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour Démarrer le chat (VNC) - + Forum du support @@ -845,7 +845,7 @@ Voir l'article de support Microsoft http://support.microsoft.com/kb/811833 pour Voir seulement (VNC) - + Site web diff --git a/mRemoteNG/Language/Language.hu.resx b/mRemoteNG/Language/Language.hu.resx index 5d5ae888..56870233 100644 --- a/mRemoteNG/Language/Language.hu.resx +++ b/mRemoteNG/Language/Language.hu.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Névjegy @@ -267,7 +267,7 @@ (Automatikus észlelés) - + Frissítés keresése @@ -294,7 +294,7 @@ Fül átnevezése - + Hibabejelentés @@ -306,7 +306,7 @@ Kapcsolatfájl mentése, mint... - + Honlap diff --git a/mRemoteNG/Language/Language.it.resx b/mRemoteNG/Language/Language.it.resx index 5a1b7dc3..6bc51d94 100644 --- a/mRemoteNG/Language/Language.it.resx +++ b/mRemoteNG/Language/Language.it.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Informazioni su @@ -622,7 +622,7 @@ Creazione di un nuovo file delle connessioni. Aggiungi pannello delle connessioni - + Verifica la presenza di aggiornamenti @@ -643,7 +643,7 @@ Creazione di un nuovo file delle connessioni. Elimina applicazione esterna... - + Effettua una donazione @@ -661,7 +661,7 @@ Creazione di un nuovo file delle connessioni. &Aiuto - + Guida di mRemoteNG @@ -703,7 +703,7 @@ Creazione di un nuovo file delle connessioni. Rinomina tab - + Segnala un bug @@ -733,7 +733,7 @@ Creazione di un nuovo file delle connessioni. Avvia chat (VNC) - + Forum di supporto @@ -748,7 +748,7 @@ Creazione di un nuovo file delle connessioni. Visualizza soltanto (VNC) - + Sito web diff --git a/mRemoteNG/Language/Language.ja-JP.resx b/mRemoteNG/Language/Language.ja-JP.resx index 5e2a58db..56b6f21b 100644 --- a/mRemoteNG/Language/Language.ja-JP.resx +++ b/mRemoteNG/Language/Language.ja-JP.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mRemoteNGについて @@ -723,7 +723,7 @@ Starting with new connections file. 接続表示パネルの追加 - + 最新バージョンをチェック @@ -744,7 +744,7 @@ Starting with new connections file. 外部ツールを削除... - + 寄付のお願い @@ -762,7 +762,7 @@ Starting with new connections file. ヘルプ(&H) - + mRemoteNGヘルプ @@ -804,7 +804,7 @@ Starting with new connections file. タブ名を変更 - + バグを報告する @@ -835,7 +835,7 @@ Starting with new connections file. Start Chat (VNC) - + サポートフォーラム @@ -850,7 +850,7 @@ Starting with new connections file. View Only (VNC) - + ウェブサイト(英語) diff --git a/mRemoteNG/Language/Language.ko-KR.resx b/mRemoteNG/Language/Language.ko-KR.resx index 2b537381..3d90db05 100644 --- a/mRemoteNG/Language/Language.ko-KR.resx +++ b/mRemoteNG/Language/Language.ko-KR.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mRemoteNG 정보 @@ -712,7 +712,7 @@ 연결 패널 추가 - + 업데이트 확인 @@ -733,7 +733,7 @@ 외부 도구를 삭제 ... - + 기부 @@ -751,7 +751,7 @@ 도움말(&H) - + mRemoteNG 도움말 @@ -793,7 +793,7 @@ 탭 이름 바꾸기 - + 버그 신고 @@ -823,7 +823,7 @@ 채팅 시작 (VNC) - + 지원 포럼 @@ -838,7 +838,7 @@ 보기 전용 (VNC) - + 웹 사이트 diff --git a/mRemoteNG/Language/Language.nb-NO.resx b/mRemoteNG/Language/Language.nb-NO.resx index 51efed4b..76748c96 100644 --- a/mRemoteNG/Language/Language.nb-NO.resx +++ b/mRemoteNG/Language/Language.nb-NO.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Om @@ -708,7 +708,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me Legg til tilkoblingspanel - + Se etter oppdateringer @@ -729,7 +729,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me Slett eksternt verktøy... - + Donér @@ -747,7 +747,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me &Hjelp - + mRemoteNG-hjelp @@ -789,7 +789,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me Gi nytt navn til fane - + Rapporter en feil @@ -819,7 +819,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me Start chat (VNC) - + Forum for brukerstøtte @@ -834,7 +834,7 @@ Se Microsofts support-artikkel på http://support.microsoft.com/kb/811833 for me Kun visning (VNC) - + Nettsted diff --git a/mRemoteNG/Language/Language.nl.resx b/mRemoteNG/Language/Language.nl.resx index cd461392..9b758081 100644 --- a/mRemoteNG/Language/Language.nl.resx +++ b/mRemoteNG/Language/Language.nl.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Over @@ -631,7 +631,7 @@ Beginnen met nieuwe Connectie bestand. Voeg Connectie Paneel toe - + Controleer voor beschikbare Updates @@ -652,7 +652,7 @@ Beginnen met nieuwe Connectie bestand. Verwijder Externe Applicatie... - + Doneer @@ -670,7 +670,7 @@ Beginnen met nieuwe Connectie bestand. &Help - + mRemoteNG Help @@ -712,7 +712,7 @@ Beginnen met nieuwe Connectie bestand. Hernoem Tab - + Meld een bug @@ -742,7 +742,7 @@ Beginnen met nieuwe Connectie bestand. Start Chat (VNC) - + Ondersteunings Forum @@ -757,7 +757,7 @@ Beginnen met nieuwe Connectie bestand. Alleen bekijken (VNC) - + Website diff --git a/mRemoteNG/Language/Language.pl.resx b/mRemoteNG/Language/Language.pl.resx index 863489b9..b3eab02f 100644 --- a/mRemoteNG/Language/Language.pl.resx +++ b/mRemoteNG/Language/Language.pl.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + O programie @@ -722,7 +722,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso Dodaj panel połączenia - + Sprawdź aktualizacje @@ -743,7 +743,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso Usuń zewnętrzne narzędzie... - + Darowizna @@ -761,7 +761,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso &Pomoc - + Pomoc mRemoteNG @@ -803,7 +803,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso Zmień nazwę karty - + Zgłoś błąd @@ -833,7 +833,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso Rozpocznij Chat (VNC) - + Forum pomocy @@ -848,7 +848,7 @@ Więcj informacji w aktykule Wsparcia Windows na stronie https://support.microso Tylko pogląd (VNC) - + Strona WWW diff --git a/mRemoteNG/Language/Language.pt-BR.resx b/mRemoteNG/Language/Language.pt-BR.resx index 77fb4202..c1778b52 100644 --- a/mRemoteNG/Language/Language.pt-BR.resx +++ b/mRemoteNG/Language/Language.pt-BR.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Sobre diff --git a/mRemoteNG/Language/Language.pt.resx b/mRemoteNG/Language/Language.pt.resx index 6bcaec29..0dbb7ce1 100644 --- a/mRemoteNG/Language/Language.pt.resx +++ b/mRemoteNG/Language/Language.pt.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Sobre @@ -627,7 +627,7 @@ Adicionar o Painel de Ligação - + Verificar se há atualizações @@ -648,7 +648,7 @@ Excluir ferramenta externa... - + Doar @@ -666,7 +666,7 @@ &Ajuda - + Ajuda mRemoteNG @@ -708,7 +708,7 @@ Renomear aba - + Relatar um erro @@ -735,7 +735,7 @@ Iniciar chat (VNC) - + Fórum de suporte @@ -750,7 +750,7 @@ Somente ver (VNC) - + Sítio diff --git a/mRemoteNG/Language/Language.resx b/mRemoteNG/Language/Language.resx index 61286304..43f705b7 100644 --- a/mRemoteNG/Language/Language.resx +++ b/mRemoteNG/Language/Language.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + About @@ -731,7 +731,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for Add Connection Panel - + Check for Updates @@ -752,7 +752,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for Delete External Tool... - + Donate @@ -770,7 +770,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for &Help - + mRemoteNG Help @@ -812,8 +812,8 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for Rename Tab - - Report a Bug + + Report an Issue Reset layout @@ -842,7 +842,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for Start Chat (VNC) - + Support Forum @@ -857,7 +857,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for View Only - + Website @@ -1519,6 +1519,12 @@ If you run into such an error, please create a new connection file! Do you want to save the current connections file before loading another? + + Do you want to save the changes made to the options? + + + Discard + Daily @@ -2509,4 +2515,12 @@ Nightly Channel includes Alphas, Betas & Release Candidates. LDAP static role + + mR Chat + Chat to dev + + + Community + Reddit + \ No newline at end of file diff --git a/mRemoteNG/Language/Language.ru.resx b/mRemoteNG/Language/Language.ru.resx index 07be01cc..fa87d548 100644 --- a/mRemoteNG/Language/Language.ru.resx +++ b/mRemoteNG/Language/Language.ru.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + О программе @@ -719,7 +719,7 @@ Добавить Панель подключения - + Проверка наличия обновлений @@ -740,7 +740,7 @@ Удалить внешний инструмент... - + Помочь проекту @@ -758,7 +758,7 @@ &Справка - + Справка mRemoteNG @@ -800,7 +800,7 @@ Переименовать закладку - + Сообщить об ошибке @@ -830,7 +830,7 @@ Начать чат (VNC) - + Форум поддержки @@ -845,7 +845,7 @@ Просмотр (VNC) - + Веб-сайт diff --git a/mRemoteNG/Language/Language.sv-SE.resx b/mRemoteNG/Language/Language.sv-SE.resx index 76b1a293..144efce3 100644 --- a/mRemoteNG/Language/Language.sv-SE.resx +++ b/mRemoteNG/Language/Language.sv-SE.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Om @@ -710,7 +710,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer Lägg till anslutningspanel - + Sök efter uppdateringar @@ -725,7 +725,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer Ta bort externt verktyg... - + Donera @@ -743,7 +743,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer &Hjälp - + mRemoteNG hjälp @@ -785,7 +785,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer Byt namn på flik - + Rapportera en bugg @@ -812,7 +812,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer Starta chatt (VNC) - + Supportforum @@ -827,7 +827,7 @@ Se Microsofts supportartikel på http://support.microsoft.com/kb/811833 för mer Visa endast - + Webbplats diff --git a/mRemoteNG/Language/Language.ta.resx b/mRemoteNG/Language/Language.ta.resx index 6753502a..85dee411 100644 --- a/mRemoteNG/Language/Language.ta.resx +++ b/mRemoteNG/Language/Language.ta.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + பற்றி @@ -725,7 +725,7 @@ இணைப்பு பலகையைச் சேர் - + புதுப்பிப்புகளை சரிபார் @@ -746,7 +746,7 @@ வெளிப்புற கருவியை நீக்கு... - + நன்கொடை @@ -764,7 +764,7 @@ உதவி - + பலதொலைஅத உதவி @@ -806,7 +806,7 @@ தாவலை மறுபெயரிடுங்கள் - + ஒரு பிழையைப் புகாரளி @@ -836,7 +836,7 @@ அரட்டையைத் தொடங்கு (விஎன்சி) - + உதவி மன்றம் @@ -851,7 +851,7 @@ பார்க்க மட்டுமே - + வலைத்தளம் diff --git a/mRemoteNG/Language/Language.tr-TR.resx b/mRemoteNG/Language/Language.tr-TR.resx index fc9428b2..43270bec 100644 --- a/mRemoteNG/Language/Language.tr-TR.resx +++ b/mRemoteNG/Language/Language.tr-TR.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Hakkında @@ -693,7 +693,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: Bağlantı Paneli Ekle - + Güncelleştirmeleri Konrol Et @@ -708,7 +708,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: Harici Aracı Sil... - + Bağış Yap @@ -726,7 +726,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: &Yardım - + mRemoteNG Yardım @@ -768,7 +768,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: Sekmeyi Yeniden Adlandır - + Hata Raporla @@ -798,7 +798,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: Sohbet'i Başlat (VNC) - + Destek Forumu @@ -813,7 +813,7 @@ PuTTY ve harici araçlar için en fazla bekleme süresi: Yalnızca Gör (VNC) - + Web Sitesi diff --git a/mRemoteNG/Language/Language.uk.resx b/mRemoteNG/Language/Language.uk.resx index ee789c43..056a7567 100644 --- a/mRemoteNG/Language/Language.uk.resx +++ b/mRemoteNG/Language/Language.uk.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Про програму @@ -698,7 +698,7 @@ Додати панель з'єднання - + Перевірка наявності оновлень @@ -719,7 +719,7 @@ Видалити зовнішній інструмент… - + Пожертва @@ -737,7 +737,7 @@ &Довідка - + Довідка mRemoteNG @@ -779,7 +779,7 @@ Перейменувати вкладку - + Повідомити про помилку @@ -806,7 +806,7 @@ Почати чат (VNC) - + Форум підтримки @@ -821,7 +821,7 @@ Перегляд (VNC) - + Веб-сайт diff --git a/mRemoteNG/Language/Language.zh-CN.resx b/mRemoteNG/Language/Language.zh-CN.resx index b1b6f074..cb93d77c 100644 --- a/mRemoteNG/Language/Language.zh-CN.resx +++ b/mRemoteNG/Language/Language.zh-CN.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 关于 @@ -719,7 +719,7 @@ 添加连接面板 - + 检查更新 @@ -740,7 +740,7 @@ 删除外部工具... - + 捐赠 @@ -758,7 +758,7 @@ 帮助(&H) - + mRemoteNG 帮助 @@ -800,7 +800,7 @@ 重命名标签 - + 报告问题 @@ -830,7 +830,7 @@ 启动 Chat(VNC) - + 支持论坛 @@ -845,7 +845,7 @@ 仅查看 - + 网站 diff --git a/mRemoteNG/Language/Language.zh-TW.resx b/mRemoteNG/Language/Language.zh-TW.resx index ac4a7847..df2c0a6b 100644 --- a/mRemoteNG/Language/Language.zh-TW.resx +++ b/mRemoteNG/Language/Language.zh-TW.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 關於 @@ -634,7 +634,7 @@ 加入連線面板 - + 檢查更新 @@ -655,7 +655,7 @@ 刪除外部工具... - + 捐贈 @@ -673,7 +673,7 @@ 說明(&H) - + mRemoteNG 說明 @@ -715,7 +715,7 @@ 重新命名索引標籤 - + 報告 Bug @@ -745,7 +745,7 @@ 開始聊天 (VNC) - + 支援討論區 @@ -760,7 +760,7 @@ 只有檢視 (VNC) - + 網站 diff --git a/mRemoteNG/Tools/ExternalTool.cs b/mRemoteNG/Tools/ExternalTool.cs index d9297e36..41c379b6 100644 --- a/mRemoteNG/Tools/ExternalTool.cs +++ b/mRemoteNG/Tools/ExternalTool.cs @@ -156,11 +156,7 @@ namespace mRemoteNG.Tools ExternalToolArgumentParser argParser = new(startConnectionInfo); process.StartInfo.UseShellExecute = true; process.StartInfo.FileName = argParser.ParseArguments(FileName); - var parsedArgs = argParser.ParseArguments(Arguments).Split(' '); - foreach (var arg in parsedArgs) - { - process.StartInfo.ArgumentList.Add(arg); - } + process.StartInfo.Arguments = argParser.ParseArguments(Arguments); if (WorkingDir != "") process.StartInfo.WorkingDirectory = argParser.ParseArguments(WorkingDir); if (RunElevated) process.StartInfo.Verb = "runas"; } diff --git a/mRemoteNG/Tree/Root/RootNodeInfo.cs b/mRemoteNG/Tree/Root/RootNodeInfo.cs index 2cf34641..a035e6b5 100644 --- a/mRemoteNG/Tree/Root/RootNodeInfo.cs +++ b/mRemoteNG/Tree/Root/RootNodeInfo.cs @@ -45,7 +45,7 @@ namespace mRemoteNG.Tree.Root [Browsable(false)] public string PasswordString { - get => Password ? _customPassword : DefaultPassword; + get => (Password && !string.IsNullOrEmpty(_customPassword)) ? _customPassword : DefaultPassword; set { _customPassword = value; diff --git a/mRemoteNG/UI/Controls/ConnectionContextMenu.cs b/mRemoteNG/UI/Controls/ConnectionContextMenu.cs index a2e5357c..a526f84f 100644 --- a/mRemoteNG/UI/Controls/ConnectionContextMenu.cs +++ b/mRemoteNG/UI/Controls/ConnectionContextMenu.cs @@ -810,7 +810,8 @@ namespace mRemoteNG.UI.Controls ESysIcons.Question); if (CTaskDialog.VerificationChecked) { - Settings.Default.ConfirmCloseConnection--; + Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; + Settings.Default.Save(); } if (result == DialogResult.No) diff --git a/mRemoteNG/UI/Forms/FrmAbout.Designer.cs b/mRemoteNG/UI/Forms/FrmAbout.Designer.cs index 7f2fb295..ef7b7613 100644 --- a/mRemoteNG/UI/Forms/FrmAbout.Designer.cs +++ b/mRemoteNG/UI/Forms/FrmAbout.Designer.cs @@ -142,14 +142,9 @@ Controls.Add(pbLogo); Font = new System.Drawing.Font("Segoe UI", 8.25F); ForeColor = System.Drawing.SystemColors.ControlText; - FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - MaximizeBox = false; - MaximumSize = new System.Drawing.Size(20000, 10000); - MinimizeBox = false; Name = "frmAbout"; - StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; Text = "About"; - TopMost = true; + TabText = "About"; ((System.ComponentModel.ISupportInitialize)pbLogo).EndInit(); pnlBottom.ResumeLayout(false); pnlBottom.PerformLayout(); diff --git a/mRemoteNG/UI/Forms/FrmAbout.cs b/mRemoteNG/UI/Forms/FrmAbout.cs index 5bb4cbfb..06e8be28 100644 --- a/mRemoteNG/UI/Forms/FrmAbout.cs +++ b/mRemoteNG/UI/Forms/FrmAbout.cs @@ -7,15 +7,16 @@ using System.Reflection; using mRemoteNG.Properties; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using mRemoteNG.UI.Window; namespace mRemoteNG.UI.Forms { [SupportedOSPlatform("windows")] - public partial class frmAbout : Form + public partial class frmAbout : BaseWindow { public static frmAbout Instance { get; set; } = new frmAbout(); - private frmAbout() + public frmAbout() { InitializeComponent(); Icon = Resources.ImageConverter.GetImageAsIcon(Properties.Resources.UIAboutBox_16x); @@ -27,7 +28,8 @@ namespace mRemoteNG.UI.Forms private void ApplyLanguage() { lblLicense.Text = Language.ReleasedUnderGPL; - base.Text = Language.About; + base.Text = Language.MenuItem_About; + TabText = Language.MenuItem_About; llChangelog.Text = Language.Changelog; llCredits.Text = Language.Credits; llLicense.Text = Language.License; @@ -50,9 +52,9 @@ namespace mRemoteNG.UI.Forms protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); - - e.Cancel = true; - Hide(); + + // Don't cancel close when shown in DockPanel + // This allows the tab to close properly without showing connection close dialog } private void llLicense_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) diff --git a/mRemoteNG/UI/Forms/FrmUnhandledException.cs b/mRemoteNG/UI/Forms/FrmUnhandledException.cs index 86865b11..c42e27cd 100644 --- a/mRemoteNG/UI/Forms/FrmUnhandledException.cs +++ b/mRemoteNG/UI/Forms/FrmUnhandledException.cs @@ -56,7 +56,7 @@ namespace mRemoteNG.UI.Forms labelExceptionMessageHeader.Text = Language.ExceptionMessage; labelStackTraceHeader.Text = Language.StackTrace; labelEnvironment.Text = Language.Environment; - buttonCreateBug.Text = Language.ReportBug; + buttonCreateBug.Text = Language.MenuItem_ReportIssue; buttonCopyAll.Text = Language.CopyAll; buttonClose.Text = _isFatal ? Language.Exit diff --git a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs index b6b6e648..8cc71c64 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs @@ -257,8 +257,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages // tableLayoutPanel2 // tableLayoutPanel2.ColumnCount = 2; - tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 45F)); - tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 55F)); + tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.AutoSize)); + tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); tableLayoutPanel2.Controls.Add(numRdpReconnectionCount, 1, 0); tableLayoutPanel2.Controls.Add(numAutoSave, 1, 2); tableLayoutPanel2.Controls.Add(lblRdpReconnectionCount, 0, 0); diff --git a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs index 6b9c7ef6..f185c1fb 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs @@ -29,6 +29,17 @@ namespace mRemoteNG.UI.Forms.OptionsPages * 1) chkSaveConnectionsAfterEveryEdit: never used */ chkSaveConnectionsAfterEveryEdit.Visible = false; // Temporary hide control, never used, added: Jun 15, 2024 + + // Reload settings when page becomes visible to reflect any changes made outside the Options dialog + VisibleChanged += ConnectionsPage_VisibleChanged; + } + + private void ConnectionsPage_VisibleChanged(object sender, EventArgs e) + { + if (Visible) + { + LoadSettings(); + } } public override string PageName diff --git a/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs index cc26edda..cb200a1b 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/OptionsPage.cs @@ -24,6 +24,12 @@ namespace mRemoteNG.UI.Forms.OptionsPages public virtual Icon PageIcon { get; protected set; } public virtual Image IconImage => PageIcon?.ToBitmap(); + /// + /// Indicates whether the settings on this page have been modified. + /// + [Browsable(false)] + public bool HasChanges { get; set; } + #endregion #region Public Methods diff --git a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs index 47d06cd0..f8e5247b 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs @@ -79,7 +79,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkIdentifyQuickConnectTabs._mice = MrngCheckBox.MouseState.OUT; chkIdentifyQuickConnectTabs.AutoSize = true; chkIdentifyQuickConnectTabs.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkIdentifyQuickConnectTabs.Location = new System.Drawing.Point(3, 118); + chkIdentifyQuickConnectTabs.Location = new System.Drawing.Point(3, 72); chkIdentifyQuickConnectTabs.Name = "chkIdentifyQuickConnectTabs"; chkIdentifyQuickConnectTabs.Size = new System.Drawing.Size(315, 17); chkIdentifyQuickConnectTabs.TabIndex = 4; @@ -103,7 +103,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkAlwaysShowPanelSelectionDlg._mice = MrngCheckBox.MouseState.OUT; chkAlwaysShowPanelSelectionDlg.AutoSize = true; chkAlwaysShowPanelSelectionDlg.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkAlwaysShowPanelSelectionDlg.Location = new System.Drawing.Point(3, 164); + chkAlwaysShowPanelSelectionDlg.Location = new System.Drawing.Point(3, 118); chkAlwaysShowPanelSelectionDlg.Name = "chkAlwaysShowPanelSelectionDlg"; chkAlwaysShowPanelSelectionDlg.Size = new System.Drawing.Size(347, 17); chkAlwaysShowPanelSelectionDlg.TabIndex = 6; @@ -115,7 +115,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkShowLogonInfoOnTabs._mice = MrngCheckBox.MouseState.OUT; chkShowLogonInfoOnTabs.AutoSize = true; chkShowLogonInfoOnTabs.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkShowLogonInfoOnTabs.Location = new System.Drawing.Point(3, 72); + chkShowLogonInfoOnTabs.Location = new System.Drawing.Point(3, 26); chkShowLogonInfoOnTabs.Name = "chkShowLogonInfoOnTabs"; chkShowLogonInfoOnTabs.Size = new System.Drawing.Size(226, 17); chkShowLogonInfoOnTabs.TabIndex = 2; @@ -127,7 +127,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkDoubleClickClosesTab._mice = MrngCheckBox.MouseState.OUT; chkDoubleClickClosesTab.AutoSize = true; chkDoubleClickClosesTab.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkDoubleClickClosesTab.Location = new System.Drawing.Point(3, 141); + chkDoubleClickClosesTab.Location = new System.Drawing.Point(3, 95); chkDoubleClickClosesTab.Name = "chkDoubleClickClosesTab"; chkDoubleClickClosesTab.Size = new System.Drawing.Size(170, 17); chkDoubleClickClosesTab.TabIndex = 5; @@ -139,7 +139,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkShowProtocolOnTabs._mice = MrngCheckBox.MouseState.OUT; chkShowProtocolOnTabs.AutoSize = true; chkShowProtocolOnTabs.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkShowProtocolOnTabs.Location = new System.Drawing.Point(3, 95); + chkShowProtocolOnTabs.Location = new System.Drawing.Point(3, 49); chkShowProtocolOnTabs.Name = "chkShowProtocolOnTabs"; chkShowProtocolOnTabs.Size = new System.Drawing.Size(180, 17); chkShowProtocolOnTabs.TabIndex = 3; @@ -151,7 +151,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkCreateEmptyPanelOnStart._mice = MrngCheckBox.MouseState.OUT; chkCreateEmptyPanelOnStart.AutoSize = true; chkCreateEmptyPanelOnStart.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - chkCreateEmptyPanelOnStart.Location = new System.Drawing.Point(3, 187); + chkCreateEmptyPanelOnStart.Location = new System.Drawing.Point(3, 141); chkCreateEmptyPanelOnStart.Name = "chkCreateEmptyPanelOnStart"; chkCreateEmptyPanelOnStart.Size = new System.Drawing.Size(271, 17); chkCreateEmptyPanelOnStart.TabIndex = 7; @@ -162,7 +162,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages // txtBoxPanelName // txtBoxPanelName.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - txtBoxPanelName.Location = new System.Drawing.Point(35, 223); + txtBoxPanelName.Location = new System.Drawing.Point(35, 177); txtBoxPanelName.Name = "txtBoxPanelName"; txtBoxPanelName.Size = new System.Drawing.Size(213, 22); txtBoxPanelName.TabIndex = 8; @@ -170,7 +170,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages // lblPanelName // lblPanelName.AutoSize = true; - lblPanelName.Location = new System.Drawing.Point(32, 207); + lblPanelName.Location = new System.Drawing.Point(32, 161); lblPanelName.Name = "lblPanelName"; lblPanelName.Size = new System.Drawing.Size(69, 13); lblPanelName.TabIndex = 9; @@ -192,7 +192,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages pnlOptions.Dock = System.Windows.Forms.DockStyle.Top; pnlOptions.Location = new System.Drawing.Point(0, 30); pnlOptions.Name = "pnlOptions"; - pnlOptions.Size = new System.Drawing.Size(610, 262); + pnlOptions.Size = new System.Drawing.Size(610, 216); pnlOptions.TabIndex = 10; // // lblRegistrySettingsUsedInfo diff --git a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs index 19b25794..b8d35393 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs @@ -89,7 +89,10 @@ namespace mRemoteNG.UI.Forms.OptionsPages * Properties.OptionsTabsPanelsPage.Default.AlwaysShowConnectionTabs nerver used */ //Properties.OptionsTabsPanelsPage.Default.AlwaysShowConnectionTabs = chkAlwaysShowConnectionTabs.Checked; - FrmMain.Default.ShowHidePanelTabs(); + + // Defer the ShowHidePanelTabs call to avoid corrupting the Options window + // This ensures the call happens after the Options window is closed + FrmMain.Default.BeginInvoke(new System.Windows.Forms.MethodInvoker(() => FrmMain.Default.ShowHidePanelTabs())); /* * Comment added: June 16, 2024 diff --git a/mRemoteNG/UI/Forms/OptionsPages/ThemePage.cs b/mRemoteNG/UI/Forms/OptionsPages/ThemePage.cs index cadd833d..4a6013c5 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/ThemePage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/ThemePage.cs @@ -18,6 +18,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages private readonly ThemeManager _themeManager; private readonly bool _oriActiveTheming; + private ThemeInfo _oriActiveTheme; private readonly List modifiedThemes = []; #endregion @@ -65,6 +66,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages // ReSharper disable once CoVariantArrayConversion cboTheme.Items.AddRange(_themeManager.LoadThemes().OrderBy(x => x.Name).ToArray()); cboTheme.SelectedItem = _themeManager.ActiveTheme; + // Store the original active theme for reverting + _oriActiveTheme = _themeManager.ActiveTheme; cboTheme_SelectionChangeCommitted(this, new EventArgs()); cboTheme.DisplayMember = "Name"; @@ -107,6 +110,20 @@ namespace mRemoteNG.UI.Forms.OptionsPages { base.RevertSettings(); _themeManager.ThemingActive = _oriActiveTheming; + + // Clear the modified themes list without saving + modifiedThemes.Clear(); + + // Restore the original theme selection + if (_oriActiveTheme != null) + { + _themeManager.ActiveTheme = _oriActiveTheme; + // Reload the theme list to reflect the original state + cboTheme.Items.Clear(); + cboTheme.Items.AddRange(_themeManager.LoadThemes().OrderBy(x => x.Name).ToArray()); + cboTheme.SelectedItem = _oriActiveTheme; + cboTheme_SelectionChangeCommitted(this, new EventArgs()); + } } #region Private Methods diff --git a/mRemoteNG/UI/Forms/frmMain.cs b/mRemoteNG/UI/Forms/frmMain.cs index b1a38662..2e7ae7c2 100644 --- a/mRemoteNG/UI/Forms/frmMain.cs +++ b/mRemoteNG/UI/Forms/frmMain.cs @@ -470,7 +470,7 @@ namespace mRemoteNG.UI.Forms DialogResult result = CTaskDialog.MessageBox(this, Application.ProductName, Language.ConfirmExitMainInstruction, "", "", "", Language.CheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.YesNo, ESysIcons.Question, ESysIcons.Question); if (CTaskDialog.VerificationChecked) { - Properties.Settings.Default.ConfirmCloseConnection--; //--? + Properties.Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; } if (result == DialogResult.No) diff --git a/mRemoteNG/UI/Forms/frmOptions.cs b/mRemoteNG/UI/Forms/frmOptions.cs index 267d3b7a..e867c35b 100644 --- a/mRemoteNG/UI/Forms/frmOptions.cs +++ b/mRemoteNG/UI/Forms/frmOptions.cs @@ -22,6 +22,8 @@ namespace mRemoteNG.UI.Forms private string _pageName; private readonly DisplayProperties _display = new(); private readonly List _optionPageObjectNames; + private bool _isLoading = true; + private bool _isInitialized = false; // Add this field to the FrmOptions class public FrmOptions() : this(Language.StartupExit) { @@ -57,6 +59,13 @@ namespace mRemoteNG.UI.Forms private void FrmOptions_Load(object sender, EventArgs e) { + // Only initialize once to prevent multiple event subscriptions and page reloading + if (_isInitialized) + { + this.Visible = true; + return; + } + this.Visible = true; FontOverrider.FontOverride(this); SetActivatedPage(); @@ -71,6 +80,23 @@ namespace mRemoteNG.UI.Forms //ThemeManager.getInstance().ThemeChanged += ApplyTheme; lstOptionPages.SelectedIndexChanged += LstOptionPages_SelectedIndexChanged; lstOptionPages.SelectedIndex = 0; + + // Handle visibility changes to ensure panel is populated when form is shown + this.VisibleChanged += FrmOptions_VisibleChanged; + + // Mark as initialized + _isInitialized = true; + } + + private void FrmOptions_VisibleChanged(object sender, EventArgs e) + { + // When the form becomes visible, ensure the panel is populated with the selected page + if (this.Visible && pnlMain.Controls.Count == 0) + { + OptionsPage page = (OptionsPage)lstOptionPages.SelectedObject; + if (page != null) + pnlMain.Controls.Add(page); + } } private void ApplyTheme() @@ -105,6 +131,8 @@ namespace mRemoteNG.UI.Forms if (_currentIndex >= _optionPageObjectNames.Count) { Application.Idle -= new EventHandler(Application_Idle); + // All pages loaded, now start tracking changes + _isLoading = false; } else { @@ -210,6 +238,9 @@ namespace mRemoteNG.UI.Forms page.LoadSettings(); _optionPages.Add(page); lstOptionPages.AddObject(page); + + // Track changes in all controls on the page + TrackChangesInControls(page); } private object ImageGetter(object rowobject) @@ -238,12 +269,16 @@ namespace mRemoteNG.UI.Forms private void BtnOK_Click(object sender, EventArgs e) { SaveOptions(); + // Clear change flags after saving + ClearChangeFlags(); this.Visible = false; } private void BtnApply_Click(object sender, EventArgs e) { SaveOptions(); + // Clear change flags after applying + ClearChangeFlags(); } private void SaveOptions() @@ -269,13 +304,113 @@ namespace mRemoteNG.UI.Forms private void BtnCancel_Click(object sender, EventArgs e) { + // When Cancel is clicked, we don't check for changes + // The user explicitly wants to cancel this.Visible = false; } private void FrmOptions_FormClosing(object sender, FormClosingEventArgs e) { - e.Cancel = true; - this.Visible = false; + // Check if any page has unsaved changes + bool hasChanges = _optionPages.Any(page => page.HasChanges); + + if (hasChanges) + { + DialogResult result = MessageBox.Show( + Language.SaveOptionsBeforeClosing, + Language.Options, + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + + switch (result) + { + case DialogResult.Yes: + SaveOptions(); + ClearChangeFlags(); + e.Cancel = true; + this.Visible = false; + break; + case DialogResult.No: + // Discard changes + ClearChangeFlags(); + e.Cancel = true; + this.Visible = false; + break; + case DialogResult.Cancel: + // Cancel closing - keep the dialog open + e.Cancel = true; + break; + } + } + else + { + e.Cancel = true; + this.Visible = false; + } + } + + private void TrackChangesInControls(Control control) + { + foreach (Control childControl in control.Controls) + { + // Track changes for common input controls + if (childControl is TextBox textBox) + { + textBox.TextChanged += (s, e) => MarkPageAsChanged(control); + } + else if (childControl is CheckBox checkBox) + { + checkBox.CheckedChanged += (s, e) => MarkPageAsChanged(control); + } + else if (childControl is RadioButton radioButton) + { + radioButton.CheckedChanged += (s, e) => MarkPageAsChanged(control); + } + else if (childControl is ComboBox comboBox) + { + comboBox.SelectedIndexChanged += (s, e) => MarkPageAsChanged(control); + } + else if (childControl is NumericUpDown numericUpDown) + { + numericUpDown.ValueChanged += (s, e) => MarkPageAsChanged(control); + } + else if (childControl is ListBox listBox) + { + listBox.SelectedIndexChanged += (s, e) => MarkPageAsChanged(control); + } + + // Recursively track changes in nested controls + if (childControl.Controls.Count > 0) + { + TrackChangesInControls(childControl); + } + } + } + + private void MarkPageAsChanged(Control control) + { + // Don't track changes during initial loading + if (_isLoading) return; + + // Find the parent OptionsPage + Control current = control; + while (current != null && !(current is OptionsPage)) + { + current = current.Parent; + } + + if (current is OptionsPage page) + { + page.HasChanges = true; + } + } + + private void ClearChangeFlags() + { + foreach (OptionsPage page in _optionPages) + { + page.HasChanges = false; + } } } } \ No newline at end of file diff --git a/mRemoteNG/UI/Menu/msMain/HelpMenu.cs b/mRemoteNG/UI/Menu/msMain/HelpMenu.cs index dfd829a9..dc0c6a1e 100644 --- a/mRemoteNG/UI/Menu/msMain/HelpMenu.cs +++ b/mRemoteNG/UI/Menu/msMain/HelpMenu.cs @@ -13,17 +13,19 @@ namespace mRemoteNG.UI.Menu [SupportedOSPlatform("windows")] public class HelpMenu : ToolStripMenuItem { - private ToolStripMenuItem _mMenInfoHelp; - private ToolStripMenuItem _mMenInfoWebsite; - private ToolStripSeparator _mMenInfoSep1; - private ToolStripMenuItem _mMenInfoAbout; - private ToolStripMenuItem _mMenInfoDonate; - private ToolStripSeparator _mMenInfoSep2; - private ToolStripSeparator _mMenInfoSep3; - private ToolStripSeparator _mMenInfoSep4; - private ToolStripMenuItem _mMenInfoForum; - private ToolStripMenuItem _mMenInfoBug; - private ToolStripMenuItem _mMenToolsUpdate; + private ToolStripMenuItem _mMenInfoHelp = null!; + private ToolStripMenuItem _mMenInfoWebsite = null!; + private ToolStripSeparator _mMenInfoSep1 = null!; + private ToolStripMenuItem _mMenInfoAbout = null!; + private ToolStripMenuItem _mMenInfoDonate = null!; + private ToolStripSeparator _mMenInfoSep2 = null!; + private ToolStripSeparator _mMenInfoSep3 = null!; + private ToolStripSeparator _mMenInfoSep4 = null!; + private ToolStripMenuItem _mMenInfoForum = null!; + private ToolStripMenuItem _mMenInfoChat = null!; + private ToolStripMenuItem _mMenInfoCommunity = null!; + private ToolStripMenuItem _mMenInfoBug = null!; + private ToolStripMenuItem _mMenToolsUpdate = null!; public HelpMenu() { @@ -37,6 +39,8 @@ namespace mRemoteNG.UI.Menu _mMenInfoWebsite = new ToolStripMenuItem(); _mMenInfoDonate = new ToolStripMenuItem(); _mMenInfoForum = new ToolStripMenuItem(); + _mMenInfoChat = new ToolStripMenuItem(); + _mMenInfoCommunity = new ToolStripMenuItem(); _mMenInfoBug = new ToolStripMenuItem(); _mMenToolsUpdate = new ToolStripMenuItem(); _mMenInfoSep2 = new ToolStripSeparator(); @@ -53,6 +57,8 @@ namespace mRemoteNG.UI.Menu _mMenInfoSep1, _mMenInfoWebsite, _mMenInfoForum, + _mMenInfoChat, + _mMenInfoCommunity, _mMenInfoBug, _mMenInfoSep2, _mMenToolsUpdate, @@ -72,7 +78,7 @@ namespace mRemoteNG.UI.Menu _mMenInfoHelp.Name = "mMenInfoHelp"; _mMenInfoHelp.ShortcutKeys = Keys.F1; _mMenInfoHelp.Size = new System.Drawing.Size(190, 22); - _mMenInfoHelp.Text = Language.HelpContents; + _mMenInfoHelp.Text = Language.MenuItem_HelpContents; _mMenInfoHelp.Click += mMenInfoHelp_Click; // // mMenToolsUpdate @@ -80,7 +86,7 @@ namespace mRemoteNG.UI.Menu _mMenToolsUpdate.Image = Properties.Resources.RunUpdate_16x; _mMenToolsUpdate.Name = "mMenToolsUpdate"; _mMenToolsUpdate.Size = new System.Drawing.Size(190, 22); - _mMenToolsUpdate.Text = Language.CheckForUpdates; + _mMenToolsUpdate.Text = Language.MenuItem_CheckForUpdates; _mMenToolsUpdate.Click += mMenToolsUpdate_Click; _mMenToolsUpdate.Enabled = CommonRegistrySettings.AllowCheckForUpdates && CommonRegistrySettings.AllowCheckForUpdatesManual; @@ -94,28 +100,42 @@ namespace mRemoteNG.UI.Menu // _mMenInfoWebsite.Name = "mMenInfoWebsite"; _mMenInfoWebsite.Size = new System.Drawing.Size(190, 22); - _mMenInfoWebsite.Text = Language.Website; + _mMenInfoWebsite.Text = Language.MenuItem_Website; _mMenInfoWebsite.Click += mMenInfoWebsite_Click; // // mMenInfoDonate // _mMenInfoDonate.Name = "mMenInfoDonate"; _mMenInfoDonate.Size = new System.Drawing.Size(190, 22); - _mMenInfoDonate.Text = Language.Donate; + _mMenInfoDonate.Text = Language.MenuItem_Donate; _mMenInfoDonate.Click += mMenInfoDonate_Click; // // mMenInfoForum // _mMenInfoForum.Name = "mMenInfoForum"; _mMenInfoForum.Size = new System.Drawing.Size(190, 22); - _mMenInfoForum.Text = Language.SupportForum; + _mMenInfoForum.Text = Language.MenuItem_SupportForum; _mMenInfoForum.Click += mMenInfoForum_Click; // + // mMenInfoChat + // + _mMenInfoChat.Name = "mMenInfoChat"; + _mMenInfoChat.Size = new System.Drawing.Size(190, 22); + _mMenInfoChat.Text = Language.MenuItem_Chat; + _mMenInfoChat.Click += mMenInfoChat_Click; + // + // mMenInfoCommunity + // + _mMenInfoCommunity.Name = "mMenInfoCommunity"; + _mMenInfoCommunity.Size = new System.Drawing.Size(190, 22); + _mMenInfoCommunity.Text = Language.MenuItem_Community; + _mMenInfoCommunity.Click += mMenInfoCommunity_Click; + // // mMenInfoBug // _mMenInfoBug.Name = "mMenInfoBug"; _mMenInfoBug.Size = new System.Drawing.Size(190, 22); - _mMenInfoBug.Text = Language.ReportBug; + _mMenInfoBug.Text = Language.MenuItem_ReportIssue; _mMenInfoBug.Click += mMenInfoBug_Click; // // mMenInfoSep2 @@ -138,20 +158,22 @@ namespace mRemoteNG.UI.Menu _mMenInfoAbout.Image = Properties.Resources.UIAboutBox_16x; _mMenInfoAbout.Name = "mMenInfoAbout"; _mMenInfoAbout.Size = new System.Drawing.Size(190, 22); - _mMenInfoAbout.Text = Language.About; + _mMenInfoAbout.Text = Language.MenuItem_About; _mMenInfoAbout.Click += mMenInfoAbout_Click; } public void ApplyLanguage() { Text = Language._Help; - _mMenInfoHelp.Text = Language.HelpContents; - _mMenInfoWebsite.Text = Language.Website; - _mMenInfoDonate.Text = Language.Donate; - _mMenInfoForum.Text = Language.SupportForum; - _mMenInfoBug.Text = Language.ReportBug; - _mMenInfoAbout.Text = Language.About; - _mMenToolsUpdate.Text = Language.CheckForUpdates; + _mMenInfoHelp.Text = Language.MenuItem_HelpContents; + _mMenInfoWebsite.Text = Language.MenuItem_Website; + _mMenInfoDonate.Text = Language.MenuItem_Donate; + _mMenInfoForum.Text = Language.MenuItem_SupportForum; + _mMenInfoChat.Text = Language.MenuItem_Chat; + _mMenInfoCommunity.Text = Language.MenuItem_Community; + _mMenInfoBug.Text = Language.MenuItem_ReportIssue; + _mMenInfoAbout.Text = Language.MenuItem_About; + _mMenToolsUpdate.Text = Language.MenuItem_CheckForUpdates; } #region Info @@ -166,17 +188,26 @@ namespace mRemoteNG.UI.Menu } } - private void mMenInfoHelp_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlDocumentation); + private void mMenInfoHelp_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlDocumentation); - private void mMenInfoForum_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlForum); + private void mMenInfoForum_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlForum); - private void mMenInfoBug_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlBugs); + private void mMenInfoChat_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlChat); - private void mMenInfoWebsite_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlHome); + private void mMenInfoCommunity_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlCommunity); - private void mMenInfoDonate_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlDonate); + private void mMenInfoBug_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlBugs); - private void mMenInfoAbout_Click(object sender, EventArgs e) => frmAbout.Instance.Show(); + private void mMenInfoWebsite_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlHome); + + private void mMenInfoDonate_Click(object? sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlDonate); + + private void mMenInfoAbout_Click(object? sender, EventArgs e) + { + if (frmAbout.Instance == null || frmAbout.Instance.IsDisposed) + frmAbout.Instance = new frmAbout(); + frmAbout.Instance.Show(FrmMain.Default.pnlDock); + } #endregion } diff --git a/mRemoteNG/UI/Panels/PanelAdder.cs b/mRemoteNG/UI/Panels/PanelAdder.cs index 75d9afde..728c989c 100644 --- a/mRemoteNG/UI/Panels/PanelAdder.cs +++ b/mRemoteNG/UI/Panels/PanelAdder.cs @@ -15,14 +15,17 @@ namespace mRemoteNG.UI.Panels [SupportedOSPlatform("windows")] public class PanelAdder { - public ConnectionWindow AddPanel(string title = "") + public ConnectionWindow AddPanel(string title = "", bool showImmediately = true) { try { ConnectionWindow connectionForm = new(new DockContent()); BuildConnectionWindowContextMenu(connectionForm); SetConnectionWindowTitle(title, connectionForm); - ShowConnectionWindow(connectionForm); + // Only show immediately if requested (for user-created empty panels) + // When opening connections, we defer showing until first tab is added + if (showImmediately) + ShowConnectionWindow(connectionForm); PrepareTabSupport(connectionForm); return connectionForm; } diff --git a/mRemoteNG/UI/Tabs/ConnectionTab.cs b/mRemoteNG/UI/Tabs/ConnectionTab.cs index 82d2926f..3d4f2c53 100644 --- a/mRemoteNG/UI/Tabs/ConnectionTab.cs +++ b/mRemoteNG/UI/Tabs/ConnectionTab.cs @@ -55,7 +55,8 @@ namespace mRemoteNG.UI.Tabs ESysIcons.Question); if (CTaskDialog.VerificationChecked) { - Settings.Default.ConfirmCloseConnection--; + Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; + Settings.Default.Save(); } if (result == DialogResult.No) diff --git a/mRemoteNG/UI/Window/ConnectionWindow.cs b/mRemoteNG/UI/Window/ConnectionWindow.cs index 506e88e3..eb99a600 100644 --- a/mRemoteNG/UI/Window/ConnectionWindow.cs +++ b/mRemoteNG/UI/Window/ConnectionWindow.cs @@ -143,6 +143,13 @@ namespace mRemoteNG.UI.Window // TODO: See if we can make this work with DPS... //TabController.HideTabsMode = TabControl.HideTabsModes.HideAlways; + // Ensure the ConnectionWindow is visible before adding the tab + // This prevents visibility issues when the window was created but not yet shown + // Check DockState instead of Visible to properly detect if window is shown in DockPanel + if (DockState == DockState.Unknown || DockState == DockState.Hidden || !Visible) + { + Show(FrmMain.Default.pnlDock, DockState.Document); + } //Show the tab conTab.Show(connDock, DockState.Document); @@ -288,16 +295,11 @@ namespace mRemoteNG.UI.Window Settings.Default.ConfirmCloseConnection == (int)ConfirmCloseEnum.Multiple & connDock.Documents.Count() > 1)) { - DialogResult result = CTaskDialog.MessageBox(this, GeneralAppInfo.ProductName, - string - .Format(Language.ConfirmCloseConnectionPanelMainInstruction, - Text), "", "", "", - Language.CheckboxDoNotShowThisMessageAgain, - ETaskDialogButtons.YesNo, ESysIcons.Question, - ESysIcons.Question); + DialogResult result = CTaskDialog.MessageBox(this, GeneralAppInfo.ProductName, string.Format(Language.ConfirmCloseConnectionPanelMainInstruction, Text), "", "", "", Language.CheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.YesNo, ESysIcons.Question, ESysIcons.Question); if (CTaskDialog.VerificationChecked) { - Settings.Default.ConfirmCloseConnection--; + Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; + Settings.Default.Save(); } if (result == DialogResult.No) @@ -662,7 +664,8 @@ namespace mRemoteNG.UI.Window ESysIcons.Question); if (CTaskDialog.VerificationChecked) { - Settings.Default.ConfirmCloseConnection--; + Settings.Default.ConfirmCloseConnection = (int)ConfirmCloseEnum.Never; + Settings.Default.Save(); } if (result == DialogResult.No) diff --git a/mRemoteNG/UI/Window/OptionsWindow.cs b/mRemoteNG/UI/Window/OptionsWindow.cs index 6b07a754..3f3931bb 100644 --- a/mRemoteNG/UI/Window/OptionsWindow.cs +++ b/mRemoteNG/UI/Window/OptionsWindow.cs @@ -12,6 +12,7 @@ namespace mRemoteNG.UI.Window public partial class OptionsWindow : BaseWindow { private FrmOptions _optionsForm; + private bool _isInitialized = false; #region Public Methods @@ -34,8 +35,14 @@ namespace mRemoteNG.UI.Window private void Options_Load(object sender, EventArgs e) { + // Only subscribe to ThemeChanged once to prevent multiple subscriptions + if (!_isInitialized) + { + ThemeManager.getInstance().ThemeChanged += ApplyTheme; + _isInitialized = true; + } + ApplyTheme(); - ThemeManager.getInstance().ThemeChanged += ApplyTheme; ApplyLanguage(); LoadOptionsForm(); } diff --git a/mRemoteNG/UI/Window/UpdateWindow.cs b/mRemoteNG/UI/Window/UpdateWindow.cs index 9ff6eaea..d590152d 100644 --- a/mRemoteNG/UI/Window/UpdateWindow.cs +++ b/mRemoteNG/UI/Window/UpdateWindow.cs @@ -1,16 +1,18 @@ -using System; +using mRemoteNG.App; +using mRemoteNG.App.Update; +using mRemoteNG.Messages; +using mRemoteNG.Resources.Language; +using mRemoteNG.Themes; + +using System; using System.Diagnostics; using System.Drawing; using System.IO; -using System.Windows.Forms; -using mRemoteNG.App; -using mRemoteNG.App.Update; -using mRemoteNG.Messages; -using mRemoteNG.Themes; -using WeifenLuo.WinFormsUI.Docking; -using mRemoteNG.Resources.Language; -using System.Threading.Tasks; using System.Runtime.Versioning; +using System.Threading.Tasks; +using System.Windows.Forms; + +using WeifenLuo.WinFormsUI.Docking; namespace mRemoteNG.UI.Window { @@ -66,8 +68,8 @@ namespace mRemoteNG.UI.Window private void ApplyLanguage() { - Text = Language.CheckForUpdates; - TabText = Language.CheckForUpdates; + Text = Language.MenuItem_CheckForUpdates; + TabText = Language.MenuItem_CheckForUpdates; btnCheckForUpdate.Text = Language.CheckAgain; btnDownload.Text = Runtime.IsPortableEdition ? Language.Download @@ -116,7 +118,7 @@ namespace mRemoteNG.UI.Window return; } - lblStatus.Text = Language.CheckForUpdates; + lblStatus.Text = Language.MenuItem_CheckForUpdates; lblStatus.ForeColor = SystemColors.WindowText; lblLatestVersionLabel.Visible = false; lblInstalledVersion.Visible = false; @@ -213,11 +215,11 @@ namespace mRemoteNG.UI.Window prgbDownload.Visible = false; if (Runtime.IsPortableEdition) - MessageBox.Show(Language.UpdatePortableDownloadComplete, Language.CheckForUpdates, + MessageBox.Show(Language.UpdatePortableDownloadComplete, Language.MenuItem_CheckForUpdates, MessageBoxButtons.OK, MessageBoxIcon.Information); else { - if (MessageBox.Show(Language.UpdateDownloadComplete, Language.CheckForUpdates, + if (MessageBox.Show(Language.UpdateDownloadComplete, Language.MenuItem_CheckForUpdates, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) { Shutdown.Quit(_appUpdate.CurrentUpdateInfo.UpdateFilePath); diff --git a/mRemoteNGTests/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializerTests.cs b/mRemoteNGTests/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializerTests.cs index 9ad944a2..751dd371 100644 --- a/mRemoteNGTests/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializerTests.cs +++ b/mRemoteNGTests/Config/Serializers/ConnectionSerializers/Xml/XmlRootNodeSerializerTests.cs @@ -97,6 +97,36 @@ public class XmlRootNodeSerializerTests Assert.That(attributeValuePlainText, Is.EqualTo(expectedPlainText)); } + [Test] + public void ProtectedStringSerializedWhenPasswordPropertySetDirectly() + { + // Simulate edge case where Password property is set to true directly + // without setting PasswordString (leaving _customPassword empty) + _rootNodeInfo.Password = true; + var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, _version); + var attributeValue = element.Attribute(XName.Get("Protected"))?.Value; + // Should use default password and serialize as "ThisIsNotProtected" + var attributeValuePlainText = + _cryptographyProvider.Decrypt(attributeValue, _rootNodeInfo.PasswordString.ConvertToSecureString()); + Assert.That(attributeValuePlainText, Is.EqualTo("ThisIsNotProtected")); + } + + [Test] + public void FullFileEncryptionWorksWithPasswordPropertySetDirectly() + { + // Simulate edge case where Password property is set to true directly + // This should not cause encryption to fail + _rootNodeInfo.Password = true; + var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, _version, fullFileEncryption: true); + var fullFileEncryptionValue = element.Attribute(XName.Get("FullFileEncryption"))?.Value; + Assert.That(bool.Parse(fullFileEncryptionValue), Is.True); + // Verify Protected attribute can be decrypted successfully + var protectedValue = element.Attribute(XName.Get("Protected"))?.Value; + Assert.That(protectedValue, Is.Not.Null.And.Not.Empty); + var decryptedProtected = _cryptographyProvider.Decrypt(protectedValue, _rootNodeInfo.PasswordString.ConvertToSecureString()); + Assert.That(decryptedProtected, Is.EqualTo("ThisIsNotProtected")); + } + [Test] public void ConfVersionSerialized() { diff --git a/mRemoteNGTests/Tools/ExternalToolTests.cs b/mRemoteNGTests/Tools/ExternalToolTests.cs new file mode 100644 index 00000000..7334c024 --- /dev/null +++ b/mRemoteNGTests/Tools/ExternalToolTests.cs @@ -0,0 +1,115 @@ +using System.Diagnostics; +using System.Reflection; +using mRemoteNG.Connection; +using mRemoteNG.Tools; +using NUnit.Framework; + +namespace mRemoteNGTests.Tools +{ + [TestFixture] + public class ExternalToolTests + { + [Test] + public void PasswordWithEqualsSignIsPassedCorrectly() + { + // Arrange + var connectionInfo = new ConnectionInfo + { + Password = "Z-3=Wv99/Aq", + Hostname = "testhost", + Username = "testuser" + }; + + var externalTool = new ExternalTool + { + DisplayName = "Test Tool", + FileName = "test.exe", + Arguments = "-u %USERNAME% -p %PASSWORD% -h %HOSTNAME%" + }; + + // Act + var process = new Process(); + var setProcessPropertiesMethod = typeof(ExternalTool).GetMethod( + "SetProcessProperties", + BindingFlags.NonPublic | BindingFlags.Instance + ); + setProcessPropertiesMethod?.Invoke(externalTool, new object[] { process, connectionInfo }); + + // Assert + // The arguments should contain the password with the equals sign + // It may be escaped (e.g., Z-3^=Wv99/Aq), but should not be split + Assert.That(process.StartInfo.Arguments, Does.Contain("Z-3")); + Assert.That(process.StartInfo.Arguments, Does.Contain("Wv99/Aq")); + // The equals sign should be present (possibly escaped as ^=) + Assert.That(process.StartInfo.Arguments, Does.Match("Z-3.=Wv99/Aq")); + } + + [Test] + public void PasswordWithSpecialCharactersIsPassedCorrectly() + { + // Arrange + var connectionInfo = new ConnectionInfo + { + Password = "P@ss=W0rd!", + Hostname = "testhost", + Username = "testuser" + }; + + var externalTool = new ExternalTool + { + DisplayName = "Test Tool", + FileName = "test.exe", + Arguments = "-p %PASSWORD%" + }; + + // Act + var process = new Process(); + var setProcessPropertiesMethod = typeof(ExternalTool).GetMethod( + "SetProcessProperties", + BindingFlags.NonPublic | BindingFlags.Instance + ); + setProcessPropertiesMethod?.Invoke(externalTool, new object[] { process, connectionInfo }); + + // Assert + // The password should be present in the arguments (possibly escaped) + Assert.That(process.StartInfo.Arguments, Does.Contain("P@ss")); + Assert.That(process.StartInfo.Arguments, Does.Contain("W0rd")); + } + + [Test] + public void MultipleArgumentsAreParsedCorrectly() + { + // Arrange + var connectionInfo = new ConnectionInfo + { + Password = "TestPass=123", + Hostname = "myhost.com", + Username = "admin", + Port = 8080 + }; + + var externalTool = new ExternalTool + { + DisplayName = "Test Tool", + FileName = "app.exe", + Arguments = "--host %HOSTNAME% --port %PORT% --user %USERNAME% --pass %PASSWORD%" + }; + + // Act + var process = new Process(); + var setProcessPropertiesMethod = typeof(ExternalTool).GetMethod( + "SetProcessProperties", + BindingFlags.NonPublic | BindingFlags.Instance + ); + setProcessPropertiesMethod?.Invoke(externalTool, new object[] { process, connectionInfo }); + + // Assert + var arguments = process.StartInfo.Arguments; + Assert.That(arguments, Does.Contain("myhost.com")); + Assert.That(arguments, Does.Contain("8080")); + Assert.That(arguments, Does.Contain("admin")); + Assert.That(arguments, Does.Contain("TestPass")); + Assert.That(arguments, Does.Contain("123")); + } + } +} diff --git a/mRemoteNGTests/Tree/RootNodeInfoTests.cs b/mRemoteNGTests/Tree/RootNodeInfoTests.cs index 4baf33ee..61a6b744 100644 --- a/mRemoteNGTests/Tree/RootNodeInfoTests.cs +++ b/mRemoteNGTests/Tree/RootNodeInfoTests.cs @@ -48,6 +48,14 @@ namespace mRemoteNGTests.Tree Assert.That(_rootNodeInfo.PasswordString, Is.EqualTo(password)); } + [Test] + public void PasswordStringReturnsDefaultWhenPasswordPropertySetWithoutPasswordString() + { + // Edge case: Password property set to true directly without setting PasswordString + _rootNodeInfo.Password = true; + Assert.That(_rootNodeInfo.PasswordString, Is.EqualTo(_rootNodeInfo.DefaultPassword)); + } + [TestCase(RootNodeType.Connection, TreeNodeType.Root)] [TestCase(RootNodeType.PuttySessions, TreeNodeType.PuttyRoot)] public void RootNodeHasCorrectTreeNodeType(RootNodeType rootNodeType, TreeNodeType expectedTreeNodeType) diff --git a/mRemoteNGTests/UI/Forms/OptionsFormTests.cs b/mRemoteNGTests/UI/Forms/OptionsFormTests.cs index 2b964cb4..bd3b8048 100644 --- a/mRemoteNGTests/UI/Forms/OptionsFormTests.cs +++ b/mRemoteNGTests/UI/Forms/OptionsFormTests.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Windows.Forms; using mRemoteNGTests.TestHelpers; +using System.Linq; namespace mRemoteNGTests.UI.Forms { @@ -33,5 +34,37 @@ namespace mRemoteNGTests.UI.Forms ListViewTester listViewTester = new("lstOptionPages", _optionsForm); Assert.That(listViewTester.Items.Count, Is.EqualTo(12)); } + + [Test] + public void ChangingOptionMarksPageAsChanged() + { + // Wait for all pages to load + System.Threading.Thread.Sleep(500); + Application.DoEvents(); + + // Get the options panel + var pnlMain = _optionsForm.FindControl("pnlMain"); + Assert.That(pnlMain, Is.Not.Null); + + if (pnlMain.Controls.Count > 0) + { + var optionsPage = pnlMain.Controls[0] as mRemoteNG.UI.Forms.OptionsPages.OptionsPage; + Assert.That(optionsPage, Is.Not.Null); + + // Find a checkbox in the options page + var checkBoxes = optionsPage.Controls.Find("", true).OfType().ToList(); + + if (checkBoxes.Count > 0) + { + var checkBox = checkBoxes[0]; + bool originalValue = checkBox.Checked; + checkBox.Checked = !originalValue; + Application.DoEvents(); + + // Verify the page is marked as changed + Assert.That(optionsPage.HasChanges, Is.True); + } + } + } } } \ No newline at end of file