mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Compare commits
19 Commits
v1.75RC1
...
v1.75Hotfi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3943b8753f | ||
|
|
9e26ea1866 | ||
|
|
8152a87514 | ||
|
|
b28775c2c6 | ||
|
|
3eb96ef765 | ||
|
|
8805584cbe | ||
|
|
be5c66bd93 | ||
|
|
5347e5a3aa | ||
|
|
9b22254b6c | ||
|
|
6a67e0ea8b | ||
|
|
7b118995ea | ||
|
|
35b4564644 | ||
|
|
30df947365 | ||
|
|
b1ec975612 | ||
|
|
1034e434c4 | ||
|
|
f419bff545 | ||
|
|
69eec0135e | ||
|
|
2849baf857 | ||
|
|
768fdcd0e4 |
@@ -1,3 +1,43 @@
|
||||
1.75.7002 (2017-03-10):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#448: Resolved issue with SQL saving
|
||||
|
||||
|
||||
1.75.7001 (2017-03-10):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#408: Update SQL scripts
|
||||
|
||||
|
||||
1.75 hotfix 1 (2017-03-06):
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
#437: Modify version numbering scheme
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#422: Uncaught exception when clicking in connection tree whitespace
|
||||
#312: Resolved KeePass auto-type issue
|
||||
#427: Export does not respect filtering user/password/domain
|
||||
|
||||
|
||||
1.75 (2017-03-01):
|
||||
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
@@ -12,13 +12,14 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public class XmlConnectionNodeSerializerTests
|
||||
{
|
||||
private XmlConnectionNodeSerializer _connectionNodeSerializer;
|
||||
private ICryptographyProvider _cryptographyProvider;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
|
||||
BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString());
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), new SaveFilter());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -48,8 +49,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void AttributesNotSerializedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
|
||||
{
|
||||
var saveFilter = new SaveFilter(true);
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
|
||||
Assert.That(targetAttribute?.Value, Is.EqualTo(string.Empty));
|
||||
@@ -59,8 +59,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void InheritanceNotSerialiedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
|
||||
{
|
||||
var saveFilter = new SaveFilter(true);
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
|
||||
Assert.That(targetAttribute?.Value, Is.EqualTo(false.ToString()));
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void Setup()
|
||||
{
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var saveFilter = new SaveFilter();
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, saveFilter);
|
||||
_connectionTreeModel = SetupConnectionTreeModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
{
|
||||
var connectionTreeModel = SetupConnectionTreeModel();
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider).CompileDocument(connectionTreeModel, false, false);
|
||||
var saveFilter = new SaveFilter();
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, saveFilter).CompileDocument(connectionTreeModel, false, false);
|
||||
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
@@ -45,6 +47,27 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
Assert.That(connectionNode, Is.Not.Null);
|
||||
}
|
||||
|
||||
[TestCase("Username", "")]
|
||||
[TestCase("Domain", "")]
|
||||
[TestCase("Password", "")]
|
||||
[TestCase("InheritAutomaticResize", "False")]
|
||||
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
|
||||
{
|
||||
_serializer.SaveFilter = new SaveFilter(true);
|
||||
var connectionInfo = new ConnectionInfo
|
||||
{
|
||||
Name = "myConnection",
|
||||
Username = "somefilteredstuff",
|
||||
Domain = "somefilteredstuff",
|
||||
Password = "somefilteredstuff",
|
||||
Inheritance = {AutomaticResize = true}
|
||||
};
|
||||
var serializedConnections = _serializer.Serialize(connectionInfo);
|
||||
var xdoc = XDocument.Parse(serializedConnections);
|
||||
var attributeValue = xdoc.Root?.Element("Node")?.Attribute(attributeName)?.Value;
|
||||
Assert.That(attributeValue, Is.EqualTo(expectedValue));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel SetupConnectionTreeModel()
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -276,14 +276,14 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
#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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
var connector = new SqlDatabaseConnector();
|
||||
var dataProvider = new SqlDataProvider(connector);
|
||||
var dataTable = dataProvider.Load();
|
||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
|
||||
databaseVersionVerifier.VerifyDatabaseVersion();
|
||||
var dataTable = dataProvider.Load();
|
||||
deserializer = new DataTableDeserializer(dataTable);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -85,8 +85,9 @@ namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
var sqlConnector = new SqlDatabaseConnector();
|
||||
sqlConnector.Connect();
|
||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
|
||||
|
||||
if (!VerifyDatabaseVersion(sqlConnector))
|
||||
if (!databaseVersionVerifier.VerifyDatabaseVersion())
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
|
||||
return;
|
||||
@@ -102,83 +103,6 @@ namespace mRemoteNG.Config.Connections
|
||||
sqlConnector.Dispose();
|
||||
}
|
||||
|
||||
private bool VerifyDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
var isVerified = false;
|
||||
try
|
||||
{
|
||||
var databaseVersion = GetDatabaseVersion(sqlDatabaseConnector);
|
||||
SqlCommand sqlCommand;
|
||||
|
||||
if (databaseVersion.Equals(new Version()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 2)) == 0) // 2.2
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.3.");
|
||||
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD EnableFontSmoothing bit NOT NULL DEFAULT 0, EnableDesktopComposition bit NOT NULL DEFAULT 0, InheritEnableFontSmoothing bit NOT NULL DEFAULT 0, InheritEnableDesktopComposition bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
databaseVersion = new Version(2, 3);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 3)) == 0) // 2.3
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.4.");
|
||||
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD UseCredSsp bit NOT NULL DEFAULT 1, InheritUseCredSsp bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
databaseVersion = new Version(2, 4);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 4)) == 0) // 2.4
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.5.");
|
||||
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD LoadBalanceInfo varchar (1024) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, AutomaticResize bit NOT NULL DEFAULT 1, InheritLoadBalanceInfo bit NOT NULL DEFAULT 0, InheritAutomaticResize bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
databaseVersion = new Version(2, 5);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 5)) == 0) // 2.5
|
||||
isVerified = true;
|
||||
|
||||
if (isVerified == false)
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, string.Format(Language.strErrorBadDatabaseVersion, databaseVersion, GeneralAppInfo.ProductName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.strErrorVerifyDatabaseVersionFailed, ex.Message));
|
||||
}
|
||||
return isVerified;
|
||||
}
|
||||
|
||||
private Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
Version databaseVersion;
|
||||
SqlDataReader sqlDataReader = null;
|
||||
try
|
||||
{
|
||||
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||
sqlDataReader = sqlCommand.ExecuteReader();
|
||||
if (!sqlDataReader.HasRows)
|
||||
return new Version(); // assume new empty database
|
||||
else
|
||||
sqlDataReader.Read();
|
||||
databaseVersion = new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sqlDataReader != null && !sqlDataReader.IsClosed)
|
||||
sqlDataReader.Close();
|
||||
}
|
||||
return databaseVersion;
|
||||
}
|
||||
|
||||
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
|
||||
@@ -33,9 +33,13 @@ namespace mRemoteNG.Config.DataProviders
|
||||
{
|
||||
if (!SqlDatabaseConnector.IsConnected)
|
||||
OpenConnection();
|
||||
var sqlBulkCopy = new SqlBulkCopy(SqlDatabaseConnector.SqlConnection) {DestinationTableName = "dbo.tblCons"};
|
||||
sqlBulkCopy.WriteToServer(dataTable);
|
||||
sqlBulkCopy.Close();
|
||||
using (var sqlBulkCopy = new SqlBulkCopy(SqlDatabaseConnector.SqlConnection))
|
||||
{
|
||||
foreach (DataColumn col in dataTable.Columns)
|
||||
sqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
|
||||
sqlBulkCopy.DestinationTableName = "dbo.tblCons";
|
||||
sqlBulkCopy.WriteToServer(dataTable);
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Connection.Protocol.Http;
|
||||
@@ -33,6 +34,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
var connectionList = CreateNodesFromTable();
|
||||
var connectionTreeModel = CreateNodeHierarchy(connectionList);
|
||||
Runtime.IsConnectionsFileLoaded = true;
|
||||
return connectionTreeModel;
|
||||
}
|
||||
|
||||
@@ -155,8 +157,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.RDPAlertIdleTimeout = (bool)dataRow["InheritRDPAlertIdleTimeout"];
|
||||
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = (bool)dataRow["InheritRDPMinutesToIdleTimeout"];
|
||||
connectionInfo.Inheritance.LoadBalanceInfo = (bool)dataRow["InheritLoadBalanceInfo"];
|
||||
connectionInfo.Inheritance.PreExtApp = (bool)dataRow["InheritPreExtApp"];
|
||||
connectionInfo.Inheritance.PostExtApp = (bool)dataRow["InheritPostExtApp"];
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
private void CreateSchema()
|
||||
{
|
||||
// Note: these columns must be defined in the same order that they exist in the DB
|
||||
_dataTable.Columns.Add("ID", typeof(int));
|
||||
_dataTable.Columns[0].AutoIncrement = true;
|
||||
_dataTable.Columns.Add("ConstantID", typeof(string));
|
||||
@@ -65,8 +66,6 @@ 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));
|
||||
@@ -123,15 +122,12 @@ namespace mRemoteNG.Config.Serializers
|
||||
_dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRedirectSound", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritResolution", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritUseConsoleSession", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritUseCredSsp", typeof(bool));
|
||||
_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));
|
||||
@@ -159,6 +155,12 @@ namespace mRemoteNG.Config.Serializers
|
||||
_dataTable.Columns.Add("AutomaticResize", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritLoadBalanceInfo", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritAutomaticResize", typeof(bool));
|
||||
_dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
|
||||
_dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("SoundQuality", typeof(string));
|
||||
_dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
|
||||
_dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
|
||||
}
|
||||
|
||||
private void SetPrimaryKey()
|
||||
@@ -204,8 +206,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["RDPMinutesToIdleTimeout"] = connectionInfo.RDPMinutesToIdleTimeout;
|
||||
dataRow["RDPAlertIdleTimeout"] = connectionInfo.RDPAlertIdleTimeout;
|
||||
dataRow["LoadBalanceInfo"] = connectionInfo.LoadBalanceInfo;
|
||||
dataRow["Colors"] = connectionInfo.Colors;
|
||||
dataRow["Resolution"] = connectionInfo.Resolution;
|
||||
@@ -220,7 +222,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["RedirectPrinters"] = connectionInfo.RedirectPrinters;
|
||||
dataRow["RedirectSmartCards"] = connectionInfo.RedirectSmartCards;
|
||||
dataRow["RedirectSound"] = connectionInfo.RedirectSound;
|
||||
//dataRow["SoundQuality"] = connectionInfo.SoundQuality;
|
||||
dataRow["SoundQuality"] = connectionInfo.SoundQuality;
|
||||
dataRow["RedirectKeys"] = connectionInfo.RedirectKeys;
|
||||
dataRow["Connected"] = connectionInfo.OpenConnections.Count > 0;
|
||||
dataRow["PreExtApp"] = connectionInfo.PreExtApp;
|
||||
@@ -267,7 +269,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritRedirectPrinters"] = connectionInfo.Inheritance.RedirectPrinters;
|
||||
dataRow["InheritRedirectSmartCards"] = connectionInfo.Inheritance.RedirectSmartCards;
|
||||
dataRow["InheritRedirectSound"] = connectionInfo.Inheritance.RedirectSound;
|
||||
//dataRow["InheritSoundQuality"] = connectionInfo.Inheritance.SoundQuality;
|
||||
dataRow["InheritSoundQuality"] = connectionInfo.Inheritance.SoundQuality;
|
||||
dataRow["InheritResolution"] = connectionInfo.Inheritance.Resolution;
|
||||
dataRow["InheritAutomaticResize"] = connectionInfo.Inheritance.AutomaticResize;
|
||||
dataRow["InheritUseConsoleSession"] = connectionInfo.Inheritance.UseConsoleSession;
|
||||
@@ -276,8 +278,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["InheritRDPMinutesToIdleTimeout"] = connectionInfo.Inheritance.RDPMinutesToIdleTimeout;
|
||||
dataRow["InheritRDPAlertIdleTimeout"] = connectionInfo.Inheritance.RDPAlertIdleTimeout;
|
||||
dataRow["InheritLoadBalanceInfo"] = connectionInfo.Inheritance.LoadBalanceInfo;
|
||||
dataRow["InheritPreExtApp"] = connectionInfo.Inheritance.PreExtApp;
|
||||
dataRow["InheritPostExtApp"] = connectionInfo.Inheritance.PostExtApp;
|
||||
@@ -324,7 +326,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritRedirectPrinters"] = false;
|
||||
dataRow["InheritRedirectSmartCards"] = false;
|
||||
dataRow["InheritRedirectSound"] = false;
|
||||
//dataRow["InheritSoundQuality"] = false;
|
||||
dataRow["InheritSoundQuality"] = false;
|
||||
dataRow["InheritResolution"] = false;
|
||||
dataRow["InheritAutomaticResize"] = false;
|
||||
dataRow["InheritUseConsoleSession"] = false;
|
||||
@@ -333,8 +335,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritUsername"] = false;
|
||||
dataRow["InheritICAEncryptionStrength"] = false;
|
||||
dataRow["InheritRDPAuthenticationLevel"] = false;
|
||||
//dataRow["InheritRDPMinutesToIdleTimeout"] = false;
|
||||
//dataRow["InheritRDPAlertIdleTimeout"] = false;
|
||||
dataRow["InheritRDPMinutesToIdleTimeout"] = false;
|
||||
dataRow["InheritRDPAlertIdleTimeout"] = false;
|
||||
dataRow["InheritLoadBalanceInfo"] = false;
|
||||
dataRow["InheritPreExtApp"] = false;
|
||||
dataRow["InheritPostExtApp"] = false;
|
||||
|
||||
158
mRemoteV1/Config/Serializers/SqlDatabaseVersionVerifier.cs
Normal file
158
mRemoteV1/Config/Serializers/SqlDatabaseVersionVerifier.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
public class SqlDatabaseVersionVerifier
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
|
||||
public SqlDatabaseVersionVerifier(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
}
|
||||
|
||||
public bool VerifyDatabaseVersion()
|
||||
{
|
||||
var isVerified = false;
|
||||
try
|
||||
{
|
||||
var databaseVersion = GetDatabaseVersion(_sqlDatabaseConnector);
|
||||
|
||||
if (databaseVersion.Equals(new Version()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 2)) == 0) // 2.2
|
||||
{
|
||||
UpgradeFrom2_2();
|
||||
databaseVersion = new Version(2, 3);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 3)) == 0) // 2.3
|
||||
{
|
||||
UpgradeFrom2_3();
|
||||
databaseVersion = new Version(2, 4);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 4)) == 0) // 2.4
|
||||
{
|
||||
UpgradeFrom2_4();
|
||||
databaseVersion = new Version(2, 5);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 5)) == 0) // 2.5
|
||||
{
|
||||
UpgradeFrom2_5();
|
||||
databaseVersion = new Version(2, 6);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 6)) == 0) // 2.6
|
||||
isVerified = true;
|
||||
|
||||
if (isVerified == false)
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg,
|
||||
string.Format(Language.strErrorBadDatabaseVersion, databaseVersion, GeneralAppInfo.ProductName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg,
|
||||
string.Format(Language.strErrorVerifyDatabaseVersionFailed, ex.Message));
|
||||
}
|
||||
return isVerified;
|
||||
}
|
||||
|
||||
private Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
Version databaseVersion;
|
||||
SqlDataReader sqlDataReader = null;
|
||||
try
|
||||
{
|
||||
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||
if (!sqlDatabaseConnector.IsConnected)
|
||||
sqlDatabaseConnector.Connect();
|
||||
sqlDataReader = sqlCommand.ExecuteReader();
|
||||
if (!sqlDataReader.HasRows)
|
||||
return new Version(); // assume new empty database
|
||||
else
|
||||
sqlDataReader.Read();
|
||||
databaseVersion =
|
||||
new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sqlDataReader != null && !sqlDataReader.IsClosed)
|
||||
sqlDataReader.Close();
|
||||
}
|
||||
return databaseVersion;
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_2()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.2 to version 2.3.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD EnableFontSmoothing bit NOT NULL DEFAULT 0,
|
||||
EnableDesktopComposition bit NOT NULL DEFAULT 0,
|
||||
InheritEnableFontSmoothing bit NOT NULL DEFAULT 0,
|
||||
InheritEnableDesktopComposition bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_3()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.3 to version 2.4.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD UseCredSsp bit NOT NULL DEFAULT 1,
|
||||
InheritUseCredSsp bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_4()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.4 to version 2.5.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD LoadBalanceInfo varchar (1024) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
AutomaticResize bit NOT NULL DEFAULT 1,
|
||||
InheritLoadBalanceInfo bit NOT NULL DEFAULT 0,
|
||||
InheritAutomaticResize bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_5()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.5 to version 2.6.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD RDPMinutesToIdleTimeout int NOT NULL DEFAULT 0,
|
||||
RDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
SoundQuality varchar (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL DEFAULT 'Dynamic',
|
||||
InheritRDPMinutesToIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
InheritRDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
InheritSoundQuality bit NOT NULL DEFAULT 0;
|
||||
UPDATE tblRoot
|
||||
SET ConfVersion='2.6'";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Security;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
@@ -13,14 +14,15 @@ namespace mRemoteNG.Config.Serializers
|
||||
private readonly SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter = new SaveFilter();
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
|
||||
{
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
}
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (encryptionKey == null)
|
||||
throw new ArgumentNullException(nameof(encryptionKey));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
_saveFilter = saveFilter;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
@@ -14,10 +15,17 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter;
|
||||
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider)
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_saveFilter = saveFilter;
|
||||
}
|
||||
|
||||
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
|
||||
@@ -77,7 +85,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey);
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey, _saveFilter);
|
||||
return connectionSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
var xml = "";
|
||||
try
|
||||
{
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, SaveFilter);
|
||||
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
|
||||
xml = WriteXmlToString(xmlDocument);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
|
||||
// by using the '*' as shown below:
|
||||
// <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
[assembly: AssemblyVersion("1.75.*")]
|
||||
[assembly: AssemblyVersion("1.75.7002.*")]
|
||||
|
||||
[assembly:NeutralResourcesLanguageAttribute("en")]
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ CREATE TABLE [dbo].[tblCons] (
|
||||
[RenderingEngine] [varchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
|
||||
[ICAEncryptionStrength] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
|
||||
[RDPAuthenticationLevel] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
|
||||
[RDPMinutesToIdleTimeout] [int] NOT NULL,
|
||||
[RDPAlertIdleTimeout] [bit] NOT NULL,
|
||||
[Colors] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
|
||||
[Resolution] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
|
||||
[DisplayWallpaper] [bit] NOT NULL ,
|
||||
@@ -46,6 +48,7 @@ CREATE TABLE [dbo].[tblCons] (
|
||||
[RedirectPrinters] [bit] NOT NULL ,
|
||||
[RedirectSmartCards] [bit] NOT NULL ,
|
||||
[RedirectSound] [varchar] (64) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
|
||||
[SoundQuality] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
[RedirectKeys] [bit] NOT NULL ,
|
||||
[Connected] [bit] NOT NULL ,
|
||||
[PreExtApp] [varchar] (256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
|
||||
@@ -90,12 +93,15 @@ CREATE TABLE [dbo].[tblCons] (
|
||||
[InheritRedirectPrinters] [bit] NOT NULL ,
|
||||
[InheritRedirectSmartCards] [bit] NOT NULL ,
|
||||
[InheritRedirectSound] [bit] NOT NULL ,
|
||||
[InheritSoundQuality] [bit] NOT NULL,
|
||||
[InheritResolution] [bit] NOT NULL ,
|
||||
[InheritUseConsoleSession] [bit] NOT NULL ,
|
||||
[InheritUseCredSsp] [bit] NOT NULL ,
|
||||
[InheritRenderingEngine] [bit] NOT NULL ,
|
||||
[InheritICAEncryptionStrength] [bit] NOT NULL ,
|
||||
[InheritRDPAuthenticationLevel] [bit] NOT NULL ,
|
||||
[InheritRDPMinutesToIdleTimeout] [bit] NOT NULL,
|
||||
[InheritRDPAlertIdleTimeout] [bit] NOT NULL,
|
||||
[InheritUsername] [bit] NOT NULL ,
|
||||
[InheritPreExtApp] [bit] NOT NULL ,
|
||||
[InheritPostExtApp] [bit] NOT NULL ,
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
InitializeComponent();
|
||||
SetupConnectionTreeView();
|
||||
UseOverlays = false;
|
||||
}
|
||||
|
||||
#region ConnectionTree Setup
|
||||
@@ -99,8 +100,8 @@ namespace mRemoteNG.UI.Controls
|
||||
container.IsExpanded = true;
|
||||
};
|
||||
SelectionChanged += tvConnections_AfterSelect;
|
||||
CellClick += tvConnections_NodeMouseSingleClick;
|
||||
CellClick += tvConnections_NodeMouseDoubleClick;
|
||||
MouseDoubleClick += OnMouse_DoubleClick;
|
||||
MouseClick += OnMouse_SingleClick;
|
||||
CellToolTipShowing += tvConnections_CellToolTipShowing;
|
||||
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
|
||||
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
|
||||
@@ -249,22 +250,26 @@ namespace mRemoteNG.UI.Controls
|
||||
}
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseSingleClick(object sender, CellClickEventArgs e)
|
||||
private void OnMouse_DoubleClick(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
if (e.ClickCount > 1) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
if (clickedNode == null) return;
|
||||
SingleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseDoubleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
if (e.ClickCount < 2) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
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
|
||||
|
||||
@@ -213,6 +213,7 @@
|
||||
<Compile Include="Tools\NotificationAreaIcon.cs" />
|
||||
<Compile Include="Tools\ScanHost.cs" />
|
||||
<Compile Include="Tools\SecureTransfer.cs" />
|
||||
<Compile Include="Config\Serializers\SqlDatabaseVersionVerifier.cs" />
|
||||
<Compile Include="Tree\AlwaysConfirmYes.cs" />
|
||||
<Compile Include="Tree\SelectedConnectionDeletionConfirmer.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeDragAndDropHandler.cs" />
|
||||
|
||||
Reference in New Issue
Block a user