mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
@@ -1,14 +1,62 @@
|
||||
1.75 Beta 3 (2016-12-01):
|
||||
1.75 (2017-03-01):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#289: Install fails during update process (only affects v1.75 beta 1 - v1.75 beta 2)
|
||||
Known Issue:
|
||||
------------
|
||||
File hash check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
Exception will be: "MD5 Hashes didn't match!" for 1.75 Beta 1 - 1.75 RC1
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
#344 - Use SHA512 File Hashes to validate downloads (in the update mechanism & posted to the Downloads page)
|
||||
|
||||
|
||||
1.75 RC1 (2017-01-27):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
Added Release Channels to the update check functionality allowing users to select one of 3 release channels for updates: Stable, Beta, Dev
|
||||
#360: Help -> About, Version # is now selectable/copyable
|
||||
#221: RDP: Optional disconnect after X number of minutes of inactivity
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#369: Reset Layout Option Does Not Reset Notification Pane
|
||||
#362: Invalid cast exception when using the Notification Area Icon minimize/restore
|
||||
#334: Quick Connect displays warning when clicking on a folder
|
||||
#325: When using a connection with an external app, results in opening the same external app continuously
|
||||
#311: Import from Active Directory does not use machine's domain by default
|
||||
#258: Rename Tab dialog - populate original name in dialog (1.72 functionality)
|
||||
#211, #267: Recursive AD Import wasn't fully functional
|
||||
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
The usual general code clean up and refactoring
|
||||
#325: Code clean up and additional logging for External Tools based connections
|
||||
#298: Code clean up and additional logging around application startup
|
||||
#291, #236: External Tools code clean up and additional logging
|
||||
|
||||
|
||||
|
||||
1.75 Beta 3 (2016-12-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#289: Install fails during update process (only affects v1.75 beta 1 - v1.75 beta 2)
|
||||
|
||||
|
||||
1.75 Beta 2 (2016-12-01):
|
||||
|
||||
Features/Enhancements:
|
||||
@@ -21,7 +69,7 @@ Fixes:
|
||||
------
|
||||
#254: Component check window position issues and uncaught exception
|
||||
#260: Crash when attempting to load fully encrypted confCons v2.5
|
||||
#261: Double clicking folder in treeview doesnt expand it in 1.75 beta1
|
||||
#261: Double clicking folder in treeview doesn't expand it in 1.75 beta1
|
||||
#271: Install package is not using the last installation path
|
||||
#278: Silent installs not detecting prerequisites
|
||||
|
||||
@@ -65,7 +113,7 @@ Fixes:
|
||||
MR-965, MR-871, MR-629: Error 264 on RDP Connect attempt - Added timeout value to Tools -> Options -> Connections
|
||||
MR-946: Remove old/insecure SharpSSH and related components. Replace with SSH.NET for File Transfer Functionality
|
||||
MR-896: Added prerequisite installer check for KB2574819. Prevents "Class not registered" errors when opening RDP connections.
|
||||
PR-130: Fix Scan button width to fit russian translation
|
||||
PR-130: Fix Scan button width to fit Russian translation
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +121,7 @@ PR-130: Fix Scan button width to fit russian translation
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
Updated GeckoFx pacakge
|
||||
Updated GeckoFx package
|
||||
Updated DockPanelSuite library to 2.10 Final
|
||||
Japanese translation updated
|
||||
MR-942: Refactored code relating to loading the connections file
|
||||
@@ -148,7 +196,7 @@ Port Scan is now Asynchronous (and is significantly faster)
|
||||
Fixes:
|
||||
------
|
||||
MR-874: Added work-around to installer to ignore installation prerequisites
|
||||
MR-884: Slow startup in some scnearios checking authenticode certificate
|
||||
MR-884: Slow startup in some scenarios checking authenticode certificate
|
||||
MR-872: Crash in External Tools when arguments aren't quoted
|
||||
MR-854: crashes when right clicking on connection tab
|
||||
MR-852: Option "Allow only a single instance of the application" non-functional
|
||||
@@ -289,7 +337,7 @@ Fixed issue MR-398 - Full Screen mode doesn't correctly make use of available sp
|
||||
Fixed issue MR-402 - scrollbar touch moves putty window
|
||||
Fixed issue MR-406 - Items disappear from External Tools toolbar when accessing External Tools panel
|
||||
Fixed issue MR-410 - Unhandled exception when clicking New button under Theme
|
||||
Fixed issue MR-413 - Can't use aplication
|
||||
Fixed issue MR-413 - Can't use application
|
||||
Fixed new connections having a globe icon.
|
||||
Fixed the category names in the themes tab of the options dialog on Windows XP not showing correctly.
|
||||
Fixed PuTTY saved sessions with spaces or special characters not being listed.
|
||||
|
||||
@@ -8,9 +8,12 @@ Sean Kaim (github.com/kmscode)
|
||||
Thanks for the awesome new website!
|
||||
Bennett Blodinger (github.com/benwa)
|
||||
|
||||
Joe Cefoli (github.com/jcefoli)
|
||||
countchappy (github.com/countchappy)
|
||||
Tony Lambert
|
||||
|
||||
|
||||
|
||||
Past Contributors
|
||||
=================
|
||||
|
||||
|
||||
17
README.MD
17
README.MD
@@ -4,12 +4,17 @@
|
||||
[](https://gitter.im/mRemoteNG/PublicChat)
|
||||
[](https://www.paypal.me/DavidSparer)
|
||||
|
||||
[](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/develop/)
|
||||
[](https://waffle.io/mRemoteNG/mRemoteNG)
|
||||
[](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74)
|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/529)
|
||||
|
||||
[](https://waffle.io/mRemoteNG/mRemoteNG)
|
||||
|
||||
| Update Channel | Build Status | Downloads |
|
||||
| ---------------|--------------|-----------|
|
||||
| Stable | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74) |
|
||||
| Beta | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/beta_channel/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Beta3) |
|
||||
| Development | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/develop/) | - |
|
||||
|
||||
|
||||
|
||||
mRemoteNG is the next generation of mRemote, a full-featured, multi-tab remote connections manager.
|
||||
|
||||
@@ -35,8 +40,8 @@ https://support.microsoft.com/en-us/kb/2923545
|
||||
|
||||
Windows 8+ support RDP version 8+ out of the box.
|
||||
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connection successfully to a Windows 2003 host (for example).
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connect successfully to a Windows 2003 host (for example).
|
||||
|
||||
|
||||
|
||||
[](https://www.jetbrains.com/resharper/)
|
||||
[](https://www.jetbrains.com/resharper/)
|
||||
|
||||
@@ -18,7 +18,7 @@ Write-Host Version: $version
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
|
||||
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
|
||||
|
||||
@@ -38,5 +38,5 @@ Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
|
||||
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
84
mRemoteNGTests/App/UpdaterTests.cs
Normal file
84
mRemoteNGTests/App/UpdaterTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNGTests.Properties;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.App
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdaterTests
|
||||
{
|
||||
[Test]
|
||||
public void UpdateStableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateStablePortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
@@ -30,5 +31,43 @@ namespace mRemoteNGTests.Connection
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Domain, Is.EqualTo(_testDomain));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveEnumValuesToString()
|
||||
{
|
||||
const ProtocolType targetProtocol = ProtocolType.RAW;
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.Protocol = targetProtocol;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Protocol, Is.EqualTo(targetProtocol.ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveIntegerValuesToString()
|
||||
{
|
||||
const int targetValue = 123;
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.RDPMinutesToIdleTimeout = targetValue;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.RDPMinutesToIdleTimeout, Is.EqualTo(targetValue.ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveStringValuesToString()
|
||||
{
|
||||
const string targetName = "hello";
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.Username = targetName;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Username, Is.EqualTo(targetName));
|
||||
}
|
||||
|
||||
|
||||
private class AllStringPropertySaveTarget
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Protocol { get; set; }
|
||||
public string RDPMinutesToIdleTimeout { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
77
mRemoteNGTests/Properties/Resources.Designer.cs
generated
77
mRemoteNGTests/Properties/Resources.Designer.cs
generated
@@ -60,6 +60,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string beta_update {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string beta_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" Protected="95syzRuZ4mRxpNkZQzoyX8SDpQXLyMq3GncO8o4SyTBoYvn3TAWgn05ZEU2DrjkM" ConfVersion="2.5">
|
||||
@@ -142,6 +168,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string dev_update {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string dev_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-16"?>
|
||||
///<!-- ****************************************************************-->
|
||||
@@ -276,5 +328,30 @@ namespace mRemoteNGTests.Properties {
|
||||
return ResourceManager.GetString("test_remotedesktopconnection_rdp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.72.5065.32737
|
||||
///dURL: http://downloads.mremoteng.org/mRemoteNG-Installer-1.72.exe
|
||||
///clURL: http://update.mremoteng.org/changes-1.72.txt
|
||||
///CertificateThumbprint: 1cbd910dbd6e77f26506e7f600736972f700673f
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string update {
|
||||
get {
|
||||
return ResourceManager.GetString("update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,12 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="beta_update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\beta-update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="beta_update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\beta-update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="confCons_v2_5" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_5.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
@@ -142,6 +148,12 @@
|
||||
<data name="confCons_v2_6_passwordis_Password_fullencryption" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_6_passwordis_Password_fullencryption.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="dev_update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\dev-update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="dev_update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\dev-update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="test_puttyConnectionManager_database" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\test_puttyConnectionManager_database.dat;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
@@ -163,4 +175,10 @@
|
||||
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
<data name="update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
</root>
|
||||
5
mRemoteNGTests/Resources/beta-update-portable.txt
Normal file
5
mRemoteNGTests/Resources/beta-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/beta-update.txt
Normal file
5
mRemoteNGTests/Resources/beta-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/dev-update-portable.txt
Normal file
5
mRemoteNGTests/Resources/dev-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/dev-update.txt
Normal file
5
mRemoteNGTests/Resources/dev-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/update-portable.txt
Normal file
5
mRemoteNGTests/Resources/update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/update.txt
Normal file
5
mRemoteNGTests/Resources/update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ExpandNodeClickHandlerTests
|
||||
{
|
||||
private ExpandNodeClickHandler _clickHandler;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_clickHandler = new ExpandNodeClickHandler(_connectionTree);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetedNodeIsExpanded()
|
||||
{
|
||||
var folder = new ContainerInfo();
|
||||
_clickHandler.Execute(folder);
|
||||
_connectionTree.Received().ToggleExpansion(folder);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NothingHappensWhenConnectionInfoProvided()
|
||||
{
|
||||
_clickHandler.Execute(new ConnectionInfo());
|
||||
_connectionTree.DidNotReceiveWithAnyArgs().ToggleExpansion(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownOnConstructorNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new ExpandNodeClickHandler(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class OpenConnectionClickHandlerTests
|
||||
{
|
||||
private OpenConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new OpenConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConnectionOpened()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().OpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new OpenConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SwitchToConnectionClickHandlerTests
|
||||
{
|
||||
private SwitchToConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new SwitchToConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SwitchesToConnection()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().SwitchToOpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().SwitchToOpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new SwitchToConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class TreeNodeCompositeClickHandlerTests
|
||||
{
|
||||
private TreeNodeCompositeClickHandler _clickHandler;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_clickHandler = new TreeNodeCompositeClickHandler();
|
||||
_connectionInfo = new ConnectionInfo();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExecutesAllItsHandlers()
|
||||
{
|
||||
var handler1 = Substitute.For<ITreeNodeClickHandler>();
|
||||
var handler2 = Substitute.For<ITreeNodeClickHandler>();
|
||||
_clickHandler.ClickHandlers = new[] {handler1, handler2};
|
||||
_clickHandler.Execute(_connectionInfo);
|
||||
handler1.Received().Execute(_connectionInfo);
|
||||
handler2.Received().Execute(_connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
51
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
51
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ConnectionTreeTests
|
||||
{
|
||||
private ConnectionTree _connectionTree;
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeModel = CreateConnectionTreeModel();
|
||||
_connectionTree = new ConnectionTree
|
||||
{
|
||||
PostSetupActions = new IConnectionTreeDelegate[] {new RootNodeExpander()}
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTree.Dispose();
|
||||
}
|
||||
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanDeleteLastFolderInTheTree()
|
||||
{
|
||||
var lastFolder = new ContainerInfo();
|
||||
_connectionTreeModel.RootNodes[0].AddChild(lastFolder);
|
||||
_connectionTree.ConnectionTreeModel = _connectionTreeModel;
|
||||
_connectionTree.SelectObject(lastFolder);
|
||||
_connectionTree.DeleteSelectedNode();
|
||||
Assert.That(_connectionTree.GetRootConnectionNode().HasChildren, Is.False);
|
||||
}
|
||||
|
||||
private ConnectionTreeModel CreateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
connectionTreeModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection));
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
mRemoteNGTests/Tree/PreviousSessionOpenerTests.cs
Normal file
50
mRemoteNGTests/Tree/PreviousSessionOpenerTests.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviousSessionOpenerTests
|
||||
{
|
||||
private PreviousSessionOpener _previousSessionOpener;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_previousSessionOpener = new PreviousSessionOpener(_connectionInitiator);
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.GetRootConnectionNode().Returns(BuildTree());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllRequestedSessionsAreReopened()
|
||||
{
|
||||
_previousSessionOpener.Execute(_connectionTree);
|
||||
_connectionInitiator.ReceivedWithAnyArgs(2).OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new PreviousSessionOpener(null));
|
||||
}
|
||||
|
||||
private RootNodeInfo BuildTree()
|
||||
{
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
root.AddChild(new ConnectionInfo());
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
mRemoteNGTests/Tree/PreviouslyOpenedFolderExpanderTests.cs
Normal file
49
mRemoteNGTests/Tree/PreviouslyOpenedFolderExpanderTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviouslyOpenedFolderExpanderTests
|
||||
{
|
||||
private PreviouslyOpenedFolderExpander _folderExpander;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_folderExpander = new PreviouslyOpenedFolderExpander();
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandsAllFoldersThatAreMarkedForExpansion()
|
||||
{
|
||||
var connectionTreeModel = GenerateConnectionTreeModel();
|
||||
_connectionTree.ConnectionTreeModel.Returns(connectionTreeModel);
|
||||
_connectionTree.GetRootConnectionNode().Returns(connectionTreeModel.RootNodes[0]);
|
||||
_folderExpander.Execute(_connectionTree);
|
||||
Assert.That(_connectionTree.ExpandedObjects, Is.EquivalentTo(connectionTreeModel.GetRecursiveChildList().OfType<ContainerInfo>().Where(info => info.IsExpanded)));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel GenerateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection) { IsExpanded = true };
|
||||
var folder1 = new ContainerInfo { IsExpanded = true };
|
||||
var folder2 = new ContainerInfo();
|
||||
var con1 = new ConnectionInfo();
|
||||
root.AddChild(folder1);
|
||||
folder1.AddChild(folder2);
|
||||
root.AddChild(con1);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SelectedConnectionDeletionConfirmerTests
|
||||
{
|
||||
private SelectedConnectionDeletionConfirmer _deletionConfirmer;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.SelectedNode.Returns(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingYesReturnsTrue()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickYes);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingNoReturnsFalse()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickNo);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.False);
|
||||
}
|
||||
|
||||
private DialogResult MockClickYes(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.Yes;
|
||||
}
|
||||
|
||||
private DialogResult MockClickNo(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.No;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
mRemoteNGTests/UI/Window/ConnectionTreeWindowTests.cs
Normal file
32
mRemoteNGTests/UI/Window/ConnectionTreeWindowTests.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.UI.Window;
|
||||
using NUnit.Framework;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.UI.Window
|
||||
{
|
||||
public class ConnectionTreeWindowTests
|
||||
{
|
||||
private ConnectionTreeWindow _connectionTreeWindow;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent());
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTreeWindow.Close();
|
||||
}
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanShowWindow()
|
||||
{
|
||||
_connectionTreeWindow.Show();
|
||||
Assert.That(_connectionTreeWindow.Visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -31,7 +31,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -40,7 +40,7 @@
|
||||
<OutputPath>bin\x86\Debug Portable\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;PORTABLE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -49,7 +49,7 @@
|
||||
<DefineConstants>TRACE;PORTABLE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -101,12 +101,15 @@
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="App\LoggerTests.cs" />
|
||||
<Compile Include="App\UpdaterTests.cs" />
|
||||
<Compile Include="BinaryFileTests.cs" />
|
||||
<Compile Include="Config\Serializers\DataTableSerializerTests.cs" />
|
||||
<Compile Include="Config\Serializers\PortScanDeserializerTests.cs" />
|
||||
@@ -127,6 +130,7 @@
|
||||
<Compile Include="Security\KeyDerivation\Pkcs5S2KeyGeneratorTests.cs" />
|
||||
<Compile Include="Security\SecureStringExtensionsTests.cs" />
|
||||
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
|
||||
<Compile Include="Connection\ConnectionInfoInheritanceTests.cs" />
|
||||
@@ -146,8 +150,15 @@
|
||||
<Compile Include="Security\CryptographyProviderFactoryTests.cs" />
|
||||
<Compile Include="Security\EncryptedSecureStringTests.cs" />
|
||||
<Compile Include="Security\LegacyRijndaelCryptographyProviderTests.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\ExpandNodeClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\NodeSearcherTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\OpenConnectionClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\PreviouslyOpenedFolderExpanderTests.cs" />
|
||||
<Compile Include="Tree\PreviousSessionOpenerTests.cs" />
|
||||
<Compile Include="Tree\RootNodeInfoTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
|
||||
<Compile Include="UI\Controls\TestForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -157,6 +168,7 @@
|
||||
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
|
||||
<Compile Include="UI\Forms\PasswordFormTests.cs" />
|
||||
<Compile Include="UI\WindowListTests.cs" />
|
||||
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -207,6 +219,14 @@
|
||||
<ItemGroup>
|
||||
<None Include="Resources\confCons_v2_5_passwordis_Password_fullencryption.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\beta-update-portable.txt" />
|
||||
<Content Include="Resources\beta-update.txt" />
|
||||
<Content Include="Resources\dev-update-portable.txt" />
|
||||
<Content Include="Resources\dev-update.txt" />
|
||||
<Content Include="Resources\update-portable.txt" />
|
||||
<Content Include="Resources\update.txt" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
|
||||
2
mRemoteNGTests/mRemoteNGTests.csproj.DotSettings
Normal file
2
mRemoteNGTests/mRemoteNGTests.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=tree_005Cclickhandlers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -8,24 +8,23 @@ using System.Windows.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class CompatibilityChecker
|
||||
public static class CompatibilityChecker
|
||||
{
|
||||
public void CheckCompatibility()
|
||||
public static void CheckCompatibility()
|
||||
{
|
||||
CheckFipsPolicy();
|
||||
CheckLenovoAutoScrollUtility();
|
||||
}
|
||||
|
||||
private void CheckFipsPolicy()
|
||||
private static void CheckFipsPolicy()
|
||||
{
|
||||
if (FipsPolicyEnabledForServer2003() || FipsPolicyEnabledForServer2008AndNewer())
|
||||
{
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
Logger.Instance.InfoFormat("Checking FIPS Policy...");
|
||||
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2003()
|
||||
private static bool FipsPolicyEnabledForServer2003()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa");
|
||||
var fipsPolicy = regKey?.GetValue("FIPSAlgorithmPolicy");
|
||||
@@ -34,7 +33,7 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
private static bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy");
|
||||
var fipsPolicy = regKey?.GetValue("Enabled");
|
||||
@@ -43,12 +42,14 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private void CheckLenovoAutoScrollUtility()
|
||||
private static void CheckLenovoAutoScrollUtility()
|
||||
{
|
||||
Logger.Instance.InfoFormat("Checking Lenovo AutoScroll Utility...");
|
||||
|
||||
if (!Settings.Default.CompatibilityWarnLenovoAutoScrollUtility)
|
||||
return;
|
||||
|
||||
Process[] proccesses = new Process[] { };
|
||||
var proccesses = new Process[] { };
|
||||
try
|
||||
{
|
||||
proccesses = Process.GetProcessesByName("virtscrl");
|
||||
@@ -58,12 +59,10 @@ namespace mRemoteNG.App
|
||||
Runtime.MessageCollector.AddExceptionMessage("Error in CheckLenovoAutoScrollUtility", ex);
|
||||
}
|
||||
|
||||
if (proccesses.Length > 0)
|
||||
{
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
if (proccesses.Length <= 0) return;
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
|
||||
if (exportForm.ShowDialog(frmMain.Default) != DialogResult.OK)
|
||||
return ;
|
||||
return;
|
||||
|
||||
ConnectionInfo exportTarget;
|
||||
switch (exportForm.Scope)
|
||||
@@ -76,12 +76,17 @@ namespace mRemoteNG.App
|
||||
var factory = new CryptographyProviderFactory();
|
||||
var cryptographyProvider = factory.CreateAeadCryptographyProvider(mRemoteNG.Settings.Default.EncryptionEngine, mRemoteNG.Settings.Default.EncryptionBlockCipherMode);
|
||||
cryptographyProvider.KeyDerivationIterations = Settings.Default.EncryptionKeyDerivationIterations;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider);
|
||||
((XmlConnectionsSerializer) serializer).SaveFilter = saveFilter;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider)
|
||||
{
|
||||
Export = true,
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
case ConnectionsSaver.Format.mRCSV:
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat();
|
||||
((CsvConnectionsSerializerMremotengFormat)serializer).SaveFilter = saveFilter;
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat
|
||||
{
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(saveFormat), saveFormat, null);
|
||||
|
||||
@@ -11,23 +11,27 @@ namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class GeneralAppInfo
|
||||
{
|
||||
public static readonly string UrlHome = "http://www.mremoteng.org/";
|
||||
public static readonly string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public static readonly string UrlForum = "http://forum.mremoteng.org/";
|
||||
public static readonly string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static readonly string ApplicationVersion = Application.ProductVersion;
|
||||
public const string UrlHome = "http://www.mremoteng.org/";
|
||||
public const string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public const string UrlForum = "http://forum.mremoteng.org/";
|
||||
public const string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static string ApplicationVersion = Application.ProductVersion;
|
||||
public static readonly string ProductName = Application.ProductName;
|
||||
public static readonly string Copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCopyrightAttribute), false)).Copyright;
|
||||
public static readonly string HomePath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||
public static string ReportingFilePath = "";
|
||||
//public static string ReportingFilePath = "";
|
||||
public static readonly string PuttyPath = HomePath + "\\PuTTYNG.exe";
|
||||
public static string UserAgent
|
||||
{
|
||||
get
|
||||
{
|
||||
var details = new List<string>();
|
||||
details.Add("compatible");
|
||||
details.Add(OSVersion.Platform == PlatformID.Win32NT ? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}": OSVersion.VersionString);
|
||||
var details = new List<string>
|
||||
{
|
||||
"compatible",
|
||||
OSVersion.Platform == PlatformID.Win32NT
|
||||
? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}"
|
||||
: OSVersion.VersionString
|
||||
};
|
||||
if (Is64BitProcess)
|
||||
{
|
||||
details.Add("WOW64");
|
||||
|
||||
@@ -1,34 +1,72 @@
|
||||
namespace mRemoteNG.App.Info
|
||||
using System;
|
||||
|
||||
namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class UpdateChannelInfo
|
||||
{
|
||||
public static string FileName
|
||||
public const string STABLE = "Stable";
|
||||
public const string BETA = "Beta";
|
||||
public const string DEV = "Development";
|
||||
|
||||
/* no #if here since they are used for unit tests as well */
|
||||
public const string STABLE_PORTABLE = "update-portable.txt";
|
||||
public const string BETA_PORTABLE = "beta-update-portable.txt";
|
||||
public const string DEV_PORTABLE = "dev-update-portable.txt";
|
||||
|
||||
public const string STABLE_MSI = "update.txt";
|
||||
public const string BETA_MSI = "beta-update.txt";
|
||||
public const string DEV_MSI = "dev-update.txt";
|
||||
|
||||
|
||||
public static Uri GetUpdateChannelInfo()
|
||||
{
|
||||
var channel = IsValidChannel(Settings.Default.UpdateChannel) ? Settings.Default.UpdateChannel : STABLE;
|
||||
return GetUpdateTxtUri(channel);
|
||||
}
|
||||
|
||||
private static string GetChannelFileName(string channel)
|
||||
{
|
||||
#if PORTABLE
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return PORTABLE update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-portable-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-portable-debug.txt" : "update-portable.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_PORTABLE;
|
||||
case BETA:
|
||||
return BETA_PORTABLE;
|
||||
case DEV:
|
||||
return DEV_PORTABLE;
|
||||
default:
|
||||
return STABLE_PORTABLE;
|
||||
}
|
||||
#else //NOT portable
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return INSTALLER update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-debug.txt" : "update.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_MSI;
|
||||
case BETA:
|
||||
return BETA_MSI;
|
||||
case DEV:
|
||||
return DEV_MSI;
|
||||
default:
|
||||
return STABLE_MSI;
|
||||
}
|
||||
#endif //endif for PORTABLE
|
||||
}
|
||||
|
||||
private static Uri GetUpdateTxtUri(string channel)
|
||||
{
|
||||
return new Uri(new Uri(Settings.Default.UpdateAddress), new Uri(GetChannelFileName(channel), UriKind.Relative));
|
||||
}
|
||||
|
||||
private static bool IsValidChannel(string s)
|
||||
{
|
||||
return s.Equals(STABLE) || s.Equals(BETA) || s.Equals(DEV);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
@@ -326,6 +327,11 @@ namespace mRemoteNG.App
|
||||
/// </summary>
|
||||
public const int WM_ACTIVATEAPP = 0x1C;
|
||||
|
||||
/// <summary>
|
||||
/// Sent to a window if the mouse causes the cursor to move within a window and mouse input is not captured.
|
||||
/// </summary>
|
||||
public const int WM_SETCURSOR = 0x20;
|
||||
|
||||
/// <summary>
|
||||
/// Sent when the cursor is in an inactive window and the user presses a mouse button. The parent window receives this message only if the child window passes it to the DefWindowProc function.
|
||||
/// </summary>
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace mRemoteNG.App
|
||||
#region Public Properties
|
||||
public static WindowList WindowList { get; set; }
|
||||
public static MessageCollector MessageCollector { get; set; }
|
||||
public static Controls.NotificationAreaIcon NotificationAreaIcon { get; set; }
|
||||
public static NotificationAreaIcon NotificationAreaIcon { get; set; }
|
||||
public static bool IsConnectionsFileLoaded { get; set; }
|
||||
public static RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; }
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
@@ -42,8 +42,8 @@ namespace mRemoteNG.App
|
||||
public static SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
|
||||
public static ConnectionTreeModel ConnectionTreeModel
|
||||
{
|
||||
get { return Windows.TreeForm.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTreeModel = value; }
|
||||
get { return Windows.TreeForm.ConnectionTree.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTree.ConnectionTreeModel = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace mRemoteNG.App
|
||||
// Load config
|
||||
connectionsLoader.ConnectionFileName = filename;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -274,7 +274,7 @@ namespace mRemoteNG.App
|
||||
{
|
||||
if (withDialog)
|
||||
{
|
||||
var loadDialog = Controls.ConnectionsLoadDialog();
|
||||
var loadDialog = ConnectionsLoadDialog();
|
||||
if (loadDialog.ShowDialog() != DialogResult.OK) return;
|
||||
connectionsLoader.ConnectionFileName = loadDialog.FileName;
|
||||
}
|
||||
@@ -288,7 +288,7 @@ namespace mRemoteNG.App
|
||||
|
||||
connectionsLoader.UseDatabase = Settings.Default.UseSQLServer;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
|
||||
if (Settings.Default.UseSQLServer)
|
||||
{
|
||||
@@ -353,6 +353,16 @@ namespace mRemoteNG.App
|
||||
}
|
||||
}
|
||||
|
||||
private static OpenFileDialog ConnectionsLoadDialog()
|
||||
{
|
||||
return new OpenFileDialog
|
||||
{
|
||||
CheckFileExists = true,
|
||||
InitialDirectory = ConnectionsFileInfo.DefaultConnectionsPath,
|
||||
Filter = Language.strFiltermRemoteXML + @"|*.xml|" + Language.strFilterAll + @"|*.*"
|
||||
};
|
||||
}
|
||||
|
||||
private static void CreateBackupFile(string fileName)
|
||||
{
|
||||
// This intentionally doesn't prune any existing backup files. We just assume the user doesn't want any new ones created.
|
||||
@@ -593,7 +603,8 @@ namespace mRemoteNG.App
|
||||
connectionInfo.Protocol = url.StartsWith("https:") ? ProtocolType.HTTPS : ProtocolType.HTTP;
|
||||
connectionInfo.SetDefaultPort();
|
||||
connectionInfo.IsQuickConnect = true;
|
||||
ConnectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
var connectionInitiator = new ConnectionInitiator();
|
||||
connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public static void GoToWebsite()
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
@@ -14,22 +7,26 @@ using System.IO;
|
||||
using System.Management;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.Connections.Multiuser;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private CompatibilityChecker _compatibilityChecker;
|
||||
private AppUpdater _appUpdate;
|
||||
|
||||
public static Startup Instance { get; } = new Startup();
|
||||
|
||||
private Startup()
|
||||
{
|
||||
_compatibilityChecker = new CompatibilityChecker();
|
||||
_appUpdate = new AppUpdater();
|
||||
}
|
||||
|
||||
@@ -41,49 +38,31 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Debug.Print("---------------------------" + Environment.NewLine + "[START] - " + Convert.ToString(DateTime.Now, CultureInfo.InvariantCulture));
|
||||
LogStartupData();
|
||||
_compatibilityChecker.CheckCompatibility();
|
||||
CompatibilityChecker.CheckCompatibility();
|
||||
ParseCommandLineArgs();
|
||||
IeBrowserEmulation.Register();
|
||||
GetConnectionIcons();
|
||||
DefaultConnectionInfo.Instance.LoadFrom(Settings.Default, (a)=>"ConDefault"+a);
|
||||
DefaultConnectionInheritance.Instance.LoadFrom(Settings.Default, (a)=>"InhDefault"+a);
|
||||
DefaultConnectionInfo.Instance.LoadFrom(Settings.Default, a=>"ConDefault"+a);
|
||||
DefaultConnectionInheritance.Instance.LoadFrom(Settings.Default, a=>"InhDefault"+a);
|
||||
}
|
||||
|
||||
public void SetDefaultLayout()
|
||||
private static void GetConnectionIcons()
|
||||
{
|
||||
frmMain.Default.pnlDock.Visible = false;
|
||||
|
||||
frmMain.Default.pnlDock.DockLeftPortion = frmMain.Default.pnlDock.Width * 0.2;
|
||||
frmMain.Default.pnlDock.DockRightPortion = frmMain.Default.pnlDock.Width * 0.2;
|
||||
frmMain.Default.pnlDock.DockTopPortion = frmMain.Default.pnlDock.Height * 0.25;
|
||||
frmMain.Default.pnlDock.DockBottomPortion = frmMain.Default.pnlDock.Height * 0.25;
|
||||
|
||||
Windows.TreePanel.Show(frmMain.Default.pnlDock, DockState.DockLeft);
|
||||
Windows.ConfigPanel.Show(frmMain.Default.pnlDock);
|
||||
Windows.ConfigPanel.DockTo(Windows.TreePanel.Pane, DockStyle.Bottom, -1);
|
||||
|
||||
Windows.ScreenshotForm.Hide();
|
||||
|
||||
frmMain.Default.pnlDock.Visible = true;
|
||||
}
|
||||
|
||||
private void GetConnectionIcons()
|
||||
{
|
||||
string iPath = GeneralAppInfo.HomePath + "\\Icons\\";
|
||||
var iPath = GeneralAppInfo.HomePath + "\\Icons\\";
|
||||
if (Directory.Exists(iPath) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string f in Directory.GetFiles(iPath, "*.ico", SearchOption.AllDirectories))
|
||||
foreach (var f in Directory.GetFiles(iPath, "*.ico", SearchOption.AllDirectories))
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(f);
|
||||
var fInfo = new FileInfo(f);
|
||||
Array.Resize(ref ConnectionIcon.Icons, ConnectionIcon.Icons.Length + 1);
|
||||
ConnectionIcon.Icons.SetValue(fInfo.Name.Replace(".ico", ""), ConnectionIcon.Icons.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogStartupData()
|
||||
private static void LogStartupData()
|
||||
{
|
||||
if (!Settings.Default.WriteLogFile) return;
|
||||
LogApplicationData();
|
||||
@@ -93,17 +72,17 @@ namespace mRemoteNG.App
|
||||
LogCultureData();
|
||||
}
|
||||
|
||||
private void LogSystemData()
|
||||
private static void LogSystemData()
|
||||
{
|
||||
string osData = GetOperatingSystemData();
|
||||
string architecture = GetArchitectureData();
|
||||
var osData = GetOperatingSystemData();
|
||||
var architecture = GetArchitectureData();
|
||||
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(Convert.ToString(s)))));
|
||||
}
|
||||
|
||||
private string GetOperatingSystemData()
|
||||
private static string GetOperatingSystemData()
|
||||
{
|
||||
string osVersion = string.Empty;
|
||||
string servicePack = string.Empty;
|
||||
var osVersion = string.Empty;
|
||||
var servicePack = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -118,13 +97,13 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Logger.Instance.WarnFormat($"Error retrieving operating system information from WMI. {ex.Message}");
|
||||
}
|
||||
string osData = string.Join(" ", new string[] { osVersion, servicePack });
|
||||
var osData = string.Join(" ", osVersion, servicePack);
|
||||
return osData;
|
||||
}
|
||||
|
||||
private string GetOSServicePack(string servicePack, ManagementObject managementObject)
|
||||
private static string GetOSServicePack(string servicePack, ManagementObject managementObject)
|
||||
{
|
||||
int servicePackNumber = Convert.ToInt32(managementObject.GetPropertyValue("ServicePackMajorVersion"));
|
||||
var servicePackNumber = Convert.ToInt32(managementObject.GetPropertyValue("ServicePackMajorVersion"));
|
||||
if (servicePackNumber != 0)
|
||||
{
|
||||
servicePack = $"Service Pack {servicePackNumber}";
|
||||
@@ -132,15 +111,15 @@ namespace mRemoteNG.App
|
||||
return servicePack;
|
||||
}
|
||||
|
||||
private string GetArchitectureData()
|
||||
private static string GetArchitectureData()
|
||||
{
|
||||
string architecture = string.Empty;
|
||||
var architecture = string.Empty;
|
||||
try
|
||||
{
|
||||
foreach (var o in new ManagementObjectSearcher("SELECT * FROM Win32_Processor WHERE DeviceID=\'CPU0\'").Get())
|
||||
{
|
||||
var managementObject = (ManagementObject) o;
|
||||
int addressWidth = Convert.ToInt32(managementObject.GetPropertyValue("AddressWidth"));
|
||||
var addressWidth = Convert.ToInt32(managementObject.GetPropertyValue("AddressWidth"));
|
||||
architecture = $"{addressWidth}-bit";
|
||||
}
|
||||
}
|
||||
@@ -151,7 +130,7 @@ namespace mRemoteNG.App
|
||||
return architecture;
|
||||
}
|
||||
|
||||
private void LogApplicationData()
|
||||
private static void LogApplicationData()
|
||||
{
|
||||
#if !PORTABLE
|
||||
Logger.Instance.InfoFormat($"{Application.ProductName} {Application.ProductVersion} starting.");
|
||||
@@ -161,17 +140,17 @@ namespace mRemoteNG.App
|
||||
#endif
|
||||
}
|
||||
|
||||
private void LogCmdLineArgs()
|
||||
private static void LogCmdLineArgs()
|
||||
{
|
||||
Logger.Instance.InfoFormat($"Command Line: {Environment.GetCommandLineArgs()}");
|
||||
}
|
||||
|
||||
private void LogCLRData()
|
||||
private static void LogCLRData()
|
||||
{
|
||||
Logger.Instance.InfoFormat($"Microsoft .NET CLR {Environment.Version}");
|
||||
}
|
||||
|
||||
private void LogCultureData()
|
||||
private static void LogCultureData()
|
||||
{
|
||||
Logger.Instance.InfoFormat(
|
||||
$"System Culture: {Thread.CurrentThread.CurrentUICulture.Name}/{Thread.CurrentThread.CurrentUICulture.NativeName}");
|
||||
@@ -197,7 +176,7 @@ namespace mRemoteNG.App
|
||||
return;
|
||||
}
|
||||
|
||||
DateTime nextUpdateCheck = Convert.ToDateTime(Settings.Default.CheckForUpdatesLastCheck.Add(TimeSpan.FromDays(Convert.ToDouble(Settings.Default.CheckForUpdatesFrequencyDays))));
|
||||
var nextUpdateCheck = Convert.ToDateTime(Settings.Default.CheckForUpdatesLastCheck.Add(TimeSpan.FromDays(Convert.ToDouble(Settings.Default.CheckForUpdatesFrequencyDays))));
|
||||
if (!Settings.Default.UpdatePending && DateTime.UtcNow < nextUpdateCheck)
|
||||
{
|
||||
return;
|
||||
@@ -211,7 +190,7 @@ namespace mRemoteNG.App
|
||||
{
|
||||
if (frmMain.Default.InvokeRequired)
|
||||
{
|
||||
frmMain.Default.Invoke(new AsyncCompletedEventHandler(GetUpdateInfoCompleted), new object[] { sender, e });
|
||||
frmMain.Default.Invoke(new AsyncCompletedEventHandler(GetUpdateInfoCompleted), sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,7 +204,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
if (e.Error != null)
|
||||
{
|
||||
throw (e.Error);
|
||||
throw e.Error;
|
||||
}
|
||||
|
||||
if (_appUpdate.IsUpdateAvailable())
|
||||
@@ -240,13 +219,13 @@ namespace mRemoteNG.App
|
||||
}
|
||||
|
||||
|
||||
private void ParseCommandLineArgs()
|
||||
private static void ParseCommandLineArgs()
|
||||
{
|
||||
try
|
||||
{
|
||||
CmdArgumentsInterpreter cmd = new CmdArgumentsInterpreter(Environment.GetCommandLineArgs());
|
||||
var cmd = new CmdArgumentsInterpreter(Environment.GetCommandLineArgs());
|
||||
|
||||
string ConsParam = "";
|
||||
var ConsParam = "";
|
||||
if (cmd["cons"] != null)
|
||||
{
|
||||
ConsParam = "cons";
|
||||
@@ -256,7 +235,7 @@ namespace mRemoteNG.App
|
||||
ConsParam = "c";
|
||||
}
|
||||
|
||||
string ResetPosParam = "";
|
||||
var ResetPosParam = "";
|
||||
if (cmd["resetpos"] != null)
|
||||
{
|
||||
ResetPosParam = "resetpos";
|
||||
@@ -266,7 +245,7 @@ namespace mRemoteNG.App
|
||||
ResetPosParam = "rp";
|
||||
}
|
||||
|
||||
string ResetPanelsParam = "";
|
||||
var ResetPanelsParam = "";
|
||||
if (cmd["resetpanels"] != null)
|
||||
{
|
||||
ResetPanelsParam = "resetpanels";
|
||||
@@ -276,7 +255,7 @@ namespace mRemoteNG.App
|
||||
ResetPanelsParam = "rpnl";
|
||||
}
|
||||
|
||||
string ResetToolbarsParam = "";
|
||||
var ResetToolbarsParam = "";
|
||||
if (cmd["resettoolbar"] != null)
|
||||
{
|
||||
ResetToolbarsParam = "resettoolbar";
|
||||
@@ -293,7 +272,7 @@ namespace mRemoteNG.App
|
||||
ResetToolbarsParam = "rtbr";
|
||||
}
|
||||
|
||||
string NoReconnectParam = "";
|
||||
var NoReconnectParam = "";
|
||||
if (cmd["noreconnect"] != null)
|
||||
{
|
||||
NoReconnectParam = "noreconnect";
|
||||
@@ -313,7 +292,7 @@ namespace mRemoteNG.App
|
||||
Settings.Default.CustomConsPath = GeneralAppInfo.HomePath + "\\" + cmd[ConsParam];
|
||||
return;
|
||||
}
|
||||
else if (File.Exists(ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam]))
|
||||
if (File.Exists(ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam]))
|
||||
{
|
||||
Settings.Default.LoadConsFromCustomLocation = true;
|
||||
Settings.Default.CustomConsPath = ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam];
|
||||
|
||||
@@ -9,116 +9,120 @@ using mRemoteNG.Security.SymmetricEncryption;
|
||||
using System.Security.Cryptography;
|
||||
#if !PORTABLE
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
#else
|
||||
using System.Windows.Forms;
|
||||
#endif
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
public class AppUpdater
|
||||
{
|
||||
private WebProxy _webProxy;
|
||||
public class AppUpdater
|
||||
{
|
||||
private WebProxy _webProxy;
|
||||
private Thread _getUpdateInfoThread;
|
||||
private Thread _getChangeLogThread;
|
||||
|
||||
#region Public Properties
|
||||
#region Public Properties
|
||||
|
||||
public UpdateInfo CurrentUpdateInfo { get; private set; }
|
||||
|
||||
public string ChangeLog { get; private set; }
|
||||
public string ChangeLog { get; private set; }
|
||||
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void SetProxySettings()
|
||||
{
|
||||
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
|
||||
var proxyAddress = Settings.Default.UpdateProxyAddress;
|
||||
var port = Settings.Default.UpdateProxyPort;
|
||||
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
|
||||
var username = Settings.Default.UpdateProxyAuthUser;
|
||||
#region Public Methods
|
||||
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
|
||||
private void SetProxySettings()
|
||||
{
|
||||
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
|
||||
var proxyAddress = Settings.Default.UpdateProxyAddress;
|
||||
var port = Settings.Default.UpdateProxyPort;
|
||||
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
|
||||
var username = Settings.Default.UpdateProxyAuthUser;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
|
||||
SetProxySettings(shouldWeUseProxy, proxyAddress, port, useAuthentication, username, password);
|
||||
}
|
||||
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
}
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
#if !PORTABLE
|
||||
CurrentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "msi"));
|
||||
#else
|
||||
@@ -138,166 +142,174 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
#endif
|
||||
DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
private WebClient _downloadUpdateWebClient;
|
||||
private WebClient DownloadUpdateWebClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
|
||||
_downloadUpdateWebClient = CreateWebClient();
|
||||
|
||||
_downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged;
|
||||
_downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted;
|
||||
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private WebClient CreateWebClient()
|
||||
{
|
||||
var webClient = new WebClient();
|
||||
webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent);
|
||||
webClient.Proxy = _webProxy;
|
||||
return webClient;
|
||||
}
|
||||
|
||||
private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result, Exception exception, bool cancelled, object userToken)
|
||||
{
|
||||
var type = typeof(DownloadStringCompletedEventArgs);
|
||||
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
Type[] argumentTypes = {typeof(string), typeof(Exception), typeof(bool), typeof(object)};
|
||||
var constructor = type.GetConstructor(bindingFlags, null, argumentTypes, null);
|
||||
object[] arguments = {result, exception, cancelled, userToken};
|
||||
}
|
||||
|
||||
return (DownloadStringCompletedEventArgs)constructor.Invoke(arguments);
|
||||
}
|
||||
|
||||
private DownloadStringCompletedEventArgs DownloadString(Uri address)
|
||||
{
|
||||
var webClient = CreateWebClient();
|
||||
var result = string.Empty;
|
||||
Exception exception = null;
|
||||
var cancelled = false;
|
||||
|
||||
try
|
||||
{
|
||||
result = webClient.DownloadString(address);
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
cancelled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null);
|
||||
}
|
||||
|
||||
private void GetUpdateInfo()
|
||||
{
|
||||
var updateFileUri = new Uri(new Uri(Convert.ToString(Settings.Default.UpdateAddress)), new Uri(UpdateChannelInfo.FileName, UriKind.Relative));
|
||||
var e = DownloadString(updateFileUri);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
CurrentUpdateInfo = UpdateInfo.FromString(e.Result);
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private WebClient _downloadUpdateWebClient;
|
||||
|
||||
private WebClient DownloadUpdateWebClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
|
||||
_downloadUpdateWebClient = CreateWebClient();
|
||||
|
||||
_downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged;
|
||||
_downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted;
|
||||
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private WebClient CreateWebClient()
|
||||
{
|
||||
var webClient = new WebClient();
|
||||
webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent);
|
||||
webClient.Proxy = _webProxy;
|
||||
return webClient;
|
||||
}
|
||||
|
||||
private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result,
|
||||
Exception exception, bool cancelled, object userToken)
|
||||
{
|
||||
var type = typeof(DownloadStringCompletedEventArgs);
|
||||
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
Type[] argumentTypes = {typeof(string), typeof(Exception), typeof(bool), typeof(object)};
|
||||
var constructor = type.GetConstructor(bindingFlags, null, argumentTypes, null);
|
||||
object[] arguments = {result, exception, cancelled, userToken};
|
||||
|
||||
return (DownloadStringCompletedEventArgs) constructor.Invoke(arguments);
|
||||
}
|
||||
|
||||
public DownloadStringCompletedEventArgs DownloadString(Uri address)
|
||||
{
|
||||
var webClient = CreateWebClient();
|
||||
var result = string.Empty;
|
||||
Exception exception = null;
|
||||
var cancelled = false;
|
||||
|
||||
try
|
||||
{
|
||||
result = webClient.DownloadString(address);
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
cancelled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null);
|
||||
}
|
||||
|
||||
private void GetUpdateInfo()
|
||||
{
|
||||
var e = DownloadString(UpdateChannelInfo.GetUpdateChannelInfo());
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
CurrentUpdateInfo = UpdateInfo.FromString(e.Result);
|
||||
|
||||
Settings.Default.CheckForUpdatesLastCheck = DateTime.UtcNow;
|
||||
if (!Settings.Default.UpdatePending)
|
||||
{
|
||||
if (!Settings.Default.UpdatePending)
|
||||
{
|
||||
Settings.Default.UpdatePending = IsUpdateAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetUpdateInfoCompletedEventEvent?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void GetChangeLog()
|
||||
{
|
||||
var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
ChangeLog = e.Result;
|
||||
}
|
||||
|
||||
private void GetChangeLog()
|
||||
{
|
||||
var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
ChangeLog = e.Result;
|
||||
}
|
||||
|
||||
GetChangeLogCompletedEventEvent?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
|
||||
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
DownloadUpdateProgressChangedEventEvent?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
var raiseEventArgs = e;
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
var raiseEventArgs = e;
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if !PORTABLE
|
||||
var updateAuthenticode = new Authenticode(CurrentUpdateInfo.UpdateFilePath)
|
||||
{
|
||||
RequireThumbprintMatch = true,
|
||||
ThumbprintToMatch = CurrentUpdateInfo.CertificateThumbprint
|
||||
};
|
||||
{
|
||||
RequireThumbprintMatch = true,
|
||||
ThumbprintToMatch = CurrentUpdateInfo.CertificateThumbprint
|
||||
};
|
||||
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
throw (updateAuthenticode.Exception);
|
||||
}
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
throw updateAuthenticode.Exception;
|
||||
}
|
||||
|
||||
throw (new Exception(updateAuthenticode.StatusMessage));
|
||||
}
|
||||
throw new Exception(updateAuthenticode.StatusMessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
using (var md5 = MD5.Create())
|
||||
using (var cksum = SHA512.Create())
|
||||
{
|
||||
using (var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath))
|
||||
{
|
||||
var hash = md5.ComputeHash(stream);
|
||||
var hash = cksum.ComputeHash(stream);
|
||||
var hashString = BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
|
||||
if (!hashString.Equals(CurrentUpdateInfo.Checksum))
|
||||
throw new Exception("MD5 Hashes didn't match!");
|
||||
throw new Exception("SHA512 Hashes didn't match!");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
raiseEventArgs = new AsyncCompletedEventArgs(ex, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEventArgs.Cancelled || raiseEventArgs.Error != null)
|
||||
{
|
||||
File.Delete(CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
raiseEventArgs = new AsyncCompletedEventArgs(ex, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEventArgs.Cancelled || raiseEventArgs.Error != null)
|
||||
{
|
||||
File.Delete(CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
|
||||
DownloadUpdateCompletedEventEvent?.Invoke(this, raiseEventArgs);
|
||||
|
||||
_downloadUpdateWebClient.Dispose();
|
||||
_downloadUpdateWebClient = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
_downloadUpdateWebClient = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
private AsyncCompletedEventHandler GetUpdateInfoCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler GetUpdateInfoCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -311,6 +323,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler GetChangeLogCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler GetChangeLogCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -323,7 +336,8 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
|
||||
public event DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEvent
|
||||
{
|
||||
add
|
||||
@@ -337,6 +351,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler DownloadUpdateCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler DownloadUpdateCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -348,6 +363,7 @@ namespace mRemoteNG.App.Update
|
||||
DownloadUpdateCompletedEventEvent = (AsyncCompletedEventHandler)Delegate.Remove(DownloadUpdateCompletedEventEvent, value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
@@ -14,7 +15,8 @@ namespace mRemoteNG.App.Update
|
||||
#if !PORTABLE
|
||||
public string CertificateThumbprint { get; private set; }
|
||||
#endif
|
||||
public string FileName { get; private set; }
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public string FileName { get; set; }
|
||||
public string Checksum { get; private set; }
|
||||
|
||||
public static UpdateInfo FromString(string input)
|
||||
@@ -30,16 +32,45 @@ namespace mRemoteNG.App.Update
|
||||
newInfo.Version = updateFile.GetVersion();
|
||||
newInfo.DownloadAddress = updateFile.GetUri("dURL");
|
||||
newInfo.ChangeLogAddress = updateFile.GetUri("clURL");
|
||||
#if false
|
||||
newInfo.ImageAddress = updateFile.GetUri("imgURL");
|
||||
newInfo.ImageLinkAddress = updateFile.GetUri("imgURLLink");
|
||||
#endif
|
||||
#if !PORTABLE
|
||||
newInfo.CertificateThumbprint = updateFile.GetThumbprint();
|
||||
#endif
|
||||
newInfo.FileName = updateFile.GetFileName();
|
||||
newInfo.Checksum = updateFile.GetChecksum();
|
||||
newInfo.IsValid = true;
|
||||
newInfo.IsValid = newInfo.CheckIfValid();
|
||||
}
|
||||
return newInfo;
|
||||
}
|
||||
|
||||
public bool CheckIfValid()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Version.ToString()))
|
||||
return false;
|
||||
if(string.IsNullOrEmpty(DownloadAddress.AbsoluteUri))
|
||||
return false;
|
||||
if (string.IsNullOrEmpty(ChangeLogAddress.AbsoluteUri))
|
||||
return false;
|
||||
#if false
|
||||
if (string.IsNullOrEmpty(ImageAddress.AbsoluteUri))
|
||||
return false;
|
||||
if (string.IsNullOrEmpty(ImageLinkAddress.AbsoluteUri))
|
||||
return false;
|
||||
#endif
|
||||
#if !PORTABLE
|
||||
if (string.IsNullOrEmpty(CertificateThumbprint))
|
||||
return false;
|
||||
#endif
|
||||
if (string.IsNullOrEmpty(FileName))
|
||||
return false;
|
||||
// ReSharper disable once ConvertIfStatementToReturnStatement
|
||||
if (string.IsNullOrEmpty(Checksum))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace mRemoteNG.Config.Connections
|
||||
if (!VerifyDatabaseVersion(sqlConnector))
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
var rootTreeNode = Runtime.ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher != null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -158,7 +158,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_eventWatcher.EnableRaisingEvents = false;
|
||||
_eventWatcher.Dispose();
|
||||
@@ -231,7 +231,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_puttyConfFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_puttyConfFile))
|
||||
{
|
||||
@@ -299,7 +299,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_sessionFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_sessionFile))
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
// check/continue here so we don't create empty connection objects
|
||||
if(!_importSubOU) continue;
|
||||
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer);
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer, _importSubOU);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
connectionInfo.RenderingEngine = (HTTPBase.RenderingEngine)Enum.Parse(typeof(HTTPBase.RenderingEngine), (string)dataRow["RenderingEngine"]);
|
||||
connectionInfo.ICAEncryptionStrength = (ProtocolICA.EncryptionStrength)Enum.Parse(typeof(ProtocolICA.EncryptionStrength), (string)dataRow["ICAEncryptionStrength"]);
|
||||
connectionInfo.RDPAuthenticationLevel = (ProtocolRDP.AuthenticationLevel)Enum.Parse(typeof(ProtocolRDP.AuthenticationLevel), (string)dataRow["RDPAuthenticationLevel"]);
|
||||
connectionInfo.RDPMinutesToIdleTimeout = (int)dataRow["RDPMinutesToIdleTimeout"];
|
||||
connectionInfo.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
|
||||
connectionInfo.LoadBalanceInfo = (string)dataRow["LoadBalanceInfo"];
|
||||
connectionInfo.Colors = (ProtocolRDP.RDPColors)Enum.Parse(typeof(ProtocolRDP.RDPColors) ,(string)dataRow["Colors"]);
|
||||
connectionInfo.Resolution = (ProtocolRDP.RDPResolutions)Enum.Parse(typeof(ProtocolRDP.RDPResolutions), (string)dataRow["Resolution"]);
|
||||
@@ -153,6 +155,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
connectionInfo.Inheritance.Username = (bool)dataRow["InheritUsername"];
|
||||
connectionInfo.Inheritance.ICAEncryptionStrength = (bool)dataRow["InheritICAEncryptionStrength"];
|
||||
connectionInfo.Inheritance.RDPAuthenticationLevel = (bool)dataRow["InheritRDPAuthenticationLevel"];
|
||||
connectionInfo.Inheritance.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
|
||||
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = (bool)dataRow["RDPMinutesToIdleTimeout"];
|
||||
connectionInfo.Inheritance.LoadBalanceInfo = (bool)dataRow["InheritLoadBalanceInfo"];
|
||||
connectionInfo.Inheritance.PreExtApp = (bool)dataRow["InheritPreExtApp"];
|
||||
connectionInfo.Inheritance.PostExtApp = (bool)dataRow["InheritPostExtApp"];
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
_dataTable.Columns.Add("RenderingEngine", typeof(string));
|
||||
_dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
|
||||
_dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
|
||||
_dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
|
||||
_dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("Colors", typeof(string));
|
||||
_dataTable.Columns.Add("Resolution", typeof(string));
|
||||
_dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
|
||||
@@ -128,6 +130,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
_dataTable.Columns.Add("InheritRenderingEngine", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritICAEncryptionStrength", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRDPAuthenticationLevel", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritUsername", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
|
||||
@@ -200,6 +204,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["RenderingEngine"] = connectionInfo.RenderingEngine;
|
||||
dataRow["ICAEncryptionStrength"] = connectionInfo.ICAEncryptionStrength;
|
||||
dataRow["RDPAuthenticationLevel"] = connectionInfo.RDPAuthenticationLevel;
|
||||
//dataRow["RDPMinutesToIdleTimeout"] = connectionInfo.RDPMinutesToIdleTimeout;
|
||||
//dataRow["RDPAlertIdleTimeout"] = connectionInfo.RDPAlertIdleTimeout;
|
||||
dataRow["LoadBalanceInfo"] = connectionInfo.LoadBalanceInfo;
|
||||
dataRow["Colors"] = connectionInfo.Colors;
|
||||
dataRow["Resolution"] = connectionInfo.Resolution;
|
||||
@@ -270,6 +276,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritUsername"] = connectionInfo.Inheritance.Username;
|
||||
dataRow["InheritICAEncryptionStrength"] = connectionInfo.Inheritance.ICAEncryptionStrength;
|
||||
dataRow["InheritRDPAuthenticationLevel"] = connectionInfo.Inheritance.RDPAuthenticationLevel;
|
||||
//dataRow["InheritRDPMinutesToIdleTimeout"] = connectionInfo.Inheritance.RDPMinutesToIdleTimeout;
|
||||
//dataRow["InheritRDPAlertIdleTimeout"] = connectionInfo.Inheritance.RDPAlertIdleTimeout;
|
||||
dataRow["InheritLoadBalanceInfo"] = connectionInfo.Inheritance.LoadBalanceInfo;
|
||||
dataRow["InheritPreExtApp"] = connectionInfo.Inheritance.PreExtApp;
|
||||
dataRow["InheritPostExtApp"] = connectionInfo.Inheritance.PostExtApp;
|
||||
@@ -325,6 +333,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritUsername"] = false;
|
||||
dataRow["InheritICAEncryptionStrength"] = false;
|
||||
dataRow["InheritRDPAuthenticationLevel"] = false;
|
||||
//dataRow["InheritRDPMinutesToIdleTimeout"] = false;
|
||||
//dataRow["InheritRDPAlertIdleTimeout"] = false;
|
||||
dataRow["InheritLoadBalanceInfo"] = false;
|
||||
dataRow["InheritPreExtApp"] = false;
|
||||
dataRow["InheritPostExtApp"] = false;
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("Descr", connectionInfo.Description));
|
||||
element.Add(new XAttribute("Icon", connectionInfo.Icon));
|
||||
element.Add(new XAttribute("Panel", connectionInfo.Panel));
|
||||
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
|
||||
|
||||
element.Add(_saveFilter.SaveUsername
|
||||
? new XAttribute("Username", connectionInfo.Username)
|
||||
@@ -67,6 +68,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("RenderingEngine", connectionInfo.RenderingEngine));
|
||||
element.Add(new XAttribute("ICAEncryptionStrength", connectionInfo.ICAEncryptionStrength));
|
||||
element.Add(new XAttribute("RDPAuthenticationLevel", connectionInfo.RDPAuthenticationLevel));
|
||||
element.Add(new XAttribute("RDPMinutesToIdleTimeout", connectionInfo.RDPMinutesToIdleTimeout));
|
||||
element.Add(new XAttribute("RDPAlertIdleTimeout", connectionInfo.RDPAlertIdleTimeout));
|
||||
element.Add(new XAttribute("LoadBalanceInfo", connectionInfo.LoadBalanceInfo));
|
||||
element.Add(new XAttribute("Colors", connectionInfo.Colors));
|
||||
element.Add(new XAttribute("Resolution", connectionInfo.Resolution));
|
||||
@@ -159,6 +162,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", connectionInfo.Inheritance.Username.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", connectionInfo.Inheritance.ICAEncryptionStrength.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", connectionInfo.Inheritance.RDPAuthenticationLevel.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", connectionInfo.Inheritance.RDPMinutesToIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", connectionInfo.Inheritance.RDPAlertIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", connectionInfo.Inheritance.LoadBalanceInfo.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", connectionInfo.Inheritance.PreExtApp.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", connectionInfo.Inheritance.PostExtApp.ToString()));
|
||||
@@ -214,6 +219,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", false.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", false.ToString()));
|
||||
|
||||
@@ -485,8 +485,13 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
if (_confVersion >= 2.6)
|
||||
{
|
||||
connectionInfo.ConstantID = xmlnode.Attributes["Id"]?.Value ?? connectionInfo.ConstantID;
|
||||
connectionInfo.SoundQuality = (ProtocolRDP.RDPSoundQuality)Tools.MiscTools.StringToEnum(typeof(ProtocolRDP.RDPSoundQuality), Convert.ToString(xmlnode.Attributes["SoundQuality"].Value));
|
||||
connectionInfo.Inheritance.SoundQuality = bool.Parse(xmlnode.Attributes["InheritSoundQuality"].Value);
|
||||
connectionInfo.RDPMinutesToIdleTimeout = Convert.ToInt32(xmlnode.Attributes["RDPMinutesToIdleTimeout"]?.Value ?? "0");
|
||||
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPMinutesToIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["RDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.Inheritance.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace mRemoteNG.Config.Settings
|
||||
}
|
||||
else
|
||||
{
|
||||
Startup.Instance.SetDefaultLayout();
|
||||
frmMain.Default.SetDefaultLayout();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -9,6 +9,7 @@ using mRemoteNG.Themes;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
|
||||
@@ -137,14 +138,14 @@ namespace mRemoteNG.Config.Settings
|
||||
private void SetKioskMode()
|
||||
{
|
||||
if (!mRemoteNG.Settings.Default.MainFormKiosk) return;
|
||||
MainForm.Fullscreen.Value = true;
|
||||
MainForm._fullscreen.Value = true;
|
||||
MainForm.mMenViewFullscreen.Checked = true;
|
||||
}
|
||||
|
||||
private static void SetShowSystemTrayIcon()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.ShowSystemTrayIcon)
|
||||
Runtime.NotificationAreaIcon = new Tools.Controls.NotificationAreaIcon();
|
||||
Runtime.NotificationAreaIcon = new NotificationAreaIcon();
|
||||
}
|
||||
|
||||
private static void SetPuttyPath()
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
mRemoteNG.Settings.Default.MainFormState = with1.WindowState;
|
||||
|
||||
if (with1.Fullscreen != null)
|
||||
if (with1._fullscreen != null)
|
||||
{
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1.Fullscreen.Value;
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1._fullscreen.Value;
|
||||
}
|
||||
|
||||
mRemoteNG.Settings.Default.FirstStart = false;
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace mRemoteNG.Connection
|
||||
private ProtocolICA.EncryptionStrength _icaEncryption;
|
||||
private bool _useConsoleSession;
|
||||
private ProtocolRDP.AuthenticationLevel _rdpAuthenticationLevel;
|
||||
private int _rdpMinutesToIdleTimeout;
|
||||
private bool _rdpAlertIdleTimeout;
|
||||
private string _loadBalanceInfo;
|
||||
private HTTPBase.RenderingEngine _renderingEngine;
|
||||
private bool _useCredSsp;
|
||||
@@ -225,6 +227,30 @@ namespace mRemoteNG.Connection
|
||||
set { SetField(ref _rdpAuthenticationLevel, value, "RDPAuthenticationLevel"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout")]
|
||||
public virtual int RDPMinutesToIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout); }
|
||||
set {
|
||||
if(value < 0) {
|
||||
value = 0;
|
||||
} else if(value > 240) {
|
||||
value = 240;
|
||||
}
|
||||
SetField(ref _rdpMinutesToIdleTimeout, value, "RDPMinutesToIdleTimeout");
|
||||
}
|
||||
}
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout")]
|
||||
public bool RDPAlertIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout); }
|
||||
set { SetField(ref _rdpAlertIdleTimeout, value, "RDPAlertIdleTimeout"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo")]
|
||||
|
||||
@@ -248,6 +248,8 @@ namespace mRemoteNG.Connection
|
||||
ICAEncryptionStrength = (ProtocolICA.EncryptionStrength) Enum.Parse(typeof(ProtocolICA.EncryptionStrength), Settings.Default.ConDefaultICAEncryptionStrength);
|
||||
UseConsoleSession = Settings.Default.ConDefaultUseConsoleSession;
|
||||
RDPAuthenticationLevel = (ProtocolRDP.AuthenticationLevel) Enum.Parse(typeof(ProtocolRDP.AuthenticationLevel), Settings.Default.ConDefaultRDPAuthenticationLevel);
|
||||
RDPMinutesToIdleTimeout = Settings.Default.ConDefaultRDPMinutesToIdleTimeout;
|
||||
RDPAlertIdleTimeout = Settings.Default.ConDefaultRDPAlertIdleTimeout;
|
||||
LoadBalanceInfo = Settings.Default.ConDefaultLoadBalanceInfo;
|
||||
RenderingEngine = (HTTPBase.RenderingEngine) Enum.Parse(typeof(HTTPBase.RenderingEngine), Settings.Default.ConDefaultRenderingEngine);
|
||||
UseCredSsp = Settings.Default.ConDefaultUseCredSsp;
|
||||
|
||||
@@ -83,9 +83,19 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameAuthenticationLevel"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionAuthenticationLevel"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set;}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPMinutesToIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPMinutesToIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPAlertIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))] public bool RDPAlertIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionLoadBalanceInfo"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool LoadBalanceInfo {get; set;}
|
||||
|
||||
@@ -12,14 +12,52 @@ using TabPage = Crownwood.Magic.Controls.TabPage;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public static class ConnectionInitiator
|
||||
public class ConnectionInitiator : IConnectionInitiator
|
||||
{
|
||||
public static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
public void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
{
|
||||
OpenConnection(containerInfo, force, null);
|
||||
}
|
||||
|
||||
private static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
public void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SwitchToOpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var interfaceControl = FindConnectionContainer(connectionInfo);
|
||||
if (interfaceControl == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)interfaceControl.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)interfaceControl.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)interfaceControl.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Private
|
||||
private void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
var children = containerInfo.Children;
|
||||
if (children.Count == 0) return;
|
||||
@@ -33,31 +71,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
private void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -104,7 +118,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,19 +129,6 @@ namespace mRemoteNG.Connection
|
||||
extA?.Start(connectionInfo);
|
||||
}
|
||||
|
||||
public static bool SwitchToOpenConnection(ConnectionInfo nCi)
|
||||
{
|
||||
var IC = FindConnectionContainer(nCi);
|
||||
if (IC == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)IC.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)IC.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)IC.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static InterfaceControl FindConnectionContainer(ConnectionInfo connectionInfo)
|
||||
{
|
||||
if (connectionInfo.OpenConnections.Count <= 0) return null;
|
||||
@@ -185,11 +186,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
Control connectionContainer = ((ConnectionWindow)connectionForm).AddConnectionTab(connectionInfo);
|
||||
|
||||
if (connectionInfo.Protocol == ProtocolType.IntApp)
|
||||
{
|
||||
if (Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon != null)
|
||||
((TabPage)connectionContainer).Icon = Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon;
|
||||
}
|
||||
if (connectionInfo.Protocol != ProtocolType.IntApp) return connectionContainer;
|
||||
|
||||
var extT = Runtime.GetExtAppByName(connectionInfo.ExtApp);
|
||||
|
||||
if(extT == null) return connectionContainer;
|
||||
|
||||
if (extT.Icon != null)
|
||||
((TabPage)connectionContainer).Icon = extT.Icon;
|
||||
|
||||
return connectionContainer;
|
||||
}
|
||||
|
||||
@@ -210,10 +215,9 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
newProtocol.InterfaceControl = new InterfaceControl(connectionContainer, newProtocol, connectionInfo);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Event handlers
|
||||
private static void Prot_Event_Disconnected(object sender, string disconnectedMessage)
|
||||
{
|
||||
try
|
||||
@@ -230,7 +234,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.strProtocolEventDisconnectFailed, ex.Message), true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strProtocolEventDisconnectFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +244,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
var Prot = (ProtocolBase)sender;
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strConnenctionCloseEvent, true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, Prot.InterfaceControl.Info.Hostname, Prot.InterfaceControl.Info.Protocol.ToString(), Environment.UserName));
|
||||
string connDetail;
|
||||
if (Prot.InterfaceControl.Info.Hostname == "" && Prot.InterfaceControl.Info.Protocol == ProtocolType.IntApp)
|
||||
connDetail = Prot.InterfaceControl.Info.ExtApp;
|
||||
else if (Prot.InterfaceControl.Info.Hostname != "")
|
||||
connDetail = Prot.InterfaceControl.Info.Hostname;
|
||||
else
|
||||
connDetail = "UNKNOWN";
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, connDetail, Prot.InterfaceControl.Info.Protocol, Environment.UserName));
|
||||
Prot.InterfaceControl.Info.OpenConnections.Remove(Prot);
|
||||
|
||||
if (Prot.InterfaceControl.Info.PostExtApp == "") return;
|
||||
@@ -249,7 +261,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnenctionCloseEventFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnenctionCloseEventFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,8 +285,9 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionEventConnectionFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionEventConnectionFailed, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using mRemoteNG.App;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
@@ -39,15 +40,17 @@ namespace mRemoteNG.Connection
|
||||
var inheritanceProperties = GetProperties(_excludedProperties);
|
||||
foreach (var property in inheritanceProperties)
|
||||
{
|
||||
var propertyFromDestination = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
|
||||
var localValue = property.GetValue(Instance, null);
|
||||
|
||||
var descriptor = TypeDescriptor.GetProperties(Instance)[property.Name];
|
||||
var converter = descriptor.Converter;
|
||||
if (converter != null && converter.CanConvertFrom(localValue.GetType()))
|
||||
propertyFromDestination.SetValue(destinationInstance, converter.ConvertFrom(localValue), null);
|
||||
else
|
||||
propertyFromDestination.SetValue(destinationInstance, localValue, null);
|
||||
try
|
||||
{
|
||||
var propertyFromDestination = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
|
||||
var localValue = property.GetValue(Instance, null);
|
||||
var convertedValue = Convert.ChangeType(localValue, propertyFromDestination.PropertyType);
|
||||
propertyFromDestination.SetValue(destinationInstance, convertedValue, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector?.AddExceptionStackTrace($"Error saving default connectioninfo property {property.Name}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
mRemoteV1/Connection/IConnectionInitiator.cs
Normal file
15
mRemoteV1/Connection/IConnectionInitiator.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using mRemoteNG.Container;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public interface IConnectionInitiator
|
||||
{
|
||||
void OpenConnection(ConnectionInfo connectionInfo);
|
||||
|
||||
void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None);
|
||||
|
||||
void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force);
|
||||
|
||||
bool SwitchToOpenConnection(ConnectionInfo connectionInfo);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ namespace mRemoteNG.Connection.Protocol.Http
|
||||
WebBrowser objWebBrowser = wBrowser as WebBrowser;
|
||||
if (objWebBrowser == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
// This can only be set once the WebBrowser control is shown, it will throw a COM exception otherwise.
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace mRemoteNG.Connection.Protocol.ICA
|
||||
{
|
||||
if (((int)Force & (int)ConnectionInfo.Force.NoCredentials) == (int)ConnectionInfo.Force.NoCredentials)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
string _user = _Info.Username;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
@@ -20,41 +21,52 @@ namespace mRemoteNG.Connection.Protocol
|
||||
#region Public Methods
|
||||
public override bool Initialize()
|
||||
{
|
||||
if (InterfaceControl.Info != null)
|
||||
{
|
||||
_externalTool = Runtime.GetExtAppByName(Convert.ToString(InterfaceControl.Info.ExtApp));
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
}
|
||||
|
||||
return base.Initialize();
|
||||
if (InterfaceControl.Info == null) return base.Initialize();
|
||||
|
||||
_externalTool = Runtime.GetExtAppByName(InterfaceControl.Info.ExtApp);
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
|
||||
return base.Initialize();
|
||||
}
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_externalTool.TryIntegrate == false)
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Attempting to start: {_externalTool.DisplayName}", true);
|
||||
|
||||
if (_externalTool.TryIntegrate == false)
|
||||
{
|
||||
_externalTool.Start(InterfaceControl.Info);
|
||||
Close();
|
||||
return false;
|
||||
/* Don't call close here... There's nothing for the override to do in this case since
|
||||
* _process is not created in this scenario. When returning false, ProtocolBase.Close()
|
||||
* will be called - which is just going to call IntegratedProgram.Close() again anyway...
|
||||
* Close();
|
||||
*/
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Assuming no other errors/exceptions occurred immediately before this message regarding {_externalTool.DisplayName}, the next \"closed by user\" message can be ignored", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalToolArgumentParser argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo);
|
||||
_process = new Process();
|
||||
|
||||
_process.StartInfo.UseShellExecute = true;
|
||||
_process.StartInfo.FileName = argParser.ParseArguments(_externalTool.FileName);
|
||||
_process.StartInfo.Arguments = argParser.ParseArguments(_externalTool.Arguments);
|
||||
|
||||
_process.EnableRaisingEvents = true;
|
||||
_process.Exited += ProcessExited;
|
||||
var argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo);
|
||||
_process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = argParser.ParseArguments(_externalTool.FileName),
|
||||
Arguments = argParser.ParseArguments(_externalTool.Arguments)
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
|
||||
_process.Exited += ProcessExited;
|
||||
|
||||
_process.Start();
|
||||
_process.WaitForInputIdle(Convert.ToInt32(Settings.Default.MaxPuttyWaitTime * 1000));
|
||||
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
|
||||
|
||||
int startTicks = Environment.TickCount;
|
||||
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + (Settings.Default.MaxPuttyWaitTime * 1000))
|
||||
var startTicks = Environment.TickCount;
|
||||
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + Settings.Default.MaxPuttyWaitTime * 1000)
|
||||
{
|
||||
_process.Refresh();
|
||||
if (_process.MainWindowTitle != "Default IME")
|
||||
@@ -68,10 +80,10 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
|
||||
NativeMethods.SetParent(_handle, InterfaceControl.Handle);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppHandle, _handle.ToString()), true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppTitle, _process.MainWindowTitle), true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppParentHandle, InterfaceControl.Parent.Handle.ToString()), true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppHandle, _handle), true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppTitle, _process.MainWindowTitle), true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppParentHandle, InterfaceControl.Parent.Handle), true);
|
||||
|
||||
Resize(this, new EventArgs());
|
||||
base.Connect();
|
||||
@@ -88,15 +100,12 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ConnectionWindow.InTabDrag)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if (ConnectionWindow.InTabDrag) return;
|
||||
NativeMethods.SetForegroundWindow(_handle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppFocusFailed, ex: ex, logOnly: true);
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppFocusFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,45 +113,49 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InterfaceControl.Size == Size.Empty)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
NativeMethods.MoveWindow(_handle, Convert.ToInt32(-SystemInformation.FrameBorderSize.Width), Convert.ToInt32(-(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height)), InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width * 2), InterfaceControl.Height + SystemInformation.CaptionHeight + (SystemInformation.FrameBorderSize.Height * 2), true);
|
||||
if (InterfaceControl.Size == Size.Empty) return;
|
||||
NativeMethods.MoveWindow(_handle, -SystemInformation.FrameBorderSize.Width, -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height), InterfaceControl.Width + SystemInformation.FrameBorderSize.Width * 2, InterfaceControl.Height + SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height * 2, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppResizeFailed, ex: ex, logOnly: true);
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppResizeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppKillFailed, ex: ex, logOnly: true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppDisposeFailed, ex: ex, logOnly: true);
|
||||
}
|
||||
|
||||
base.Close();
|
||||
/* only attempt this if we have a valid process object
|
||||
* Non-integated tools will still call base.Close() and don't have a valid process object.
|
||||
* See Connect() above... This just muddies up the log.
|
||||
*/
|
||||
if (_process != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppKillFailed, ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppDisposeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
base.Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace mRemoteNG.Connection.Protocol
|
||||
|
||||
#region Public Properties
|
||||
#region Control
|
||||
public string Name { get; set; }
|
||||
private string Name { get; }
|
||||
|
||||
protected UI.Window.ConnectionWindow ConnectionWindow
|
||||
{
|
||||
get { return _connectionWindow; }
|
||||
set
|
||||
private set
|
||||
{
|
||||
_connectionWindow = value;
|
||||
_connectionWindow.ResizeBegin += ResizeBegin;
|
||||
@@ -61,7 +61,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public ProtocolBase()
|
||||
protected ProtocolBase()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t focus Control (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't focus Control (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t SetProps (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't SetProps (Connection.Protocol.Base)", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
Thread t = new Thread(CloseBG);
|
||||
var t = new Thread(CloseBG);
|
||||
t.SetApartmentState(ApartmentState.STA);
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
@@ -153,31 +153,31 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "Could not dispose control, probably form is already closed (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't dispose control, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (_interfaceControl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_interfaceControl.Parent == null) return;
|
||||
if (_interfaceControl.Parent.Tag != null)
|
||||
{
|
||||
SetTagToNothing();
|
||||
}
|
||||
|
||||
if (_interfaceControl == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_interfaceControl.Parent == null) return;
|
||||
|
||||
if (_interfaceControl.Parent.Tag != null)
|
||||
{
|
||||
SetTagToNothing();
|
||||
}
|
||||
|
||||
DisposeInterface();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "Could not set InterfaceControl.Parent.Tag or Dispose Interface, probably form is already closed (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
}
|
||||
}
|
||||
DisposeInterface();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't set InterfaceControl.Parent.Tag or Dispose Interface, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t Close InterfaceControl BG (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't Close InterfaceControl BG (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (_interfaceControl.InvokeRequired)
|
||||
{
|
||||
DisposeInterfaceCB s = new DisposeInterfaceCB(DisposeInterface);
|
||||
var s = new DisposeInterfaceCB(DisposeInterface);
|
||||
_interfaceControl.Invoke(s);
|
||||
}
|
||||
else
|
||||
@@ -200,7 +200,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (_interfaceControl.Parent.InvokeRequired)
|
||||
{
|
||||
SetTagToNothingCB s = new SetTagToNothingCB(SetTagToNothing);
|
||||
var s = new SetTagToNothingCB(SetTagToNothing);
|
||||
_interfaceControl.Parent.Invoke(s);
|
||||
}
|
||||
else
|
||||
@@ -214,7 +214,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (Control.InvokeRequired)
|
||||
{
|
||||
DisposeControlCB s = new DisposeControlCB(DisposeControl);
|
||||
var s = new DisposeControlCB(DisposeControl);
|
||||
Control.Invoke(s);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private bool _loginComplete;
|
||||
private bool _redirectKeys;
|
||||
private bool _alertOnIdleDisconnect;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@@ -129,9 +130,12 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
SetCredentials();
|
||||
SetResolution();
|
||||
_rdpClient.FullScreenTitle = _connectionInfo.Name;
|
||||
|
||||
//not user changeable
|
||||
_rdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
|
||||
|
||||
_alertOnIdleDisconnect = _connectionInfo.RDPAlertIdleTimeout;
|
||||
_rdpClient.AdvancedSettings2.MinutesToIdleTimeout = _connectionInfo.RDPMinutesToIdleTimeout;
|
||||
|
||||
//not user changeable
|
||||
_rdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
|
||||
_rdpClient.AdvancedSettings3.EnableAutoReconnect = true;
|
||||
_rdpClient.AdvancedSettings3.MaxReconnectAttempts = Settings.Default.RdpReconnectionCount;
|
||||
_rdpClient.AdvancedSettings2.keepAliveInterval = 60000; //in milliseconds (10,000 = 10 seconds)
|
||||
@@ -176,8 +180,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
{
|
||||
_loginComplete = false;
|
||||
SetEventHandlers();
|
||||
|
||||
try
|
||||
|
||||
try
|
||||
{
|
||||
_rdpClient.Connect();
|
||||
base.Connect();
|
||||
@@ -616,7 +620,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
_rdpClient.OnFatalError += RDPEvent_OnFatalError;
|
||||
_rdpClient.OnDisconnected += RDPEvent_OnDisconnected;
|
||||
_rdpClient.OnLeaveFullScreenMode += RDPEvent_OnLeaveFullscreenMode;
|
||||
}
|
||||
_rdpClient.OnIdleTimeoutNotification += RDPEvent_OnIdleTimeoutNotification;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strRdpSetEventHandlersFailed, ex);
|
||||
@@ -625,7 +630,20 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
#endregion
|
||||
|
||||
#region Private Events & Handlers
|
||||
private void RDPEvent_OnFatalError(int errorCode)
|
||||
private void RDPEvent_OnIdleTimeoutNotification()
|
||||
{
|
||||
Close(); //Simply close the RDP Session if the idle timeout has been triggered.
|
||||
|
||||
if (_alertOnIdleDisconnect)
|
||||
{
|
||||
string message = "The " + _connectionInfo.Name + " session was disconnected due to inactivity";
|
||||
const string caption = "Session Disconnected";
|
||||
MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RDPEvent_OnFatalError(int errorCode)
|
||||
{
|
||||
Event_ErrorOccured(this, Convert.ToString(errorCode));
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace mRemoteNG.Connection
|
||||
var puttyProcess = new PuttyProcessController();
|
||||
if (!puttyProcess.Start())
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
if (puttyProcess.SelectListBoxItem(PuttySession))
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace mRemoteNG.Messages
|
||||
return lvItem;
|
||||
}
|
||||
|
||||
public void AddExceptionMessage(string message, Exception ex, MessageClass msgClass = MessageClass.ErrorMsg, bool logOnly = false)
|
||||
public void AddExceptionMessage(string message, Exception ex, MessageClass msgClass = MessageClass.ErrorMsg, bool logOnly = true)
|
||||
{
|
||||
AddMessage(msgClass, message + Environment.NewLine + Tools.MiscTools.GetExceptionMessageRecursive(ex), logOnly);
|
||||
}
|
||||
@@ -186,7 +186,7 @@ namespace mRemoteNG.Messages
|
||||
}
|
||||
}
|
||||
|
||||
delegate void AddToListCB(ListViewItem lvItem);
|
||||
private delegate void AddToListCB(ListViewItem lvItem);
|
||||
private void AddToList(ListViewItem lvItem)
|
||||
{
|
||||
if (MCForm.lvErrorCollector.InvokeRequired)
|
||||
|
||||
@@ -14,7 +14,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyDescription("Multi-protocol remote connections manager")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly:AssemblyProduct("mRemoteNG")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
|
||||
[assembly:AssemblyTrademark("")]
|
||||
|
||||
[assembly:ComVisible(false)]
|
||||
|
||||
53
mRemoteV1/Properties/Settings.Designer.cs
generated
53
mRemoteV1/Properties/Settings.Designer.cs
generated
@@ -2099,13 +2099,16 @@ namespace mRemoteNG {
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("release")]
|
||||
public string UpdateChannel {
|
||||
get {
|
||||
return ((string)(this["UpdateChannel"]));
|
||||
}
|
||||
set {
|
||||
this["UpdateChannel"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
@@ -2347,5 +2350,53 @@ namespace mRemoteNG {
|
||||
this["InhDefaultSoundQuality"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int ConDefaultRDPMinutesToIdleTimeout {
|
||||
get {
|
||||
return ((int)(this["ConDefaultRDPMinutesToIdleTimeout"]));
|
||||
}
|
||||
set {
|
||||
this["ConDefaultRDPMinutesToIdleTimeout"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool InhDefaultRDPMinutesToIdleTimeout {
|
||||
get {
|
||||
return ((bool)(this["InhDefaultRDPMinutesToIdleTimeout"]));
|
||||
}
|
||||
set {
|
||||
this["InhDefaultRDPMinutesToIdleTimeout"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool ConDefaultRDPAlertIdleTimeout {
|
||||
get {
|
||||
return ((bool)(this["ConDefaultRDPAlertIdleTimeout"]));
|
||||
}
|
||||
set {
|
||||
this["ConDefaultRDPAlertIdleTimeout"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool InhDefaultRDPAlertIdleTimeout {
|
||||
get {
|
||||
return ((bool)(this["InhDefaultRDPAlertIdleTimeout"]));
|
||||
}
|
||||
set {
|
||||
this["InhDefaultRDPAlertIdleTimeout"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +521,7 @@
|
||||
<Setting Name="IdentifyQuickConnectTabs" Roaming="true" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="UpdateChannel" Type="System.String" Scope="Application">
|
||||
<Setting Name="UpdateChannel" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">release</Value>
|
||||
</Setting>
|
||||
<Setting Name="ThemeName" Type="System.String" Scope="User">
|
||||
@@ -584,5 +584,17 @@
|
||||
<Setting Name="InhDefaultSoundQuality" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="ConDefaultRDPMinutesToIdleTimeout" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="InhDefaultRDPMinutesToIdleTimeout" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="ConDefaultRDPAlertIdleTimeout" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="InhDefaultRDPAlertIdleTimeout" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -1,13 +1,60 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" >
|
||||
<head>
|
||||
<title>Quick Connect</title>
|
||||
<link href="Main.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>
|
||||
Sorry, not yet...</p>
|
||||
|
||||
</body>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" >
|
||||
<head>
|
||||
<title>Quick Connect</title>
|
||||
<link href="Main.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>
|
||||
The Quick Connect functionality of mRemoteNG allows you to quickly connect to a remote host using a variety of network protocols.
|
||||
</p>
|
||||
|
||||
<p class="heading1">
|
||||
Use Cases
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The primary use case for Quick Connect is to connect to remote hosts when you already remember the DNS hostname/IP address and the appropriate protocol for the connection.
|
||||
<br />
|
||||
<br />
|
||||
An additional use case is to connect to remote hosts saved as a connection quickly.
|
||||
</p>
|
||||
|
||||
<p class="heading1">
|
||||
Prerequisites
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Knowledge of a DNS host name or IP address</li>
|
||||
<li>Knowledge of an appropriate protocol to communicate with remote host</li>
|
||||
</ul>
|
||||
<p> OR </p>
|
||||
<ul>
|
||||
<li>A predefined mRemoteNG connection</li>
|
||||
</ul>
|
||||
|
||||
<p class="heading1">
|
||||
Using QuickConnect
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use Quick Connect, ensure the Quick Connect toolbar is enabled by selecting <b>View</b> and then <b>Quick Connect Toolbar</b>.
|
||||
<br />
|
||||
Next, input a DNS host name or IP address into the box labeled "Connect". This box will also save previous entries during your session.
|
||||
<br />
|
||||
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/01.png" />
|
||||
<br />
|
||||
<br />
|
||||
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/02.png" />
|
||||
<br />
|
||||
<br />
|
||||
Select the appropriate network protocol by clicking the arrow next to the Connect box.
|
||||
<br />
|
||||
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/03.png" />
|
||||
<br />
|
||||
<br />
|
||||
If you wish to use an existing connection, select the globe icon next to the protocol button and select the appropriate connection.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/01.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/02.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/03.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/03.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/01.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/02.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/03.png
Normal file
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/03.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
36
mRemoteV1/Resources/Language/Language.Designer.cs
generated
36
mRemoteV1/Resources/Language/Language.Designer.cs
generated
@@ -4117,6 +4117,24 @@ namespace mRemoteNG {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select whether to receive an alert after the RDP session disconnects due to inactivity.
|
||||
/// </summary>
|
||||
internal static string strPropertyDescriptionRDPAlertIdleTimeout {
|
||||
get {
|
||||
return ResourceManager.GetString("strPropertyDescriptionRDPAlertIdleTimeout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The number of minutes for the RDP session to sit idle before automatically disconnecting (for no limit use 0).
|
||||
/// </summary>
|
||||
internal static string strPropertyDescriptionRDPMinutesToIdleTimeout {
|
||||
get {
|
||||
return ResourceManager.GetString("strPropertyDescriptionRDPMinutesToIdleTimeout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select whether local disk drives should be shown on the remote host..
|
||||
/// </summary>
|
||||
@@ -4603,6 +4621,24 @@ namespace mRemoteNG {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Alert on Idle Disconnect.
|
||||
/// </summary>
|
||||
internal static string strPropertyNameRDPAlertIdleTimeout {
|
||||
get {
|
||||
return ResourceManager.GetString("strPropertyNameRDPAlertIdleTimeout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Minutes to Idle.
|
||||
/// </summary>
|
||||
internal static string strPropertyNameRDPMinutesToIdleTimeout {
|
||||
get {
|
||||
return ResourceManager.GetString("strPropertyNameRDPMinutesToIdleTimeout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Disk Drives.
|
||||
/// </summary>
|
||||
|
||||
@@ -2421,4 +2421,16 @@ mRemoteNG will now quit and begin with the installation.</value>
|
||||
<data name="strDownloadPortable" xml:space="preserve">
|
||||
<value>Download</value>
|
||||
</data>
|
||||
<data name="strPropertyDescriptionRDPMinutesToIdleTimeout" xml:space="preserve">
|
||||
<value>The number of minutes for the RDP session to sit idle before automatically disconnecting (for no limit use 0)</value>
|
||||
</data>
|
||||
<data name="strPropertyNameRDPMinutesToIdleTimeout" xml:space="preserve">
|
||||
<value>Minutes to Idle</value>
|
||||
</data>
|
||||
<data name="strPropertyDescriptionRDPAlertIdleTimeout" xml:space="preserve">
|
||||
<value>Select whether to receive an alert after the RDP session disconnects due to inactivity</value>
|
||||
</data>
|
||||
<data name="strPropertyNameRDPAlertIdleTimeout" xml:space="preserve">
|
||||
<value>Alert on Idle Disconnect</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -34,6 +34,7 @@
|
||||
<xs:attribute name="Descr" type="xs:string" use="required" />
|
||||
<xs:attribute name="Icon" type="xs:string" use="required" />
|
||||
<xs:attribute name="Panel" type="xs:string" use="required" />
|
||||
<xs:attribute name="Id" type="xs:string" use="required" />
|
||||
<xs:attribute name="Username" type="xs:string" use="required" />
|
||||
<xs:attribute name="Domain" type="xs:string" use="required" />
|
||||
<xs:attribute name="Password" type="xs:string" use="required" />
|
||||
@@ -46,6 +47,8 @@
|
||||
<xs:attribute name="RenderingEngine" type="xs:string" use="required" />
|
||||
<xs:attribute name="ICAEncryptionStrength" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDPAuthenticationLevel" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDPMinutesToIdleTimeout" type="xs:int" use="required" />
|
||||
<xs:attribute name="RDPAlertIdleTimeout" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="LoadBalanceInfo" type="xs:string" use="required" />
|
||||
<xs:attribute name="Colors" type="xs:string" use="required" />
|
||||
<xs:attribute name="Resolution" type="xs:string" use="required" />
|
||||
@@ -114,6 +117,8 @@
|
||||
<xs:attribute name="InheritUsername" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritICAEncryptionStrength" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDPAuthenticationLevel" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDPMinutesToIdleTimeout" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDPAlertIdleTimeout" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritLoadBalanceInfo" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPreExtApp" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPostExtApp" type="xs:boolean" use="optional" />
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_name == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_name = value;
|
||||
NotifyPropertyChanged("Name");
|
||||
@@ -135,7 +135,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_windowBackgroundColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_windowBackgroundColor = value;
|
||||
NotifyPropertyChanged("WindowBackgroundColor");
|
||||
@@ -152,7 +152,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_menuBackgroundColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_menuBackgroundColor = value;
|
||||
NotifyPropertyChanged("MenuBackgroundColor");
|
||||
@@ -169,7 +169,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_menuTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_menuTextColor = value;
|
||||
NotifyPropertyChanged("MenuTextColor");
|
||||
@@ -187,7 +187,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_toolbarBackgroundColor == value || value.A < 255)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_toolbarBackgroundColor = value;
|
||||
NotifyPropertyChanged("ToolbarBackgroundColor");
|
||||
@@ -204,7 +204,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_toolbarTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_toolbarTextColor = value;
|
||||
NotifyPropertyChanged("ToolbarTextColor");
|
||||
@@ -223,7 +223,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_connectionsPanelBackgroundColor == value || value.A < 255)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_connectionsPanelBackgroundColor = value;
|
||||
NotifyPropertyChanged("ConnectionsPanelBackgroundColor");
|
||||
@@ -240,7 +240,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_connectionsPanelTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_connectionsPanelTextColor = value;
|
||||
NotifyPropertyChanged("ConnectionsPanelTextColor");
|
||||
@@ -260,7 +260,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_connectionsPanelTreeLineColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_connectionsPanelTreeLineColor = value;
|
||||
NotifyPropertyChanged("ConnectionsPanelTreeLineColor");
|
||||
@@ -280,7 +280,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_searchBoxBackgroundColor == value || value.A < 255)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_searchBoxBackgroundColor = value;
|
||||
NotifyPropertyChanged("SearchBoxBackgroundColor");
|
||||
@@ -300,7 +300,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_searchBoxTextPromptColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_searchBoxTextPromptColor = value;
|
||||
NotifyPropertyChanged("SearchBoxTextPromptColor");
|
||||
@@ -320,7 +320,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_searchBoxTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_searchBoxTextColor = value;
|
||||
NotifyPropertyChanged("SearchBoxTextColor");
|
||||
@@ -342,7 +342,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelBackgroundColor == value || value.A < 255)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelBackgroundColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelBackgroundColor");
|
||||
@@ -362,7 +362,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelTextColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelTextColor");
|
||||
@@ -382,7 +382,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelCategoryTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelCategoryTextColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelCategoryTextColor");
|
||||
@@ -402,7 +402,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelHelpBackgroundColor == value || value.A < 255)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelHelpBackgroundColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelHelpBackgroundColor");
|
||||
@@ -422,7 +422,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelHelpTextColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelHelpTextColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelHelpTextColor");
|
||||
@@ -442,7 +442,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (_configPanelGridLineColor == value)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_configPanelGridLineColor = value;
|
||||
NotifyPropertyChanged("ConfigPanelGridLineColor");
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace mRemoteNG.Themes
|
||||
{
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
ThemeChangedEvent?.Invoke();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
public class ExternalTool
|
||||
{
|
||||
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
|
||||
#region Public Properties
|
||||
public string DisplayName { get; set; }
|
||||
public string FileName { get; set; }
|
||||
@@ -57,7 +58,7 @@ namespace mRemoteNG.Tools
|
||||
|
||||
private void StartExternalProcess()
|
||||
{
|
||||
Process process = new Process();
|
||||
var process = new Process();
|
||||
SetProcessProperties(process, ConnectionInfo);
|
||||
process.Start();
|
||||
|
||||
@@ -69,7 +70,7 @@ namespace mRemoteNG.Tools
|
||||
|
||||
private void SetProcessProperties(Process process, ConnectionInfo startConnectionInfo)
|
||||
{
|
||||
ExternalToolArgumentParser argParser = new ExternalToolArgumentParser(startConnectionInfo);
|
||||
var argParser = new ExternalToolArgumentParser(startConnectionInfo);
|
||||
process.StartInfo.UseShellExecute = true;
|
||||
process.StartInfo.FileName = argParser.ParseArguments(FileName);
|
||||
process.StartInfo.Arguments = argParser.ParseArguments(Arguments);
|
||||
@@ -79,18 +80,18 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
try
|
||||
{
|
||||
ConnectionInfo newConnectionInfo = BuildConnectionInfoForIntegratedApp();
|
||||
ConnectionInitiator.OpenConnection(newConnectionInfo);
|
||||
var newConnectionInfo = BuildConnectionInfoForIntegratedApp();
|
||||
_connectionInitiator.OpenConnection(newConnectionInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: "ExternalApp.StartIntegrated() failed.", ex: ex, logOnly: true);
|
||||
Runtime.MessageCollector.AddExceptionMessage("ExternalApp.StartIntegrated() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private ConnectionInfo BuildConnectionInfoForIntegratedApp()
|
||||
{
|
||||
ConnectionInfo newConnectionInfo = GetAppropriateInstanceOfConnectionInfo();
|
||||
var newConnectionInfo = GetAppropriateInstanceOfConnectionInfo();
|
||||
SetConnectionInfoFields(newConnectionInfo);
|
||||
return newConnectionInfo;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ using static System.String;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public class MiscTools
|
||||
public static class MiscTools
|
||||
{
|
||||
public static Icon GetIconFromFile(string FileName)
|
||||
{
|
||||
@@ -112,7 +112,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, "Taking Screenshot failed" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Taking Screenshot failed", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -120,7 +120,7 @@ namespace mRemoteNG.Tools
|
||||
|
||||
public class EnumTypeConverter : EnumConverter
|
||||
{
|
||||
private Type _enumType;
|
||||
private readonly Type _enumType;
|
||||
|
||||
public EnumTypeConverter(Type type) : base(type)
|
||||
{
|
||||
@@ -135,8 +135,8 @@ namespace mRemoteNG.Tools
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
|
||||
{
|
||||
if (value == null) return null;
|
||||
var fi = _enumType.GetField(Enum.GetName(_enumType, value: value));
|
||||
var dna = (DescriptionAttribute) (Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute)));
|
||||
var fi = _enumType.GetField(Enum.GetName(_enumType, value));
|
||||
var dna = (DescriptionAttribute) Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
|
||||
|
||||
return dna != null ? dna.Description : value.ToString();
|
||||
}
|
||||
@@ -150,9 +150,9 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
foreach (var fi in _enumType.GetFields())
|
||||
{
|
||||
var dna = (DescriptionAttribute) (Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute)));
|
||||
var dna = (DescriptionAttribute) Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
|
||||
|
||||
if ((dna != null) && ((string) value == dna.Description))
|
||||
if (dna != null && (string) value == dna.Description)
|
||||
{
|
||||
return Enum.Parse(_enumType, fi.Name);
|
||||
}
|
||||
@@ -167,12 +167,7 @@ namespace mRemoteNG.Tools
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
@@ -193,7 +188,7 @@ namespace mRemoteNG.Tools
|
||||
return false;
|
||||
}
|
||||
|
||||
throw (new Exception("Values must be \"Yes\" or \"No\""));
|
||||
throw new Exception("Values must be \"Yes\" or \"No\"");
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
@@ -220,63 +215,5 @@ namespace mRemoteNG.Tools
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
|
||||
public class Fullscreen
|
||||
{
|
||||
public Fullscreen(Form handledForm)
|
||||
{
|
||||
_handledForm = handledForm;
|
||||
}
|
||||
|
||||
private readonly Form _handledForm;
|
||||
private FormWindowState _savedWindowState;
|
||||
private FormBorderStyle _savedBorderStyle;
|
||||
private Rectangle _savedBounds;
|
||||
|
||||
private bool _value;
|
||||
public bool Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_value == value)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if (!_value)
|
||||
{
|
||||
EnterFullscreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitFullscreen();
|
||||
}
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnterFullscreen()
|
||||
{
|
||||
_savedBorderStyle = _handledForm.FormBorderStyle;
|
||||
_savedWindowState = _handledForm.WindowState;
|
||||
_savedBounds = _handledForm.Bounds;
|
||||
|
||||
_handledForm.FormBorderStyle = FormBorderStyle.None;
|
||||
if (_handledForm.WindowState == FormWindowState.Maximized)
|
||||
{
|
||||
_handledForm.WindowState = FormWindowState.Normal;
|
||||
}
|
||||
_handledForm.WindowState = FormWindowState.Maximized;
|
||||
}
|
||||
private void ExitFullscreen()
|
||||
{
|
||||
_handledForm.FormBorderStyle = _savedBorderStyle;
|
||||
_handledForm.WindowState = _savedWindowState;
|
||||
_handledForm.Bounds = _savedBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
128
mRemoteV1/Tools/NotificationAreaIcon.cs
Normal file
128
mRemoteV1/Tools/NotificationAreaIcon.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public class NotificationAreaIcon
|
||||
{
|
||||
private readonly NotifyIcon _nI;
|
||||
private readonly ContextMenuStrip _cMen;
|
||||
private readonly ToolStripMenuItem _cMenCons;
|
||||
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
|
||||
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
public NotificationAreaIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_cMenCons = new ToolStripMenuItem
|
||||
{
|
||||
Text = Language.strConnections,
|
||||
Image = Resources.Root
|
||||
};
|
||||
|
||||
var cMenSep1 = new ToolStripSeparator();
|
||||
|
||||
var cMenExit = new ToolStripMenuItem {Text = Language.strMenuExit};
|
||||
cMenExit.Click += cMenExit_Click;
|
||||
|
||||
_cMen = new ContextMenuStrip
|
||||
{
|
||||
Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular,
|
||||
System.Drawing.GraphicsUnit.Point, Convert.ToByte(0)),
|
||||
RenderMode = ToolStripRenderMode.Professional
|
||||
};
|
||||
_cMen.Items.AddRange(new ToolStripItem[] {_cMenCons, cMenSep1, cMenExit});
|
||||
|
||||
_nI = new NotifyIcon
|
||||
{
|
||||
Text = @"mRemoteNG",
|
||||
BalloonTipText = @"mRemoteNG",
|
||||
Icon = Resources.mRemote_Icon,
|
||||
ContextMenuStrip = _cMen,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
_nI.MouseClick += nI_MouseClick;
|
||||
_nI.MouseDoubleClick += nI_MouseDoubleClick;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Creating new SysTrayIcon failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
_nI.Visible = false;
|
||||
_nI.Dispose();
|
||||
_cMen.Dispose();
|
||||
Disposed = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Disposing SysTrayIcon failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void nI_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button != MouseButtons.Right) return;
|
||||
_cMenCons.DropDownItems.Clear();
|
||||
var menuItemsConverter = new ConnectionsTreeToMenuItemsConverter
|
||||
{
|
||||
MouseUpEventHandler = ConMenItem_MouseUp
|
||||
};
|
||||
|
||||
// ReSharper disable once CoVariantArrayConversion
|
||||
ToolStripItem[] rootMenuItems = menuItemsConverter.CreateToolStripDropDownItems(Runtime.ConnectionTreeModel).ToArray();
|
||||
_cMenCons.DropDownItems.AddRange(rootMenuItems);
|
||||
}
|
||||
|
||||
private static void nI_MouseDoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (frmMain.Default.Visible)
|
||||
HideForm();
|
||||
else
|
||||
ShowForm();
|
||||
}
|
||||
|
||||
private static void ShowForm()
|
||||
{
|
||||
frmMain.Default.Show();
|
||||
frmMain.Default.WindowState = frmMain.Default.PreviousWindowState;
|
||||
|
||||
if (Settings.Default.ShowSystemTrayIcon) return;
|
||||
Runtime.NotificationAreaIcon.Dispose();
|
||||
Runtime.NotificationAreaIcon = null;
|
||||
}
|
||||
|
||||
private static void HideForm()
|
||||
{
|
||||
frmMain.Default.Hide();
|
||||
frmMain.Default.PreviousWindowState = frmMain.Default.WindowState;
|
||||
}
|
||||
|
||||
private void ConMenItem_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button != MouseButtons.Left) return;
|
||||
if (!(((ToolStripMenuItem) sender).Tag is ConnectionInfo)) return;
|
||||
if (frmMain.Default.Visible == false)
|
||||
ShowForm();
|
||||
_connectionInitiator.OpenConnection((ConnectionInfo) ((ToolStripMenuItem) sender).Tag);
|
||||
}
|
||||
|
||||
private static void cMenExit_Click(object sender, EventArgs e)
|
||||
{
|
||||
Shutdown.Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace mRemoteNG.Tools
|
||||
public void WaitForExit()
|
||||
{
|
||||
if (Process == null || Process.HasExited)
|
||||
return ;
|
||||
return;
|
||||
Process.WaitForExit();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public class Controls
|
||||
{
|
||||
public class NotificationAreaIcon
|
||||
{
|
||||
private NotifyIcon _nI;
|
||||
private ContextMenuStrip _cMen;
|
||||
private ToolStripMenuItem _cMenCons;
|
||||
|
||||
public bool Disposed { get; set; }
|
||||
|
||||
public NotificationAreaIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_cMenCons = new ToolStripMenuItem
|
||||
{
|
||||
Text = Language.strConnections,
|
||||
Image = Resources.Root
|
||||
};
|
||||
|
||||
var cMenSep1 = new ToolStripSeparator();
|
||||
|
||||
var cMenExit = new ToolStripMenuItem {Text = Language.strMenuExit};
|
||||
cMenExit.Click += cMenExit_Click;
|
||||
|
||||
_cMen = new ContextMenuStrip
|
||||
{
|
||||
Font =
|
||||
new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular,
|
||||
System.Drawing.GraphicsUnit.Point, Convert.ToByte(0)),
|
||||
RenderMode = ToolStripRenderMode.Professional
|
||||
};
|
||||
_cMen.Items.AddRange(new ToolStripItem[] {_cMenCons, cMenSep1, cMenExit});
|
||||
|
||||
_nI = new NotifyIcon
|
||||
{
|
||||
Text = "mRemote",
|
||||
BalloonTipText = "mRemote",
|
||||
Icon = Resources.mRemote_Icon,
|
||||
ContextMenuStrip = _cMen,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
_nI.MouseClick += nI_MouseClick;
|
||||
_nI.MouseDoubleClick += nI_MouseDoubleClick;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Creating new SysTrayIcon failed" + Environment.NewLine + ex.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
_nI.Visible = false;
|
||||
_nI.Dispose();
|
||||
_cMen.Dispose();
|
||||
Disposed = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Disposing SysTrayIcon failed" + Environment.NewLine + ex.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void nI_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button != MouseButtons.Right) return;
|
||||
_cMenCons.DropDownItems.Clear();
|
||||
var menuItemsConverter = new ConnectionsTreeToMenuItemsConverter
|
||||
{
|
||||
MouseUpEventHandler = ConMenItem_MouseUp
|
||||
};
|
||||
|
||||
ToolStripItem[] rootMenuItems = menuItemsConverter.CreateToolStripDropDownItems(Runtime.ConnectionTreeModel).ToArray();
|
||||
_cMenCons.DropDownItems.AddRange(rootMenuItems);
|
||||
}
|
||||
|
||||
private void nI_MouseDoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (frmMain.Default.Visible)
|
||||
{
|
||||
HideForm();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowForm();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowForm()
|
||||
{
|
||||
frmMain.Default.Show();
|
||||
frmMain.Default.WindowState = frmMain.Default.PreviousWindowState;
|
||||
|
||||
if (Settings.Default.ShowSystemTrayIcon) return;
|
||||
Runtime.NotificationAreaIcon.Dispose();
|
||||
Runtime.NotificationAreaIcon = null;
|
||||
}
|
||||
|
||||
private void HideForm()
|
||||
{
|
||||
frmMain.Default.Hide();
|
||||
frmMain.Default.PreviousWindowState = frmMain.Default.WindowState;
|
||||
}
|
||||
|
||||
private void ConMenItem_MouseUp(Object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button != MouseButtons.Left) return;
|
||||
if (!(((Control) sender).Tag is ConnectionInfo)) return;
|
||||
if (frmMain.Default.Visible == false)
|
||||
{
|
||||
ShowForm();
|
||||
}
|
||||
ConnectionInitiator.OpenConnection((ConnectionInfo)((Control)sender).Tag);
|
||||
}
|
||||
|
||||
private void cMenExit_Click(Object sender, EventArgs e)
|
||||
{
|
||||
Shutdown.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
public static SaveFileDialog ConnectionsSaveAsDialog()
|
||||
{
|
||||
var saveFileDialog = new SaveFileDialog();
|
||||
saveFileDialog.CheckPathExists = true;
|
||||
saveFileDialog.InitialDirectory = App.Info.ConnectionsFileInfo.DefaultConnectionsPath;
|
||||
saveFileDialog.FileName = App.Info.ConnectionsFileInfo.DefaultConnectionsFile;
|
||||
saveFileDialog.OverwritePrompt = true;
|
||||
|
||||
saveFileDialog.Filter = Language.strFiltermRemoteXML + "|*.xml|" + Language.strFilterAll + "|*.*";
|
||||
|
||||
return saveFileDialog;
|
||||
}
|
||||
|
||||
public static OpenFileDialog ConnectionsLoadDialog()
|
||||
{
|
||||
var lDlg = new OpenFileDialog
|
||||
{
|
||||
CheckFileExists = true,
|
||||
InitialDirectory = App.Info.ConnectionsFileInfo.DefaultConnectionsPath,
|
||||
Filter = Language.strFiltermRemoteXML + "|*.xml|" + Language.strFilterAll + "|*.*"
|
||||
};
|
||||
|
||||
return lDlg;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
mRemoteV1/Tree/AlwaysConfirmYes.cs
Normal file
11
mRemoteV1/Tree/AlwaysConfirmYes.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class AlwaysConfirmYes : IConfirm
|
||||
{
|
||||
public bool Confirm()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
mRemoteV1/Tree/ClickHandlers/ExpandNodeClickHandler.cs
Normal file
28
mRemoteV1/Tree/ClickHandlers/ExpandNodeClickHandler.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class ExpandNodeClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
private readonly IConnectionTree _connectionTree;
|
||||
|
||||
public ExpandNodeClickHandler(IConnectionTree connectionTree)
|
||||
{
|
||||
if (connectionTree == null)
|
||||
throw new ArgumentNullException(nameof(connectionTree));
|
||||
|
||||
_connectionTree = connectionTree;
|
||||
}
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
var clickedNodeAsContainer = clickedNode as ContainerInfo;
|
||||
if (clickedNodeAsContainer == null) return;
|
||||
_connectionTree.ToggleExpansion(clickedNodeAsContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
mRemoteV1/Tree/ClickHandlers/ITreeNodeClickHandler.cs
Normal file
10
mRemoteV1/Tree/ClickHandlers/ITreeNodeClickHandler.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public interface ITreeNodeClickHandler
|
||||
{
|
||||
void Execute(ConnectionInfo clickedNode);
|
||||
}
|
||||
}
|
||||
26
mRemoteV1/Tree/ClickHandlers/OpenConnectionClickHandler.cs
Normal file
26
mRemoteV1/Tree/ClickHandlers/OpenConnectionClickHandler.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class OpenConnectionClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
private readonly IConnectionInitiator _connectionInitiator;
|
||||
|
||||
public OpenConnectionClickHandler(IConnectionInitiator connectionInitiator)
|
||||
{
|
||||
if (connectionInitiator == null)
|
||||
throw new ArgumentNullException(nameof(connectionInitiator));
|
||||
_connectionInitiator = connectionInitiator;
|
||||
}
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null)
|
||||
throw new ArgumentNullException(nameof(clickedNode));
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
_connectionInitiator.OpenConnection(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class SwitchToConnectionClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
private readonly IConnectionInitiator _connectionInitiator;
|
||||
|
||||
public SwitchToConnectionClickHandler(IConnectionInitiator connectionInitiator)
|
||||
{
|
||||
if (connectionInitiator == null)
|
||||
throw new ArgumentNullException(nameof(connectionInitiator));
|
||||
_connectionInitiator = connectionInitiator;
|
||||
}
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null)
|
||||
throw new ArgumentNullException(nameof(clickedNode));
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
_connectionInitiator.SwitchToOpenConnection(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class TreeNodeCompositeClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
public IEnumerable<ITreeNodeClickHandler> ClickHandlers { get; set; } = new ITreeNodeClickHandler[0];
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null)
|
||||
throw new ArgumentNullException(nameof(clickedNode));
|
||||
foreach (var handler in ClickHandlers)
|
||||
{
|
||||
handler.Execute(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
mRemoteV1/Tree/IConfirm.cs
Normal file
7
mRemoteV1/Tree/IConfirm.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public interface IConfirm
|
||||
{
|
||||
bool Confirm();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
using BrightIdeasSoftware;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public static class ObjectListViewExtensions
|
||||
{
|
||||
public static void Invoke(this Control control, MethodInvoker action)
|
||||
{
|
||||
control.Invoke(action);
|
||||
}
|
||||
|
||||
public static void InvokeExpand(this TreeListView control, object model)
|
||||
{
|
||||
control.Invoke(() => control.Expand(model));
|
||||
}
|
||||
|
||||
public static void InvokeRebuildAll(this TreeListView control, bool preserveState)
|
||||
{
|
||||
control.Invoke(() => control.RebuildAll(preserveState));
|
||||
}
|
||||
}
|
||||
}
|
||||
31
mRemoteV1/Tree/PreviousSessionOpener.cs
Normal file
31
mRemoteV1/Tree/PreviousSessionOpener.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class PreviousSessionOpener : IConnectionTreeDelegate
|
||||
{
|
||||
private readonly IConnectionInitiator _connectionInitiator;
|
||||
|
||||
public PreviousSessionOpener(IConnectionInitiator connectionInitiator)
|
||||
{
|
||||
if (connectionInitiator == null)
|
||||
throw new ArgumentNullException(nameof(connectionInitiator));
|
||||
_connectionInitiator = connectionInitiator;
|
||||
}
|
||||
|
||||
public void Execute(IConnectionTree connectionTree)
|
||||
{
|
||||
var connectionInfoList = connectionTree.GetRootConnectionNode().GetRecursiveChildList().Where(node => !(node is ContainerInfo));
|
||||
var previouslyOpenedConnections = connectionInfoList.Where(item => item.PleaseConnect);
|
||||
foreach (var connectionInfo in previouslyOpenedConnections)
|
||||
{
|
||||
_connectionInitiator.OpenConnection(connectionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
mRemoteV1/Tree/PreviouslyOpenedFolderExpander.cs
Normal file
19
mRemoteV1/Tree/PreviouslyOpenedFolderExpander.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Linq;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class PreviouslyOpenedFolderExpander : IConnectionTreeDelegate
|
||||
{
|
||||
public void Execute(IConnectionTree connectionTree)
|
||||
{
|
||||
var rootNode = connectionTree.GetRootConnectionNode();
|
||||
var containerList = connectionTree.ConnectionTreeModel.GetRecursiveChildList(rootNode).OfType<ContainerInfo>();
|
||||
var previouslyExpandedNodes = containerList.Where(container => container.IsExpanded);
|
||||
connectionTree.ExpandedObjects = previouslyExpandedNodes;
|
||||
connectionTree.InvokeRebuildAll(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
mRemoteV1/Tree/RootNodeExpander.cs
Normal file
14
mRemoteV1/Tree/RootNodeExpander.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class RootNodeExpander : IConnectionTreeDelegate
|
||||
{
|
||||
public void Execute(IConnectionTree connectionTree)
|
||||
{
|
||||
var rootConnectionNode = connectionTree.GetRootConnectionNode();
|
||||
connectionTree.InvokeExpand(rootConnectionNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
mRemoteV1/Tree/SelectedConnectionDeletionConfirmer.cs
Normal file
56
mRemoteV1/Tree/SelectedConnectionDeletionConfirmer.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class SelectedConnectionDeletionConfirmer : IConfirm
|
||||
{
|
||||
private readonly IConnectionTree _connectionTree;
|
||||
private readonly Func<string, string, MessageBoxButtons, MessageBoxIcon, DialogResult> _confirmationFunc;
|
||||
|
||||
public SelectedConnectionDeletionConfirmer(IConnectionTree connectionTree, Func<string, string, MessageBoxButtons, MessageBoxIcon, DialogResult> confirmationFunc)
|
||||
{
|
||||
_connectionTree = connectionTree;
|
||||
_confirmationFunc = confirmationFunc;
|
||||
}
|
||||
|
||||
public bool Confirm()
|
||||
{
|
||||
var deletionTarget = _connectionTree.SelectedNode;
|
||||
var deletionTargetAsContainer = deletionTarget as ContainerInfo;
|
||||
if (deletionTargetAsContainer != null)
|
||||
return deletionTargetAsContainer.HasChildren()
|
||||
? UserConfirmsNonEmptyFolderDeletion(deletionTargetAsContainer)
|
||||
: UserConfirmsEmptyFolderDeletion(deletionTargetAsContainer);
|
||||
return UserConfirmsConnectionDeletion(deletionTarget);
|
||||
}
|
||||
|
||||
private bool UserConfirmsEmptyFolderDeletion(AbstractConnectionInfoData deletionTarget)
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolder, deletionTarget.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsNonEmptyFolderDeletion(AbstractConnectionInfoData deletionTarget)
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeFolderNotEmpty, deletionTarget.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool UserConfirmsConnectionDeletion(AbstractConnectionInfoData deletionTarget)
|
||||
{
|
||||
var messagePrompt = string.Format(Language.strConfirmDeleteNodeConnection, deletionTarget.Name);
|
||||
return PromptUser(messagePrompt);
|
||||
}
|
||||
|
||||
private bool PromptUser(string promptMessage)
|
||||
{
|
||||
var msgBoxResponse = _confirmationFunc.Invoke(promptMessage, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
return msgBoxResponse == DialogResult.Yes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
@@ -6,13 +7,14 @@ using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
internal sealed class ConnectionContextMenu : ContextMenuStrip
|
||||
public sealed class ConnectionContextMenu : ContextMenuStrip
|
||||
{
|
||||
private ToolStripMenuItem _cMenTreeAddConnection;
|
||||
private ToolStripMenuItem _cMenTreeAddFolder;
|
||||
@@ -44,14 +46,23 @@ namespace mRemoteNG.UI.Controls
|
||||
private ToolStripMenuItem _cMenTreeImportFile;
|
||||
private ToolStripMenuItem _cMenTreeImportActiveDirectory;
|
||||
private ToolStripMenuItem _cMenTreeImportPortScan;
|
||||
private readonly ConnectionTree _connectionTree;
|
||||
private readonly IConnectionInitiator _connectionInitiator;
|
||||
|
||||
|
||||
public ConnectionContextMenu()
|
||||
public ConnectionContextMenu(ConnectionTree connectionTree)
|
||||
{
|
||||
_connectionTree = connectionTree;
|
||||
_connectionInitiator = new ConnectionInitiator();
|
||||
InitializeComponent();
|
||||
ApplyLanguage();
|
||||
EnableShortcutKeys();
|
||||
Opening += (sender, args) => AddExternalApps();
|
||||
Opening += (sender, args) =>
|
||||
{
|
||||
AddExternalApps();
|
||||
ShowHideMenuItems();
|
||||
};
|
||||
Closing += (sender, args) => EnableMenuItemsRecursive(Items);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
@@ -384,104 +395,129 @@ namespace mRemoteNG.UI.Controls
|
||||
_cMenTreeMoveDown.Text = Language.strMoveDown;
|
||||
}
|
||||
|
||||
internal void ShowHideTreeContextMenuItems(ConnectionInfo connectionInfo)
|
||||
internal void ShowHideMenuItems()
|
||||
{
|
||||
if (connectionInfo == null)
|
||||
if (_connectionTree.SelectedNode == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Enabled = true;
|
||||
EnableMenuItemsRecursive(Items);
|
||||
if (connectionInfo is RootPuttySessionsNodeInfo)
|
||||
if (_connectionTree.SelectedNode is RootPuttySessionsNodeInfo)
|
||||
{
|
||||
_cMenTreeAddConnection.Enabled = false;
|
||||
_cMenTreeAddFolder.Enabled = false;
|
||||
_cMenTreeConnect.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeToolsSort.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeRename.Enabled = true;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
ShowHideMenuItemsForRootPuttyNode();
|
||||
}
|
||||
else if (connectionInfo is RootNodeInfo)
|
||||
else if (_connectionTree.SelectedNode is RootNodeInfo)
|
||||
{
|
||||
_cMenTreeConnect.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
ShowHideMenuItemsForRootConnectionNode();
|
||||
}
|
||||
else if (connectionInfo is ContainerInfo)
|
||||
else if (_connectionTree.SelectedNode is ContainerInfo)
|
||||
{
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
var openConnections = ((ContainerInfo)connectionInfo).Children.Sum(child => child.OpenConnections.Count);
|
||||
if (openConnections > 0)
|
||||
_cMenTreeDisconnect.Enabled = true;
|
||||
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
ShowHideMenuItemsForContainer(_connectionTree.SelectedNode);
|
||||
}
|
||||
else if (connectionInfo is PuttySessionInfo)
|
||||
else if (_connectionTree.SelectedNode is PuttySessionInfo)
|
||||
{
|
||||
_cMenTreeAddConnection.Enabled = false;
|
||||
_cMenTreeAddFolder.Enabled = false;
|
||||
|
||||
if (connectionInfo.OpenConnections.Count == 0)
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.SSH1 | connectionInfo.Protocol == ProtocolType.SSH2))
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeToolsSort.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeRename.Enabled = false;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
ShowHideMenuItemsForPuttyNode(_connectionTree.SelectedNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectionInfo.OpenConnections.Count == 0)
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.SSH1 | connectionInfo.Protocol == ProtocolType.SSH2))
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.RDP | connectionInfo.Protocol == ProtocolType.ICA))
|
||||
{
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
}
|
||||
|
||||
if (connectionInfo.Protocol == ProtocolType.IntApp)
|
||||
_cMenTreeConnectWithOptionsNoCredentials.Enabled = false;
|
||||
ShowHideMenuItemsForConnectionNode(_connectionTree.SelectedNode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("ShowHideTreeContextMenuItems (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("ShowHideMenuItems (UI.Controls.ConnectionContextMenu) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ShowHideMenuItemsForRootPuttyNode()
|
||||
{
|
||||
_cMenTreeAddConnection.Enabled = false;
|
||||
_cMenTreeAddFolder.Enabled = false;
|
||||
_cMenTreeConnect.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeToolsSort.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeRename.Enabled = true;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
}
|
||||
|
||||
internal void ShowHideMenuItemsForRootConnectionNode()
|
||||
{
|
||||
_cMenTreeConnect.Enabled = false;
|
||||
_cMenTreeConnectWithOptions.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
}
|
||||
|
||||
internal void ShowHideMenuItemsForContainer(ConnectionInfo connectionInfo)
|
||||
{
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
var openConnections = ((ContainerInfo)connectionInfo).Children.Sum(child => child.OpenConnections.Count);
|
||||
if (openConnections > 0)
|
||||
_cMenTreeDisconnect.Enabled = true;
|
||||
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
_cMenTreeToolsExternalApps.Enabled = false;
|
||||
}
|
||||
|
||||
internal void ShowHideMenuItemsForPuttyNode(ConnectionInfo connectionInfo)
|
||||
{
|
||||
_cMenTreeAddConnection.Enabled = false;
|
||||
_cMenTreeAddFolder.Enabled = false;
|
||||
|
||||
if (connectionInfo.OpenConnections.Count == 0)
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.SSH1 | connectionInfo.Protocol == ProtocolType.SSH2))
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
_cMenTreeToolsSort.Enabled = false;
|
||||
_cMenTreeDuplicate.Enabled = false;
|
||||
_cMenTreeRename.Enabled = false;
|
||||
_cMenTreeDelete.Enabled = false;
|
||||
_cMenTreeMoveUp.Enabled = false;
|
||||
_cMenTreeMoveDown.Enabled = false;
|
||||
}
|
||||
|
||||
internal void ShowHideMenuItemsForConnectionNode(ConnectionInfo connectionInfo)
|
||||
{
|
||||
if (connectionInfo.OpenConnections.Count == 0)
|
||||
_cMenTreeDisconnect.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.SSH1 | connectionInfo.Protocol == ProtocolType.SSH2))
|
||||
_cMenTreeToolsTransferFile.Enabled = false;
|
||||
|
||||
if (!(connectionInfo.Protocol == ProtocolType.RDP | connectionInfo.Protocol == ProtocolType.ICA))
|
||||
{
|
||||
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
|
||||
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
|
||||
}
|
||||
|
||||
if (connectionInfo.Protocol == ProtocolType.IntApp)
|
||||
_cMenTreeConnectWithOptionsNoCredentials.Enabled = false;
|
||||
}
|
||||
|
||||
internal void DisableShortcutKeys()
|
||||
{
|
||||
_cMenTreeConnect.ShortcutKeys = Keys.None;
|
||||
@@ -553,183 +589,218 @@ namespace mRemoteNG.UI.Controls
|
||||
_cMenTreeToolsExternalApps.DropDownItems.Clear();
|
||||
}
|
||||
|
||||
#region Events
|
||||
public event EventHandler ConnectClicked;
|
||||
|
||||
#region Click handlers
|
||||
private void OnConnectClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ConnectClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.DoNotJump);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public event EventHandler ConnectToConsoleSessionClicked;
|
||||
|
||||
private void OnConnectToConsoleSessionClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ConnectToConsoleSessionClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.UseConsoleSession | ConnectionInfo.Force.DoNotJump);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.UseConsoleSession | ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public event EventHandler DontConnectToConsoleSessionClicked;
|
||||
|
||||
private void OnDontConnectToConsoleSessionClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = DontConnectToConsoleSessionClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.DontUseConsoleSession | ConnectionInfo.Force.DoNotJump);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.DontUseConsoleSession | ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public event EventHandler ConnectInFullscreenClicked;
|
||||
|
||||
private void OnConnectInFullscreenClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ConnectInFullscreenClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.Fullscreen | ConnectionInfo.Force.DoNotJump);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.Fullscreen | ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public event EventHandler ConnectWithNoCredentialsClick;
|
||||
|
||||
private void OnConnectWithNoCredentialsClick(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ConnectWithNoCredentialsClick;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.NoCredentials);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.NoCredentials);
|
||||
}
|
||||
|
||||
public event EventHandler ChoosePanelBeforeConnectingClicked;
|
||||
|
||||
private void OnChoosePanelBeforeConnectingClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ChoosePanelBeforeConnectingClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo;
|
||||
if (selectedNodeAsContainer != null)
|
||||
_connectionInitiator.OpenConnection(selectedNodeAsContainer, ConnectionInfo.Force.OverridePanel | ConnectionInfo.Force.DoNotJump);
|
||||
else
|
||||
_connectionInitiator.OpenConnection(_connectionTree.SelectedNode, ConnectionInfo.Force.OverridePanel | ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
|
||||
public event EventHandler DisconnectClicked;
|
||||
|
||||
private void OnDisconnectClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = DisconnectClicked;
|
||||
handler?.Invoke(this, e);
|
||||
DisconnectConnection(_connectionTree.SelectedNode);
|
||||
}
|
||||
|
||||
public event EventHandler TransferFileClicked;
|
||||
public void DisconnectConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (connectionInfo == null) return;
|
||||
var nodeAsContainer = connectionInfo as ContainerInfo;
|
||||
if (nodeAsContainer != null)
|
||||
{
|
||||
foreach (var child in nodeAsContainer.Children)
|
||||
{
|
||||
for (var i = 0; i <= child.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
child.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i <= connectionInfo.OpenConnections.Count - 1; i++)
|
||||
{
|
||||
connectionInfo.OpenConnections[i].Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("DisconnectConnection (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTransferFileClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = TransferFileClicked;
|
||||
handler?.Invoke(this, e);
|
||||
SshTransferFile();
|
||||
}
|
||||
|
||||
public event EventHandler DuplicateClicked;
|
||||
public void SshTransferFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Show(WindowType.SSHTransfer);
|
||||
Windows.SshtransferForm.Hostname = _connectionTree.SelectedNode.Hostname;
|
||||
Windows.SshtransferForm.Username = _connectionTree.SelectedNode.Username;
|
||||
Windows.SshtransferForm.Password = _connectionTree.SelectedNode.Password;
|
||||
Windows.SshtransferForm.Port = Convert.ToString(_connectionTree.SelectedNode.Port);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("SSHTransferFile (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDuplicateClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = DuplicateClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.DuplicateSelectedNode();
|
||||
}
|
||||
|
||||
public event EventHandler RenameClicked;
|
||||
|
||||
private void OnRenameClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = RenameClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.RenameSelectedNode();
|
||||
}
|
||||
|
||||
public event EventHandler DeleteClicked;
|
||||
|
||||
private void OnDeleteClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = DeleteClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.DeleteSelectedNode();
|
||||
}
|
||||
|
||||
public event EventHandler ImportFileClicked;
|
||||
|
||||
private void OnImportFileClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ImportFileClicked;
|
||||
handler?.Invoke(this, e);
|
||||
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo ?? _connectionTree.SelectedNode.Parent;
|
||||
Import.ImportFromFile(selectedNodeAsContainer);
|
||||
}
|
||||
|
||||
public event EventHandler ImportActiveDirectoryClicked;
|
||||
|
||||
private void OnImportActiveDirectoryClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ImportActiveDirectoryClicked;
|
||||
handler?.Invoke(this, e);
|
||||
Windows.Show(WindowType.ActiveDirectoryImport);
|
||||
}
|
||||
|
||||
public event EventHandler ImportPortScanClicked;
|
||||
|
||||
private void OnImportPortScanClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ImportPortScanClicked;
|
||||
handler?.Invoke(this, e);
|
||||
Windows.Show(WindowType.PortScan);
|
||||
}
|
||||
|
||||
public event EventHandler ExportFileClicked;
|
||||
|
||||
private void OnExportFileClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ExportFileClicked;
|
||||
handler?.Invoke(this, e);
|
||||
Export.ExportToFile(_connectionTree.SelectedNode, Runtime.ConnectionTreeModel);
|
||||
}
|
||||
|
||||
public event EventHandler AddConnectionClicked;
|
||||
|
||||
private void OnAddConnectionClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = AddConnectionClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.AddConnection();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public event EventHandler AddFolderClicked;
|
||||
|
||||
private void OnAddFolderClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = AddFolderClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.AddFolder();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public event EventHandler SortAscendingClicked;
|
||||
|
||||
private void OnSortAscendingClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = SortAscendingClicked;
|
||||
handler?.Invoke(this, e);
|
||||
SortNodesRecursive(_connectionTree.SelectedNode, ListSortDirection.Ascending);
|
||||
}
|
||||
|
||||
public event EventHandler SortDescendingClicked;
|
||||
|
||||
private void OnSortDescendingClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = SortDescendingClicked;
|
||||
handler?.Invoke(this, e);
|
||||
SortNodesRecursive(_connectionTree.SelectedNode, ListSortDirection.Descending);
|
||||
}
|
||||
|
||||
public event EventHandler MoveUpClicked;
|
||||
|
||||
private void OnMoveUpClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = MoveUpClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.SelectedNode.Parent.PromoteChild(_connectionTree.SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public event EventHandler MoveDownClicked;
|
||||
|
||||
private void OnMoveDownClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = MoveDownClicked;
|
||||
handler?.Invoke(this, e);
|
||||
_connectionTree.SelectedNode.Parent.DemoteChild(_connectionTree.SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public event EventHandler ExternalToolClicked;
|
||||
|
||||
private void OnExternalToolClicked(object sender, EventArgs e)
|
||||
{
|
||||
var handler = ExternalToolClicked;
|
||||
handler?.Invoke(sender, e);
|
||||
StartExternalApp((ExternalTool)((ToolStripMenuItem)sender).Tag);
|
||||
}
|
||||
|
||||
private void StartExternalApp(ExternalTool externalTool)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_connectionTree.SelectedNode.GetTreeNodeType() == TreeNodeType.Connection | _connectionTree.SelectedNode.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
externalTool.Start(_connectionTree.SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("cMenTreeToolsExternalAppsEntry_Click failed (UI.Window.ConnectionTreeWindow)", ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void SortNodesRecursive(ConnectionInfo sortTarget, ListSortDirection sortDirection)
|
||||
{
|
||||
if (sortTarget == null)
|
||||
sortTarget = _connectionTree.GetRootConnectionNode();
|
||||
|
||||
var sortTargetAsContainer = sortTarget as ContainerInfo;
|
||||
if (sortTargetAsContainer != null)
|
||||
sortTargetAsContainer.SortRecursive(sortDirection);
|
||||
else
|
||||
_connectionTree.SelectedNode.Parent.SortRecursive(sortDirection);
|
||||
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs
generated
Normal file
36
mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
partial class ConnectionTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
286
mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
Normal file
286
mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using BrightIdeasSoftware;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public partial class ConnectionTree : TreeListView, IConnectionTree
|
||||
{
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
|
||||
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
|
||||
|
||||
public ConnectionInfo SelectedNode => (ConnectionInfo) SelectedObject;
|
||||
|
||||
public NodeSearcher NodeSearcher { get; private set; }
|
||||
|
||||
public IConfirm NodeDeletionConfirmer { get; set; } = new AlwaysConfirmYes();
|
||||
|
||||
public IEnumerable<IConnectionTreeDelegate> PostSetupActions { get; set; } = new IConnectionTreeDelegate[0];
|
||||
|
||||
public ITreeNodeClickHandler DoubleClickHandler { get; set; } = new TreeNodeCompositeClickHandler();
|
||||
|
||||
public ITreeNodeClickHandler SingleClickHandler { get; set; } = new TreeNodeCompositeClickHandler();
|
||||
|
||||
public ConnectionTreeModel ConnectionTreeModel
|
||||
{
|
||||
get { return _connectionTreeModel; }
|
||||
set
|
||||
{
|
||||
_connectionTreeModel = value;
|
||||
PopulateTreeView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ConnectionTree()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetupConnectionTreeView();
|
||||
}
|
||||
|
||||
#region ConnectionTree Setup
|
||||
private void SetupConnectionTreeView()
|
||||
{
|
||||
var imageList = new StatusImageList();
|
||||
SmallImageList = imageList.GetImageList();
|
||||
AddColumns(imageList.ImageGetter);
|
||||
LinkModelToView();
|
||||
SetupDropSink();
|
||||
SetEventHandlers();
|
||||
}
|
||||
|
||||
private void AddColumns(ImageGetterDelegate imageGetterDelegate)
|
||||
{
|
||||
Columns.Add(new NameColumn(imageGetterDelegate));
|
||||
}
|
||||
|
||||
private void LinkModelToView()
|
||||
{
|
||||
CanExpandGetter = item =>
|
||||
{
|
||||
var itemAsContainer = item as ContainerInfo;
|
||||
return itemAsContainer?.Children.Count > 0;
|
||||
};
|
||||
ChildrenGetter = item => ((ContainerInfo)item).Children;
|
||||
}
|
||||
|
||||
private void SetupDropSink()
|
||||
{
|
||||
DropSink = new SimpleDropSink
|
||||
{
|
||||
CanDropBetween = true
|
||||
};
|
||||
}
|
||||
|
||||
private void SetEventHandlers()
|
||||
{
|
||||
Collapsed += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = false;
|
||||
};
|
||||
Expanded += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = true;
|
||||
};
|
||||
SelectionChanged += tvConnections_AfterSelect;
|
||||
MouseDoubleClick += OnMouse_DoubleClick;
|
||||
MouseClick += OnMouse_SingleClick;
|
||||
CellToolTipShowing += tvConnections_CellToolTipShowing;
|
||||
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
|
||||
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
|
||||
}
|
||||
|
||||
private void PopulateTreeView()
|
||||
{
|
||||
UnregisterModelUpdateHandlers();
|
||||
SetObjects(ConnectionTreeModel.RootNodes);
|
||||
RegisterModelUpdateHandlers();
|
||||
NodeSearcher = new NodeSearcher(ConnectionTreeModel);
|
||||
ExecutePostSetupActions();
|
||||
}
|
||||
|
||||
private void RegisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged += OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged += HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged += HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void UnregisterModelUpdateHandlers()
|
||||
{
|
||||
_puttySessionsManager.PuttySessionsCollectionChanged -= OnPuttySessionsCollectionChanged;
|
||||
ConnectionTreeModel.CollectionChanged -= HandleCollectionChanged;
|
||||
ConnectionTreeModel.PropertyChanged -= HandleCollectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPuttySessionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshObjects(GetRootPuttyNodes().ToList());
|
||||
}
|
||||
|
||||
private void HandleCollectionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
|
||||
var property = propertyChangedEventArgs.PropertyName;
|
||||
if (property != "Name" && property != "OpenConnections") return;
|
||||
var senderAsConnectionInfo = sender as ConnectionInfo;
|
||||
if (senderAsConnectionInfo != null)
|
||||
RefreshObject(senderAsConnectionInfo);
|
||||
}
|
||||
|
||||
private void ExecutePostSetupActions()
|
||||
{
|
||||
foreach (var action in PostSetupActions)
|
||||
{
|
||||
action.Execute(this);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ConnectionTree Behavior
|
||||
public RootNodeInfo GetRootConnectionNode()
|
||||
{
|
||||
return (RootNodeInfo)Roots.Cast<ConnectionInfo>().First(item => item is RootNodeInfo);
|
||||
}
|
||||
|
||||
public void InvokeExpand(object model)
|
||||
{
|
||||
Invoke((MethodInvoker)(() => Expand(model)));
|
||||
}
|
||||
|
||||
public void InvokeRebuildAll(bool preserveState)
|
||||
{
|
||||
Invoke((MethodInvoker)(() => RebuildAll(preserveState)));
|
||||
}
|
||||
|
||||
public IEnumerable<RootPuttySessionsNodeInfo> GetRootPuttyNodes()
|
||||
{
|
||||
return Objects.OfType<RootPuttySessionsNodeInfo>();
|
||||
}
|
||||
|
||||
public void AddConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ConnectionInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("UI.Window.Tree.AddConnection() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ContainerInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strErrorAddFolderFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
newNode.SetParent(parent);
|
||||
Expand(parent);
|
||||
SelectObject(newNode, true);
|
||||
EnsureModelVisible(newNode);
|
||||
}
|
||||
|
||||
public void DuplicateSelectedNode()
|
||||
{
|
||||
var newNode = SelectedNode.Clone();
|
||||
newNode.Parent.SetChildBelow(newNode, SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void RenameSelectedNode()
|
||||
{
|
||||
SelectedItem.BeginEdit();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void DeleteSelectedNode()
|
||||
{
|
||||
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
|
||||
if (!NodeDeletionConfirmer.Confirm()) return;
|
||||
ConnectionTreeModel.DeleteNode(SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshObject(sender);
|
||||
}
|
||||
|
||||
private void tvConnections_AfterSelect(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.ConfigForm.SelectedTreeNode = SelectedNode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_AfterSelect (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouse_DoubleClick(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
if (mouseEventArgs.Clicks < 2) return;
|
||||
OLVColumn column;
|
||||
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
|
||||
var clickedNode = listItem.RowObject as ConnectionInfo;
|
||||
if (clickedNode == null) return;
|
||||
DoubleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
private void OnMouse_SingleClick(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
if (mouseEventArgs.Clicks > 1) return;
|
||||
OLVColumn column;
|
||||
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
|
||||
var clickedNode = listItem.RowObject as ConnectionInfo;
|
||||
if (clickedNode == null) return;
|
||||
SingleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
private void tvConnections_CellToolTipShowing(object sender, ToolTipShowingEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var nodeProducingTooltip = (ConnectionInfo)e.Model;
|
||||
e.Text = nodeProducingTooltip.Description;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_MouseMove (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
25
mRemoteV1/UI/Controls/ConnectionTree/IConnectionTree.cs
Normal file
25
mRemoteV1/UI/Controls/ConnectionTree/IConnectionTree.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public interface IConnectionTree
|
||||
{
|
||||
ConnectionTreeModel ConnectionTreeModel { get; set; }
|
||||
|
||||
ConnectionInfo SelectedNode { get; }
|
||||
|
||||
IEnumerable ExpandedObjects { get; set; }
|
||||
|
||||
RootNodeInfo GetRootConnectionNode();
|
||||
|
||||
void InvokeExpand(object model);
|
||||
|
||||
void InvokeRebuildAll(bool preserveState);
|
||||
|
||||
void ToggleExpansion(object model);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public interface IConnectionTreeDelegate
|
||||
{
|
||||
void Execute(IConnectionTree connectionTree);
|
||||
}
|
||||
}
|
||||
18
mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
Normal file
18
mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using BrightIdeasSoftware;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public class NameColumn : OLVColumn
|
||||
{
|
||||
public NameColumn(ImageGetterDelegate imageGetterDelegate)
|
||||
{
|
||||
AspectName = "Name";
|
||||
FillsFreeSpace = true;
|
||||
IsButton = true;
|
||||
AspectGetter = item => ((ConnectionInfo) item).Name;
|
||||
ImageGetter = imageGetterDelegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public class QuickConnectComboBox : ToolStripComboBox
|
||||
{
|
||||
private ComboBox _comboBox;
|
||||
private readonly ComboBox _comboBox;
|
||||
private bool _ignoreEnter;
|
||||
|
||||
public QuickConnectComboBox()
|
||||
@@ -53,7 +53,7 @@ namespace mRemoteNG.UI.Controls
|
||||
// Items can't be removed from the ComboBox while it is dropped down without possibly causing
|
||||
// an exception so we must close it, delete the item, and then drop it down again. When we
|
||||
// close it programmatically, the SelectedItem may revert to Nothing, so we must save it first.
|
||||
object item = _comboBox.SelectedItem;
|
||||
var item = _comboBox.SelectedItem;
|
||||
_comboBox.DroppedDown = false;
|
||||
_comboBox.Items.Remove(item);
|
||||
_comboBox.SelectedIndex = -1;
|
||||
@@ -66,29 +66,29 @@ namespace mRemoteNG.UI.Controls
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBox_SelectedIndexChanged(Object sender, EventArgs e)
|
||||
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!(_comboBox.SelectedItem is HistoryItem))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
HistoryItem historyItem = (HistoryItem) _comboBox.SelectedItem;
|
||||
var historyItem = (HistoryItem) _comboBox.SelectedItem;
|
||||
OnProtocolChanged(new ProtocolChangedEventArgs(historyItem.ConnectionInfo.Protocol));
|
||||
}
|
||||
|
||||
private static void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
ComboBox comboBox = sender as ComboBox;
|
||||
var comboBox = sender as ComboBox;
|
||||
if (comboBox == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
object drawItem = comboBox.Items[e.Index];
|
||||
var drawItem = comboBox.Items[e.Index];
|
||||
|
||||
string drawString;
|
||||
if (drawItem is HistoryItem)
|
||||
{
|
||||
HistoryItem historyItem = (HistoryItem) drawItem;
|
||||
var historyItem = (HistoryItem) drawItem;
|
||||
drawString = historyItem.ToString(true);
|
||||
}
|
||||
else
|
||||
@@ -116,11 +116,8 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ConnectionInfo.Protocol != other.ConnectionInfo.Protocol)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return ConnectionInfo.Protocol == other.ConnectionInfo.Protocol;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -130,31 +127,25 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
public string ToString(bool includeProtocol)
|
||||
{
|
||||
string port = string.Empty;
|
||||
var port = string.Empty;
|
||||
if (ConnectionInfo.Port != ConnectionInfo.GetDefaultPort())
|
||||
{
|
||||
port = $":{ConnectionInfo.Port}";
|
||||
}
|
||||
if (includeProtocol)
|
||||
{
|
||||
return $"{ConnectionInfo.Hostname}{port} ({ConnectionInfo.Protocol})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{ConnectionInfo.Hostname}{port}";
|
||||
}
|
||||
|
||||
return includeProtocol ? $"{ConnectionInfo.Hostname}{port} ({ConnectionInfo.Protocol})" : $"{ConnectionInfo.Hostname}{port}";
|
||||
}
|
||||
}
|
||||
|
||||
private bool Exists(HistoryItem searchItem)
|
||||
{
|
||||
foreach (object item in _comboBox.Items)
|
||||
foreach (var item in _comboBox.Items)
|
||||
{
|
||||
if (!(item is HistoryItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
HistoryItem historyItem = (HistoryItem) item;
|
||||
var historyItem = (HistoryItem) item;
|
||||
if (historyItem.Equals(searchItem))
|
||||
{
|
||||
return true;
|
||||
@@ -167,7 +158,7 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
try
|
||||
{
|
||||
HistoryItem historyItem = new HistoryItem {ConnectionInfo = connectionInfo};
|
||||
var historyItem = new HistoryItem {ConnectionInfo = connectionInfo};
|
||||
if (!Exists(historyItem))
|
||||
{
|
||||
_comboBox.Items.Insert(0, historyItem);
|
||||
@@ -175,7 +166,7 @@ namespace mRemoteNG.UI.Controls
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strQuickConnectAddFailed, ex, Messages.MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strQuickConnectAddFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +200,8 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void OnConnectRequested(ConnectRequestedEventArgs e)
|
||||
{
|
||||
ConnectRequestedEvent?.Invoke(this, new ConnectRequestedEventArgs(e.ConnectionString));
|
||||
// TODO: Any reason to not jsut pass "e"?
|
||||
ConnectRequestedEvent?.Invoke(this, new ConnectRequestedEventArgs(e.ConnectionString));
|
||||
}
|
||||
|
||||
public class ProtocolChangedEventArgs : EventArgs
|
||||
@@ -241,6 +233,7 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void OnProtocolChanged(ProtocolChangedEventArgs e)
|
||||
{
|
||||
// TODO: Any reason to not jsut pass "e"?
|
||||
ProtocolChangedEvent?.Invoke(this, new ProtocolChangedEventArgs(e.Protocol));
|
||||
}
|
||||
#endregion
|
||||
|
||||
57
mRemoteV1/UI/Controls/StatusImageList.cs
Normal file
57
mRemoteV1/UI/Controls/StatusImageList.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree.Root;
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public class StatusImageList
|
||||
{
|
||||
public ImageList GetImageList()
|
||||
{
|
||||
var imageList = new ImageList
|
||||
{
|
||||
ColorDepth = ColorDepth.Depth32Bit,
|
||||
ImageSize = new Size(16, 16),
|
||||
TransparentColor = Color.Transparent
|
||||
};
|
||||
FillImageList(imageList);
|
||||
return imageList;
|
||||
}
|
||||
|
||||
public object ImageGetter(object rowObject)
|
||||
{
|
||||
if (rowObject is RootPuttySessionsNodeInfo) return "PuttySessions";
|
||||
if (rowObject is RootNodeInfo) return "Root";
|
||||
if (rowObject is ContainerInfo) return "Folder";
|
||||
var connection = rowObject as ConnectionInfo;
|
||||
if (connection == null) return "";
|
||||
return connection.OpenConnections.Count > 0 ? "Play" : "Pause";
|
||||
}
|
||||
|
||||
private void FillImageList(ImageList imageList)
|
||||
{
|
||||
try
|
||||
{
|
||||
imageList.Images.Add(Resources.Root);
|
||||
imageList.Images.SetKeyName(0, "Root");
|
||||
imageList.Images.Add(Resources.Folder);
|
||||
imageList.Images.SetKeyName(1, "Folder");
|
||||
imageList.Images.Add(Resources.Play);
|
||||
imageList.Images.SetKeyName(2, "Play");
|
||||
imageList.Images.Add(Resources.Pause);
|
||||
imageList.Images.SetKeyName(3, "Pause");
|
||||
imageList.Images.Add(Resources.PuttySessions);
|
||||
imageList.Images.SetKeyName(4, "PuttySessions");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace($"Unable to fill the image list of type {nameof(StatusImageList)}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
if (e.CloseReason != ToolStripDropDownCloseReason.AppClicked)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle dropDownButtonBoundsClient = DropDownButtonBounds; // Relative to the ToolStripSplitButton
|
||||
|
||||
@@ -205,7 +205,7 @@ namespace mRemoteNG.UI.Forms
|
||||
SelectFileTypeBasedOnSaveFormat(saveFileDialog);
|
||||
|
||||
if (saveFileDialog.ShowDialog(this) != DialogResult.OK)
|
||||
return ;
|
||||
return;
|
||||
|
||||
txtFileName.Text = saveFileDialog.FileName;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
{
|
||||
@@ -79,7 +80,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
{
|
||||
if (Runtime.NotificationAreaIcon == null)
|
||||
{
|
||||
Runtime.NotificationAreaIcon = new Tools.Controls.NotificationAreaIcon();
|
||||
Runtime.NotificationAreaIcon = new NotificationAreaIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user