mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Implement MySQL support
* Uses MySQL Connector/NET from nuget * Adds SQL Server type to configuration. * Hostname for MySQL connections can include port - Format: <hostname>[:<port>] * Abstracted a bundle of stuff to be generic for both MSSQL and MySQL, including a number of variable and method names. (Mostly went from "sql..." -> "db..." * Changed MiscTools.DBDate() string building for MSSQL, uses DateTime.ToString() with a format which seemed simpler. * Unsure about which lines in .csproj are actually required, and which are auto-munged by Visual Studio. * ... This is my first C# (and VS!) work, be gentle! Signed-off-by: Mike Beattie <mike@ethernal.org>
This commit is contained in:
@@ -4,23 +4,23 @@ using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data.Common;
|
||||
using System.Threading;
|
||||
|
||||
namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
public class SqlConnectionsUpdateChecker : IConnectionsUpdateChecker
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlConnector;
|
||||
private readonly SqlCommand _sqlQuery;
|
||||
private readonly IDatabaseConnector _dbConnector;
|
||||
private readonly DbCommand _dbQuery;
|
||||
private DateTime LastUpdateTime => Runtime.ConnectionsService.LastSqlUpdate;
|
||||
private DateTime _lastDatabaseUpdateTime;
|
||||
|
||||
|
||||
public SqlConnectionsUpdateChecker()
|
||||
{
|
||||
_sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
||||
_sqlQuery = new SqlCommand("SELECT * FROM tblUpdate", _sqlConnector.SqlConnection);
|
||||
_dbConnector = DatabaseConnectorFactory.DatabaseConnectorFromSettings();
|
||||
_dbQuery = _dbConnector.DbCommand("SELECT * FROM tblUpdate");
|
||||
_lastDatabaseUpdateTime = default(DateTime);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
try
|
||||
{
|
||||
_sqlConnector.Connect();
|
||||
_dbConnector.Connect();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -76,7 +76,7 @@ namespace mRemoteNG.Config.Connections
|
||||
var lastUpdateInDb = default(DateTime);
|
||||
try
|
||||
{
|
||||
var sqlReader = _sqlQuery.ExecuteReader(CommandBehavior.CloseConnection);
|
||||
var sqlReader = _dbQuery.ExecuteReader(CommandBehavior.CloseConnection);
|
||||
sqlReader.Read();
|
||||
if (sqlReader.HasRows)
|
||||
lastUpdateInDb = Convert.ToDateTime(sqlReader["LastUpdate"]);
|
||||
@@ -114,7 +114,7 @@ namespace mRemoteNG.Config.Connections
|
||||
private void RaiseConnectionsUpdateAvailableEvent()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Remote connection update is available");
|
||||
var args = new ConnectionsUpdateAvailableEventArgs(_sqlConnector, _lastDatabaseUpdateTime);
|
||||
var args = new ConnectionsUpdateAvailableEventArgs(_dbConnector, _lastDatabaseUpdateTime);
|
||||
ConnectionsUpdateAvailable?.Invoke(this, args);
|
||||
}
|
||||
|
||||
@@ -126,9 +126,9 @@ namespace mRemoteNG.Config.Connections
|
||||
private void Dispose(bool itIsSafeToDisposeManagedObjects)
|
||||
{
|
||||
if (!itIsSafeToDisposeManagedObjects) return;
|
||||
_sqlConnector.Disconnect();
|
||||
_sqlConnector.Dispose();
|
||||
_sqlQuery.Dispose();
|
||||
_dbConnector.Disconnect();
|
||||
_dbConnector.Dispose();
|
||||
_dbQuery.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace mRemoteNG.Config.Connections
|
||||
|
||||
public ConnectionTreeModel Load()
|
||||
{
|
||||
var connector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
||||
var connector = DatabaseConnectorFactory.DatabaseConnectorFromSettings();
|
||||
var dataProvider = new SqlDataProvider(connector);
|
||||
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
|
||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
|
||||
|
||||
@@ -14,7 +14,6 @@ using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
@@ -61,12 +60,12 @@ namespace mRemoteNG.Config.Connections
|
||||
return;
|
||||
}
|
||||
|
||||
using (var sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings())
|
||||
using (var dbConnector = DatabaseConnectorFactory.DatabaseConnectorFromSettings())
|
||||
{
|
||||
sqlConnector.Connect();
|
||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
|
||||
dbConnector.Connect();
|
||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(dbConnector);
|
||||
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
|
||||
var metaData = metaDataRetriever.GetDatabaseMetaData(sqlConnector);
|
||||
var metaData = metaDataRetriever.GetDatabaseMetaData(dbConnector);
|
||||
|
||||
if (!databaseVersionVerifier.VerifyDatabaseVersion(metaData.ConfVersion))
|
||||
{
|
||||
@@ -75,9 +74,10 @@ namespace mRemoteNG.Config.Connections
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateRootNodeTable(rootTreeNode, sqlConnector);
|
||||
UpdateConnectionsTable(rootTreeNode, sqlConnector);
|
||||
UpdateUpdatesTable(sqlConnector);
|
||||
UpdateRootNodeTable(rootTreeNode, dbConnector);
|
||||
UpdateConnectionsTable(rootTreeNode, dbConnector);
|
||||
UpdateUpdatesTable(dbConnector);
|
||||
|
||||
}
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved connections to database");
|
||||
@@ -111,7 +111,7 @@ namespace mRemoteNG.Config.Connections
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved local connection properties");
|
||||
}
|
||||
|
||||
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
||||
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, IDatabaseConnector databaseConnector)
|
||||
{
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
string strProtected;
|
||||
@@ -132,19 +132,17 @@ namespace mRemoteNG.Config.Connections
|
||||
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _password);
|
||||
}
|
||||
|
||||
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||
sqlQuery.ExecuteNonQuery();
|
||||
var dbQuery = databaseConnector.DbCommand("DELETE FROM tblRoot");
|
||||
dbQuery.ExecuteNonQuery();
|
||||
|
||||
if (rootTreeNode != null)
|
||||
{
|
||||
sqlQuery =
|
||||
new SqlCommand(
|
||||
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(\'" +
|
||||
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "\', 0, \'" + strProtected + "\'," +
|
||||
ConnectionsFileInfo.ConnectionFileVersion.ToString(CultureInfo.InvariantCulture) +
|
||||
")",
|
||||
sqlDatabaseConnector.SqlConnection);
|
||||
sqlQuery.ExecuteNonQuery();
|
||||
dbQuery =
|
||||
databaseConnector.DbCommand(
|
||||
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(\'" +
|
||||
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "\', 0, \'" + strProtected + "\'," +
|
||||
ConnectionsFileInfo.ConnectionFileVersion.ToString(CultureInfo.InvariantCulture) + ")");
|
||||
dbQuery.ExecuteNonQuery();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,28 +151,26 @@ namespace mRemoteNG.Config.Connections
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateConnectionsTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
||||
private void UpdateConnectionsTable(RootNodeInfo rootTreeNode, IDatabaseConnector databaseConnector)
|
||||
{
|
||||
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
|
||||
var serializer = new DataTableSerializer(_saveFilter, cryptoProvider,
|
||||
rootTreeNode.PasswordString.ConvertToSecureString());
|
||||
var dataTable = serializer.Serialize(rootTreeNode);
|
||||
var dataProvider = new SqlDataProvider(sqlDatabaseConnector);
|
||||
var dataProvider = new SqlDataProvider(databaseConnector);
|
||||
|
||||
var dbQuery = databaseConnector.DbCommand("DELETE FROM tblCons");
|
||||
dbQuery.ExecuteNonQuery();
|
||||
|
||||
var sqlQuery = new SqlCommand("DELETE FROM tblCons", sqlDatabaseConnector.SqlConnection);
|
||||
sqlQuery.ExecuteNonQuery();
|
||||
dataProvider.Save(dataTable);
|
||||
}
|
||||
|
||||
private void UpdateUpdatesTable(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
private void UpdateUpdatesTable(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
var sqlQuery = new SqlCommand("DELETE FROM tblUpdate", sqlDatabaseConnector.SqlConnection);
|
||||
sqlQuery.ExecuteNonQuery();
|
||||
sqlQuery = new SqlCommand(
|
||||
"INSERT INTO tblUpdate (LastUpdate) VALUES(\'" + MiscTools.DBDate(DateTime.Now) +
|
||||
"\')",
|
||||
sqlDatabaseConnector.SqlConnection);
|
||||
sqlQuery.ExecuteNonQuery();
|
||||
var dbQuery = databaseConnector.DbCommand("DELETE FROM tblUpdate");
|
||||
dbQuery.ExecuteNonQuery();
|
||||
dbQuery = databaseConnector.DbCommand("INSERT INTO tblUpdate (LastUpdate) VALUES(\'" + MiscTools.DBDate(DateTime.Now) + "\')");
|
||||
dbQuery.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private bool SqlUserIsReadOnly()
|
||||
|
||||
@@ -1,66 +1,93 @@
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.App;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.DataProviders
|
||||
{
|
||||
public class SqlDataProvider : IDataProvider<DataTable>
|
||||
{
|
||||
public SqlDatabaseConnector SqlDatabaseConnector { get; }
|
||||
public IDatabaseConnector DatabaseConnector { get; }
|
||||
|
||||
public SqlDataProvider(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlDataProvider(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
SqlDatabaseConnector = sqlDatabaseConnector;
|
||||
DatabaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public DataTable Load()
|
||||
{
|
||||
var dataTable = new DataTable();
|
||||
var sqlQuery = new SqlCommand("SELECT * FROM tblCons ORDER BY PositionID ASC");
|
||||
SqlDatabaseConnector.AssociateItemToThisConnector(sqlQuery);
|
||||
if (!SqlDatabaseConnector.IsConnected)
|
||||
var dbQuery = DatabaseConnector.DbCommand("SELECT * FROM tblCons ORDER BY PositionID ASC");
|
||||
DatabaseConnector.AssociateItemToThisConnector(dbQuery);
|
||||
if (!DatabaseConnector.IsConnected)
|
||||
OpenConnection();
|
||||
var sqlDataReader = sqlQuery.ExecuteReader(CommandBehavior.CloseConnection);
|
||||
var dbDataReader = dbQuery.ExecuteReader(CommandBehavior.CloseConnection);
|
||||
|
||||
if (sqlDataReader.HasRows)
|
||||
dataTable.Load(sqlDataReader);
|
||||
sqlDataReader.Close();
|
||||
if (dbDataReader.HasRows)
|
||||
dataTable.Load(dbDataReader);
|
||||
dbDataReader.Close();
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
public void Save(DataTable dataTable)
|
||||
{
|
||||
if (SqlUserIsReadOnly())
|
||||
if (DbUserIsReadOnly())
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg,
|
||||
"Trying to save connections but the SQL read only checkbox is checked, aborting!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SqlDatabaseConnector.IsConnected)
|
||||
if (!DatabaseConnector.IsConnected)
|
||||
OpenConnection();
|
||||
using (var sqlBulkCopy = new SqlBulkCopy(SqlDatabaseConnector.SqlConnection))
|
||||
if (DatabaseConnector.GetType() == typeof(MSSqlDatabaseConnector))
|
||||
{
|
||||
foreach (DataColumn col in dataTable.Columns)
|
||||
sqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
|
||||
sqlBulkCopy.DestinationTableName = "dbo.tblCons";
|
||||
sqlBulkCopy.WriteToServer(dataTable);
|
||||
using (var sqlBulkCopy = new SqlBulkCopy((SqlConnection)DatabaseConnector.DbConnection()))
|
||||
{
|
||||
foreach (DataColumn col in dataTable.Columns)
|
||||
sqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
|
||||
sqlBulkCopy.DestinationTableName = "dbo.tblCons";
|
||||
sqlBulkCopy.WriteToServer(dataTable);
|
||||
}
|
||||
|
||||
}
|
||||
else if (DatabaseConnector.GetType() == typeof(MySqlDatabaseConnector))
|
||||
{
|
||||
var dbConnection = (MySqlConnection) DatabaseConnector.DbConnection();
|
||||
using (MySqlTransaction transaction = dbConnection.BeginTransaction(System.Data.IsolationLevel.Serializable))
|
||||
{
|
||||
using (MySqlCommand sqlCommand = new MySqlCommand())
|
||||
{
|
||||
sqlCommand.Connection = dbConnection;
|
||||
sqlCommand.Transaction = transaction;
|
||||
sqlCommand.CommandText = "SELECT * FROM tblCons";
|
||||
using (MySqlDataAdapter dataAdapter = new MySqlDataAdapter(sqlCommand))
|
||||
{
|
||||
dataAdapter.UpdateBatchSize = 1000;
|
||||
using (MySqlCommandBuilder cb = new MySqlCommandBuilder(dataAdapter))
|
||||
{
|
||||
dataAdapter.Update(dataTable);
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection()
|
||||
{
|
||||
SqlDatabaseConnector.Connect();
|
||||
DatabaseConnector.Connect();
|
||||
}
|
||||
|
||||
public void CloseConnection()
|
||||
{
|
||||
SqlDatabaseConnector.Disconnect();
|
||||
DatabaseConnector.Disconnect();
|
||||
}
|
||||
|
||||
private bool SqlUserIsReadOnly()
|
||||
private bool DbUserIsReadOnly()
|
||||
{
|
||||
return mRemoteNG.Settings.Default.SQLReadOnly;
|
||||
}
|
||||
|
||||
@@ -7,18 +7,19 @@ namespace mRemoteNG.Config.DatabaseConnectors
|
||||
/// <summary>
|
||||
/// A helper class for testing database connectivity
|
||||
/// </summary>
|
||||
public class SqlDatabaseConnectionTester
|
||||
public class DatabaseConnectionTester
|
||||
{
|
||||
public async Task<ConnectionTestResult> TestConnectivity(string server,
|
||||
public async Task<ConnectionTestResult> TestConnectivity(string type,
|
||||
string server,
|
||||
string database,
|
||||
string username,
|
||||
string password)
|
||||
{
|
||||
using (var sqlConnector = new SqlDatabaseConnector(server, database, username, password))
|
||||
using (var dbConnector = DatabaseConnectorFactory.DatabaseConnector(type, server, database, username, password))
|
||||
{
|
||||
try
|
||||
{
|
||||
await sqlConnector.ConnectAsync();
|
||||
await dbConnector.ConnectAsync();
|
||||
return ConnectionTestResult.ConnectionSucceded;
|
||||
}
|
||||
catch (SqlException sqlException)
|
||||
@@ -5,14 +5,28 @@ namespace mRemoteNG.Config.DatabaseConnectors
|
||||
{
|
||||
public class DatabaseConnectorFactory
|
||||
{
|
||||
public static SqlDatabaseConnector SqlDatabaseConnectorFromSettings()
|
||||
public static IDatabaseConnector DatabaseConnectorFromSettings()
|
||||
{
|
||||
var sqlType = mRemoteNG.Settings.Default.SQLServerType;
|
||||
var sqlHost = mRemoteNG.Settings.Default.SQLHost;
|
||||
var sqlCatalog = mRemoteNG.Settings.Default.SQLDatabaseName;
|
||||
var sqlUsername = mRemoteNG.Settings.Default.SQLUser;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
var sqlPassword = cryptographyProvider.Decrypt(mRemoteNG.Settings.Default.SQLPass, Runtime.EncryptionKey);
|
||||
return new SqlDatabaseConnector(sqlHost, sqlCatalog, sqlUsername, sqlPassword);
|
||||
|
||||
return DatabaseConnector(sqlType, sqlHost, sqlCatalog, sqlUsername, sqlPassword);
|
||||
}
|
||||
|
||||
public static IDatabaseConnector DatabaseConnector(string type, string server, string database, string username, string password)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "mysql":
|
||||
return new MySqlDatabaseConnector(server, database, username, password);
|
||||
case "mssql":
|
||||
default:
|
||||
return new MSSqlDatabaseConnector(server, database, username, password);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data.Common;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace mRemoteNG.Config.DatabaseConnectors
|
||||
{
|
||||
public interface IDatabaseConnector : IDisposable
|
||||
{
|
||||
DbConnection DbConnection();
|
||||
DbCommand DbCommand(string dbCommand);
|
||||
bool IsConnected { get; }
|
||||
void Connect();
|
||||
Task ConnectAsync();
|
||||
void Disconnect();
|
||||
void AssociateItemToThisConnector(SqlCommand sqlCommand);
|
||||
void AssociateItemToThisConnector(DbCommand dbCommand);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// ReSharper disable ArrangeAccessorOwnerBody
|
||||
|
||||
namespace mRemoteNG.Config.DatabaseConnectors
|
||||
{
|
||||
public class MSSqlDatabaseConnector : IDatabaseConnector
|
||||
{
|
||||
private DbConnection _dbConnection { get; set; } = default(SqlConnection);
|
||||
private string _dbConnectionString = "";
|
||||
private readonly string _dbHost;
|
||||
private readonly string _dbCatalog;
|
||||
private readonly string _dbUsername;
|
||||
private readonly string _dbPassword;
|
||||
|
||||
public DbConnection DbConnection()
|
||||
{
|
||||
return _dbConnection;
|
||||
}
|
||||
|
||||
public DbCommand DbCommand(string dbCommand)
|
||||
{
|
||||
return new SqlCommand(dbCommand, (SqlConnection) _dbConnection);
|
||||
}
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return (_dbConnection.State == ConnectionState.Open); }
|
||||
}
|
||||
|
||||
public MSSqlDatabaseConnector(string sqlServer, string catalog, string username, string password)
|
||||
{
|
||||
_dbHost = sqlServer;
|
||||
_dbCatalog = catalog;
|
||||
_dbUsername = username;
|
||||
_dbPassword = password;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
BuildSqlConnectionString();
|
||||
_dbConnection = new SqlConnection(_dbConnectionString);
|
||||
}
|
||||
|
||||
private void BuildSqlConnectionString()
|
||||
{
|
||||
if (_dbUsername != "")
|
||||
BuildDbConnectionStringWithCustomCredentials();
|
||||
else
|
||||
BuildDbConnectionStringWithDefaultCredentials();
|
||||
}
|
||||
|
||||
private void BuildDbConnectionStringWithCustomCredentials()
|
||||
{
|
||||
_dbConnectionString = $"Data Source={_dbHost};Initial Catalog={_dbCatalog};User Id={_dbUsername};Password={_dbPassword}";
|
||||
}
|
||||
|
||||
private void BuildDbConnectionStringWithDefaultCredentials()
|
||||
{
|
||||
_dbConnectionString = $"Data Source={_dbHost};Initial Catalog={_dbCatalog};Integrated Security=True";
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
_dbConnection.Open();
|
||||
}
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
await _dbConnection.OpenAsync();
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
_dbConnection.Close();
|
||||
}
|
||||
|
||||
public void AssociateItemToThisConnector(DbCommand dbCommand)
|
||||
{
|
||||
dbCommand.Connection = (SqlConnection) _dbConnection;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool itIsSafeToFreeManagedObjects)
|
||||
{
|
||||
if (!itIsSafeToFreeManagedObjects) return;
|
||||
_dbConnection.Close();
|
||||
_dbConnection.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Threading.Tasks;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
// ReSharper disable ArrangeAccessorOwnerBody
|
||||
|
||||
namespace mRemoteNG.Config.DatabaseConnectors
|
||||
{
|
||||
public class MySqlDatabaseConnector : IDatabaseConnector
|
||||
{
|
||||
private DbConnection _dbConnection { get; set; } = default(MySqlConnection);
|
||||
private string _dbConnectionString = "";
|
||||
private readonly string _dbHost;
|
||||
private readonly string _dbPort;
|
||||
private readonly string _dbName;
|
||||
private readonly string _dbUsername;
|
||||
private readonly string _dbPassword;
|
||||
|
||||
public DbConnection DbConnection()
|
||||
{
|
||||
return _dbConnection;
|
||||
}
|
||||
|
||||
public DbCommand DbCommand(string dbCommand)
|
||||
{
|
||||
return new MySqlCommand(dbCommand, (MySqlConnection) _dbConnection);
|
||||
}
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return (_dbConnection.State == ConnectionState.Open); }
|
||||
}
|
||||
|
||||
public MySqlDatabaseConnector(string host, string database, string username, string password)
|
||||
{
|
||||
string[] hostParts = host.Split(new char[]{':'}, 2);
|
||||
_dbHost = hostParts[0];
|
||||
_dbPort = (hostParts.Length == 2)?hostParts[1]:"3306";
|
||||
_dbName = database;
|
||||
_dbUsername = username;
|
||||
_dbPassword = password;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
BuildSqlConnectionString();
|
||||
_dbConnection = new MySqlConnection(_dbConnectionString);
|
||||
}
|
||||
|
||||
private void BuildSqlConnectionString()
|
||||
{
|
||||
_dbConnectionString = $"server={_dbHost};user={_dbUsername};database={_dbName};port={_dbPort};password={_dbPassword}";
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
_dbConnection.Open();
|
||||
}
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
await _dbConnection.OpenAsync();
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
_dbConnection.Close();
|
||||
}
|
||||
|
||||
public void AssociateItemToThisConnector(DbCommand dbCommand)
|
||||
{
|
||||
dbCommand.Connection = (MySqlConnection) _dbConnection;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
private void Dispose(bool itIsSafeToFreeManagedObjects)
|
||||
{
|
||||
if (!itIsSafeToFreeManagedObjects) return;
|
||||
_dbConnection.Close();
|
||||
_dbConnection.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// ReSharper disable ArrangeAccessorOwnerBody
|
||||
|
||||
namespace mRemoteNG.Config.DatabaseConnectors
|
||||
{
|
||||
public class SqlDatabaseConnector : IDatabaseConnector
|
||||
{
|
||||
public SqlConnection SqlConnection { get; private set; } = default(SqlConnection);
|
||||
private string _sqlConnectionString = "";
|
||||
private readonly string _sqlHost;
|
||||
private readonly string _sqlCatalog;
|
||||
private readonly string _sqlUsername;
|
||||
private readonly string _sqlPassword;
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return (SqlConnection.State == ConnectionState.Open); }
|
||||
}
|
||||
|
||||
public SqlDatabaseConnector(string sqlServer, string catalog, string username, string password)
|
||||
{
|
||||
_sqlHost = sqlServer;
|
||||
_sqlCatalog = catalog;
|
||||
_sqlUsername = username;
|
||||
_sqlPassword = password;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
BuildSqlConnectionString();
|
||||
SqlConnection = new SqlConnection(_sqlConnectionString);
|
||||
}
|
||||
|
||||
private void BuildSqlConnectionString()
|
||||
{
|
||||
if (_sqlUsername != "")
|
||||
BuildSqlConnectionStringWithCustomCredentials();
|
||||
else
|
||||
BuildSqlConnectionStringWithDefaultCredentials();
|
||||
}
|
||||
|
||||
private void BuildSqlConnectionStringWithCustomCredentials()
|
||||
{
|
||||
_sqlConnectionString =
|
||||
$"Data Source={_sqlHost};Initial Catalog={_sqlCatalog};User Id={_sqlUsername};Password={_sqlPassword}";
|
||||
}
|
||||
|
||||
private void BuildSqlConnectionStringWithDefaultCredentials()
|
||||
{
|
||||
_sqlConnectionString = $"Data Source={_sqlHost};Initial Catalog={_sqlCatalog};Integrated Security=True";
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
SqlConnection.Open();
|
||||
}
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
await SqlConnection.OpenAsync();
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
SqlConnection.Close();
|
||||
}
|
||||
|
||||
public void AssociateItemToThisConnector(SqlCommand sqlCommand)
|
||||
{
|
||||
sqlCommand.Connection = SqlConnection;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool itIsSafeToFreeManagedObjects)
|
||||
{
|
||||
if (!itIsSafeToFreeManagedObjects) return;
|
||||
SqlConnection.Close();
|
||||
SqlConnection.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlTypes;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
|
||||
@@ -72,7 +71,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
|
||||
dataTable.Columns.Add("ConstantID", typeof(string));
|
||||
dataTable.Columns.Add("PositionID", typeof(int));
|
||||
dataTable.Columns.Add("ParentID", typeof(string));
|
||||
dataTable.Columns.Add("LastChange", typeof(SqlDateTime));
|
||||
dataTable.Columns.Add("LastChange", MiscTools.DBTimeStampType());
|
||||
dataTable.Columns.Add("Name", typeof(string));
|
||||
dataTable.Columns.Add("Type", typeof(string));
|
||||
dataTable.Columns.Add("Expanded", typeof(bool));
|
||||
@@ -215,7 +214,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
|
||||
dataRow["ConstantID"] = connectionInfo.ConstantID;
|
||||
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
|
||||
dataRow["PositionID"] = _currentNodeIndex;
|
||||
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
|
||||
dataRow["LastChange"] = MiscTools.DBTimeStampNow();
|
||||
dataRow["Expanded"] =
|
||||
false; // TODO: this column can eventually be removed. we now save this property locally
|
||||
dataRow["Description"] = connectionInfo.Description;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
@@ -9,28 +9,28 @@ namespace mRemoteNG.Config.Serializers.MsSql
|
||||
{
|
||||
public class SqlDatabaseMetaDataRetriever
|
||||
{
|
||||
public SqlConnectionListMetaData GetDatabaseMetaData(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlConnectionListMetaData GetDatabaseMetaData(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
SqlConnectionListMetaData metaData;
|
||||
SqlDataReader sqlDataReader = null;
|
||||
DbDataReader dbDataReader = null;
|
||||
try
|
||||
{
|
||||
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||
if (!sqlDatabaseConnector.IsConnected)
|
||||
sqlDatabaseConnector.Connect();
|
||||
sqlDataReader = sqlCommand.ExecuteReader();
|
||||
if (!sqlDataReader.HasRows)
|
||||
var dbCommand = databaseConnector.DbCommand("SELECT * FROM tblRoot");
|
||||
if (!databaseConnector.IsConnected)
|
||||
databaseConnector.Connect();
|
||||
dbDataReader = dbCommand.ExecuteReader();
|
||||
if (!dbDataReader.HasRows)
|
||||
return null; // assume new empty database
|
||||
else
|
||||
sqlDataReader.Read();
|
||||
dbDataReader.Read();
|
||||
|
||||
metaData = new SqlConnectionListMetaData
|
||||
{
|
||||
Name = sqlDataReader["Name"] as string ?? "",
|
||||
Protected = sqlDataReader["Protected"] as string ?? "",
|
||||
Export = (bool)sqlDataReader["Export"],
|
||||
Name = dbDataReader["Name"] as string ?? "",
|
||||
Protected = dbDataReader["Protected"] as string ?? "",
|
||||
Export = (bool)dbDataReader["Export"],
|
||||
ConfVersion =
|
||||
new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture))
|
||||
new Version(Convert.ToString(dbDataReader["confVersion"], CultureInfo.InvariantCulture))
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -40,8 +40,8 @@ namespace mRemoteNG.Config.Serializers.MsSql
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sqlDataReader != null && !sqlDataReader.IsClosed)
|
||||
sqlDataReader.Close();
|
||||
if (dbDataReader != null && !dbDataReader.IsClosed)
|
||||
dbDataReader.Close();
|
||||
}
|
||||
|
||||
return metaData;
|
||||
|
||||
@@ -8,14 +8,14 @@ namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlDatabaseVersionVerifier
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlDatabaseVersionVerifier(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlDatabaseVersionVerifier(IDatabaseConnector DatabaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (DatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(DatabaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = DatabaseConnector;
|
||||
}
|
||||
|
||||
public bool VerifyDatabaseVersion(Version dbVersion)
|
||||
@@ -32,11 +32,11 @@ namespace mRemoteNG.Config.Serializers.Versioning
|
||||
|
||||
var dbUpgraders = new IVersionUpgrader[]
|
||||
{
|
||||
new SqlVersion22To23Upgrader(_sqlDatabaseConnector),
|
||||
new SqlVersion23To24Upgrader(_sqlDatabaseConnector),
|
||||
new SqlVersion24To25Upgrader(_sqlDatabaseConnector),
|
||||
new SqlVersion25To26Upgrader(_sqlDatabaseConnector),
|
||||
new SqlVersion26To27Upgrader(_sqlDatabaseConnector),
|
||||
new SqlVersion22To23Upgrader(_databaseConnector),
|
||||
new SqlVersion23To24Upgrader(_databaseConnector),
|
||||
new SqlVersion24To25Upgrader(_databaseConnector),
|
||||
new SqlVersion25To26Upgrader(_databaseConnector),
|
||||
new SqlVersion26To27Upgrader(_databaseConnector),
|
||||
};
|
||||
|
||||
foreach (var upgrader in dbUpgraders)
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlVersion22To23Upgrader : IVersionUpgrader
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlVersion22To23Upgrader(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlVersion22To23Upgrader(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (databaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(databaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public bool CanUpgrade(Version currentVersion)
|
||||
@@ -33,8 +32,8 @@ 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();
|
||||
var dbCommand = _databaseConnector.DbCommand(sqlText);
|
||||
dbCommand.ExecuteNonQuery();
|
||||
|
||||
return new Version(2, 3);
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlVersion23To24Upgrader : IVersionUpgrader
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlVersion23To24Upgrader(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlVersion23To24Upgrader(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (databaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(databaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public bool CanUpgrade(Version currentVersion)
|
||||
@@ -31,8 +30,8 @@ namespace mRemoteNG.Config.Serializers.Versioning
|
||||
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();
|
||||
var dbCommand = _databaseConnector.DbCommand(sqlText);
|
||||
dbCommand.ExecuteNonQuery();
|
||||
|
||||
return new Version(2, 4);
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlVersion24To25Upgrader : IVersionUpgrader
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlVersion24To25Upgrader(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlVersion24To25Upgrader(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (databaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(databaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public bool CanUpgrade(Version currentVersion)
|
||||
@@ -33,8 +32,8 @@ 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();
|
||||
var dbCommand = _databaseConnector.DbCommand(sqlText);
|
||||
dbCommand.ExecuteNonQuery();
|
||||
|
||||
return new Version(2, 5);
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlVersion25To26Upgrader : IVersionUpgrader
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlVersion25To26Upgrader(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlVersion25To26Upgrader(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (databaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(databaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public bool CanUpgrade(Version currentVersion)
|
||||
@@ -37,8 +36,8 @@ ADD RDPMinutesToIdleTimeout int 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();
|
||||
var dbCommand = _databaseConnector.DbCommand(sqlText);
|
||||
dbCommand.ExecuteNonQuery();
|
||||
|
||||
return new Version(2, 6);
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Versioning
|
||||
{
|
||||
public class SqlVersion26To27Upgrader : IVersionUpgrader
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
private readonly IDatabaseConnector _databaseConnector;
|
||||
|
||||
public SqlVersion26To27Upgrader(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
public SqlVersion26To27Upgrader(IDatabaseConnector databaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
if (databaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(databaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
_databaseConnector = databaseConnector;
|
||||
}
|
||||
|
||||
public bool CanUpgrade(Version currentVersion)
|
||||
@@ -33,8 +32,8 @@ ADD RedirectClipboard bit NOT NULL DEFAULT 0,
|
||||
InheritRedirectClipboard bit NOT NULL DEFAULT 0;
|
||||
UPDATE tblRoot
|
||||
SET ConfVersion='2.7'";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
var dbCommand = _databaseConnector.DbCommand(sqlText);
|
||||
dbCommand.ExecuteNonQuery();
|
||||
|
||||
return new Version(2, 7);
|
||||
}
|
||||
|
||||
12
mRemoteV1/Properties/Settings.Designer.cs
generated
12
mRemoteV1/Properties/Settings.Designer.cs
generated
@@ -2794,5 +2794,17 @@ namespace mRemoteNG {
|
||||
this["OverrideFIPSCheck"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("mssql")]
|
||||
public string SQLServerType {
|
||||
get {
|
||||
return ((string)(this["SQLServerType"]));
|
||||
}
|
||||
set {
|
||||
this["SQLServerType"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,5 +697,8 @@
|
||||
<Setting Name="OverrideFIPSCheck" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="SQLServerType" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">mssql</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Data.SqlTypes;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
@@ -9,6 +10,7 @@ using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using mRemoteNG.UI.Window;
|
||||
using MySql.Data.Types;
|
||||
using static System.String;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
@@ -63,13 +65,40 @@ namespace mRemoteNG.Tools
|
||||
|
||||
|
||||
public static string DBDate(DateTime Dt)
|
||||
{
|
||||
var strDate = Dt.Year + LeadingZero(Convert.ToString(Dt.Month)) + LeadingZero(Convert.ToString(Dt.Day)) +
|
||||
" " + LeadingZero(Convert.ToString(Dt.Hour)) + ":" +
|
||||
LeadingZero(Convert.ToString(Dt.Minute)) + ":" + LeadingZero(Convert.ToString(Dt.Second));
|
||||
return strDate;
|
||||
}
|
||||
{
|
||||
switch (Settings.Default.SQLServerType)
|
||||
{
|
||||
case "mysql":
|
||||
return Dt.ToString("yyyy/MM/dd HH:mm:ss");
|
||||
case "mssql":
|
||||
default:
|
||||
return Dt.ToString("yyyyMMdd HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
public static Type DBTimeStampType()
|
||||
{
|
||||
switch (Settings.Default.SQLServerType)
|
||||
{
|
||||
case "mysql":
|
||||
return typeof(MySqlDateTime);
|
||||
case "mssql":
|
||||
default:
|
||||
return typeof(SqlDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
public static object DBTimeStampNow()
|
||||
{
|
||||
switch (Settings.Default.SQLServerType)
|
||||
{
|
||||
case "mysql":
|
||||
return new MySqlDateTime(DateTime.Now);
|
||||
case "mssql":
|
||||
default:
|
||||
return (SqlDateTime)DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
public static string PrepareValueForDB(string Text)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
|
||||
namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
{
|
||||
@@ -28,6 +28,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
[System.Diagnostics.DebuggerStepThrough()]
|
||||
private void InitializeComponent()
|
||||
{
|
||||
// System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SqlServerPage));
|
||||
this.lblSQLDatabaseName = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.txtSQLDatabaseName = new mRemoteNG.UI.Controls.Base.NGTextBox();
|
||||
this.lblExperimental = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
@@ -44,13 +45,15 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
this.lblTestConnectionResults = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.chkSQLReadOnly = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.lblSQLReadOnly = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.lblSQLType = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.txtSQLType = new mRemoteNG.UI.Controls.Base.NGComboBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imgConnectionStatus)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lblSQLDatabaseName
|
||||
//
|
||||
this.lblSQLDatabaseName.Enabled = false;
|
||||
this.lblSQLDatabaseName.Location = new System.Drawing.Point(23, 132);
|
||||
this.lblSQLDatabaseName.Location = new System.Drawing.Point(23, 156);
|
||||
this.lblSQLDatabaseName.Name = "lblSQLDatabaseName";
|
||||
this.lblSQLDatabaseName.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLDatabaseName.TabIndex = 5;
|
||||
@@ -61,7 +64,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
//
|
||||
this.txtSQLDatabaseName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.txtSQLDatabaseName.Enabled = false;
|
||||
this.txtSQLDatabaseName.Location = new System.Drawing.Point(140, 130);
|
||||
this.txtSQLDatabaseName.Location = new System.Drawing.Point(140, 154);
|
||||
this.txtSQLDatabaseName.Name = "txtSQLDatabaseName";
|
||||
this.txtSQLDatabaseName.Size = new System.Drawing.Size(153, 22);
|
||||
this.txtSQLDatabaseName.TabIndex = 6;
|
||||
@@ -96,7 +99,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// lblSQLUsername
|
||||
//
|
||||
this.lblSQLUsername.Enabled = false;
|
||||
this.lblSQLUsername.Location = new System.Drawing.Point(23, 158);
|
||||
this.lblSQLUsername.Location = new System.Drawing.Point(23, 182);
|
||||
this.lblSQLUsername.Name = "lblSQLUsername";
|
||||
this.lblSQLUsername.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLUsername.TabIndex = 7;
|
||||
@@ -107,7 +110,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
//
|
||||
this.txtSQLPassword.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.txtSQLPassword.Enabled = false;
|
||||
this.txtSQLPassword.Location = new System.Drawing.Point(140, 182);
|
||||
this.txtSQLPassword.Location = new System.Drawing.Point(140, 206);
|
||||
this.txtSQLPassword.Name = "txtSQLPassword";
|
||||
this.txtSQLPassword.Size = new System.Drawing.Size(153, 22);
|
||||
this.txtSQLPassword.TabIndex = 10;
|
||||
@@ -130,7 +133,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// lblSQLServer
|
||||
//
|
||||
this.lblSQLServer.Enabled = false;
|
||||
this.lblSQLServer.Location = new System.Drawing.Point(23, 106);
|
||||
this.lblSQLServer.Location = new System.Drawing.Point(23, 130);
|
||||
this.lblSQLServer.Name = "lblSQLServer";
|
||||
this.lblSQLServer.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLServer.TabIndex = 3;
|
||||
@@ -141,7 +144,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
//
|
||||
this.txtSQLUsername.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.txtSQLUsername.Enabled = false;
|
||||
this.txtSQLUsername.Location = new System.Drawing.Point(140, 156);
|
||||
this.txtSQLUsername.Location = new System.Drawing.Point(140, 180);
|
||||
this.txtSQLUsername.Name = "txtSQLUsername";
|
||||
this.txtSQLUsername.Size = new System.Drawing.Size(153, 22);
|
||||
this.txtSQLUsername.TabIndex = 8;
|
||||
@@ -150,7 +153,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
//
|
||||
this.txtSQLServer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.txtSQLServer.Enabled = false;
|
||||
this.txtSQLServer.Location = new System.Drawing.Point(140, 103);
|
||||
this.txtSQLServer.Location = new System.Drawing.Point(140, 128);
|
||||
this.txtSQLServer.Name = "txtSQLServer";
|
||||
this.txtSQLServer.Size = new System.Drawing.Size(153, 22);
|
||||
this.txtSQLServer.TabIndex = 4;
|
||||
@@ -158,7 +161,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// lblSQLPassword
|
||||
//
|
||||
this.lblSQLPassword.Enabled = false;
|
||||
this.lblSQLPassword.Location = new System.Drawing.Point(23, 184);
|
||||
this.lblSQLPassword.Location = new System.Drawing.Point(23, 208);
|
||||
this.lblSQLPassword.Name = "lblSQLPassword";
|
||||
this.lblSQLPassword.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLPassword.TabIndex = 9;
|
||||
@@ -169,7 +172,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
//
|
||||
this.btnTestConnection._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
|
||||
this.btnTestConnection.Enabled = false;
|
||||
this.btnTestConnection.Location = new System.Drawing.Point(140, 228);
|
||||
this.btnTestConnection.Location = new System.Drawing.Point(140, 252);
|
||||
this.btnTestConnection.Name = "btnTestConnection";
|
||||
this.btnTestConnection.Size = new System.Drawing.Size(153, 23);
|
||||
this.btnTestConnection.TabIndex = 11;
|
||||
@@ -180,7 +183,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// imgConnectionStatus
|
||||
//
|
||||
this.imgConnectionStatus.Image = global::mRemoteNG.Resources.Help;
|
||||
this.imgConnectionStatus.Location = new System.Drawing.Point(297, 231);
|
||||
this.imgConnectionStatus.Location = new System.Drawing.Point(297, 255);
|
||||
this.imgConnectionStatus.Name = "imgConnectionStatus";
|
||||
this.imgConnectionStatus.Size = new System.Drawing.Size(16, 16);
|
||||
this.imgConnectionStatus.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
|
||||
@@ -190,7 +193,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// lblTestConnectionResults
|
||||
//
|
||||
this.lblTestConnectionResults.AutoSize = true;
|
||||
this.lblTestConnectionResults.Location = new System.Drawing.Point(137, 254);
|
||||
this.lblTestConnectionResults.Location = new System.Drawing.Point(137, 278);
|
||||
this.lblTestConnectionResults.Name = "lblTestConnectionResults";
|
||||
this.lblTestConnectionResults.Size = new System.Drawing.Size(124, 13);
|
||||
this.lblTestConnectionResults.TabIndex = 13;
|
||||
@@ -201,7 +204,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
this.chkSQLReadOnly._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkSQLReadOnly.AutoSize = true;
|
||||
this.chkSQLReadOnly.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.chkSQLReadOnly.Location = new System.Drawing.Point(140, 208);
|
||||
this.chkSQLReadOnly.Location = new System.Drawing.Point(140, 232);
|
||||
this.chkSQLReadOnly.Name = "chkSQLReadOnly";
|
||||
this.chkSQLReadOnly.Size = new System.Drawing.Size(15, 14);
|
||||
this.chkSQLReadOnly.TabIndex = 14;
|
||||
@@ -210,17 +213,42 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
// lblSQLReadOnly
|
||||
//
|
||||
this.lblSQLReadOnly.Enabled = false;
|
||||
this.lblSQLReadOnly.Location = new System.Drawing.Point(23, 208);
|
||||
this.lblSQLReadOnly.Location = new System.Drawing.Point(23, 232);
|
||||
this.lblSQLReadOnly.Name = "lblSQLReadOnly";
|
||||
this.lblSQLReadOnly.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLReadOnly.TabIndex = 15;
|
||||
this.lblSQLReadOnly.Text = "Read Only:";
|
||||
this.lblSQLReadOnly.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// lblSQLType
|
||||
//
|
||||
this.lblSQLType.Enabled = false;
|
||||
this.lblSQLType.Location = new System.Drawing.Point(23, 106);
|
||||
this.lblSQLType.Name = "lblSQLType";
|
||||
this.lblSQLType.Size = new System.Drawing.Size(111, 13);
|
||||
this.lblSQLType.TabIndex = 20;
|
||||
this.lblSQLType.Text = "SQL Server Type:";
|
||||
this.lblSQLType.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// txtSQLType
|
||||
//
|
||||
this.txtSQLType._mice = mRemoteNG.UI.Controls.Base.NGComboBox.MouseState.HOVER;
|
||||
this.txtSQLType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.txtSQLType.FormattingEnabled = true;
|
||||
this.txtSQLType.Items.AddRange(new object[] {
|
||||
"mssql",
|
||||
"mysql"});
|
||||
this.txtSQLType.Location = new System.Drawing.Point(140, 102);
|
||||
this.txtSQLType.Name = "txtSQLType";
|
||||
this.txtSQLType.Size = new System.Drawing.Size(153, 21);
|
||||
this.txtSQLType.TabIndex = 21;
|
||||
//
|
||||
// SqlServerPage
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.Controls.Add(this.txtSQLType);
|
||||
this.Controls.Add(this.lblSQLType);
|
||||
this.Controls.Add(this.lblSQLReadOnly);
|
||||
this.Controls.Add(this.chkSQLReadOnly);
|
||||
this.Controls.Add(this.lblTestConnectionResults);
|
||||
@@ -243,7 +271,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
((System.ComponentModel.ISupportInitialize)(this.imgConnectionStatus)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
internal Controls.Base.NGLabel lblSQLDatabaseName;
|
||||
internal Controls.Base.NGTextBox txtSQLDatabaseName;
|
||||
@@ -262,5 +289,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
private Controls.Base.NGLabel lblTestConnectionResults;
|
||||
private Controls.Base.NGCheckBox chkSQLReadOnly;
|
||||
internal Controls.Base.NGLabel lblSQLReadOnly;
|
||||
internal Controls.Base.NGLabel lblSQLType;
|
||||
private Controls.Base.NGComboBox txtSQLType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.Connections.Multiuser;
|
||||
@@ -9,14 +9,14 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
{
|
||||
public sealed partial class SqlServerPage
|
||||
{
|
||||
private readonly SqlDatabaseConnectionTester _databaseConnectionTester;
|
||||
private readonly DatabaseConnectionTester _databaseConnectionTester;
|
||||
|
||||
public SqlServerPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
ApplyTheme();
|
||||
PageIcon = Resources.Database_Icon;
|
||||
_databaseConnectionTester = new SqlDatabaseConnectionTester();
|
||||
_databaseConnectionTester = new DatabaseConnectionTester();
|
||||
}
|
||||
|
||||
public override string PageName
|
||||
@@ -44,6 +44,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
public override void LoadSettings()
|
||||
{
|
||||
chkUseSQLServer.Checked = Settings.Default.UseSQLServer;
|
||||
txtSQLType.Text = Settings.Default.SQLServerType;
|
||||
txtSQLServer.Text = Settings.Default.SQLHost;
|
||||
txtSQLDatabaseName.Text = Settings.Default.SQLDatabaseName;
|
||||
txtSQLUsername.Text = Settings.Default.SQLUser;
|
||||
@@ -59,6 +60,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
var sqlServerWasPreviouslyEnabled = Settings.Default.UseSQLServer;
|
||||
|
||||
Settings.Default.UseSQLServer = chkUseSQLServer.Checked;
|
||||
Settings.Default.SQLServerType = txtSQLType.Text;
|
||||
Settings.Default.SQLHost = txtSQLServer.Text;
|
||||
Settings.Default.SQLDatabaseName = txtSQLDatabaseName.Text;
|
||||
Settings.Default.SQLUser = txtSQLUsername.Text;
|
||||
@@ -94,11 +96,13 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
|
||||
private void toggleSQLPageControls(bool useSQLServer)
|
||||
{
|
||||
lblSQLType.Enabled = useSQLServer;
|
||||
lblSQLServer.Enabled = useSQLServer;
|
||||
lblSQLDatabaseName.Enabled = useSQLServer;
|
||||
lblSQLUsername.Enabled = useSQLServer;
|
||||
lblSQLPassword.Enabled = useSQLServer;
|
||||
lblSQLReadOnly.Enabled = useSQLServer;
|
||||
txtSQLType.Enabled = useSQLServer;
|
||||
txtSQLServer.Enabled = useSQLServer;
|
||||
txtSQLDatabaseName.Enabled = useSQLServer;
|
||||
txtSQLUsername.Enabled = useSQLServer;
|
||||
@@ -109,6 +113,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
|
||||
private async void btnTestConnection_Click(object sender, EventArgs e)
|
||||
{
|
||||
var type = txtSQLType.Text;
|
||||
var server = txtSQLServer.Text;
|
||||
var database = txtSQLDatabaseName.Text;
|
||||
var username = txtSQLUsername.Text;
|
||||
@@ -119,7 +124,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
btnTestConnection.Enabled = false;
|
||||
|
||||
var connectionTestResult =
|
||||
await _databaseConnectionTester.TestConnectivity(server, database, username, password);
|
||||
await _databaseConnectionTester.TestConnectivity(type, server, database, username, password);
|
||||
|
||||
btnTestConnection.Enabled = true;
|
||||
|
||||
|
||||
@@ -729,6 +729,9 @@
|
||||
<setting name="OverrideFIPSCheck" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="SQLServerType" serializeAs="String">
|
||||
<value>mssql</value>
|
||||
</setting>
|
||||
</mRemoteNG.Settings>
|
||||
</userSettings>
|
||||
<applicationSettings>
|
||||
|
||||
@@ -62,7 +62,11 @@
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="MySql.Data, Version=8.0.13.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.8.0.13\lib\net452\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ObjectListView, Version=2.9.1.1072, Culture=neutral, PublicKeyToken=b1c5bf581481bcd4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ObjectListView.Official.2.9.1\lib\net20\ObjectListView.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -70,12 +74,17 @@
|
||||
<HintPath>..\packages\SSH.NET.2016.1.0\lib\net40\Renci.SshNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Drawing.Design" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
@@ -148,7 +157,8 @@
|
||||
<Compile Include="Config\CredentialRepositoryListSaver.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\ConnectionTestResult.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\DatabaseConnectorFactory.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\SqlDatabaseConnectionTester.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\DatabaseConnectionTester.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\MSSqlDatabaseConnector.cs" />
|
||||
<Compile Include="Config\DataProviders\FileBackupCreator.cs" />
|
||||
<Compile Include="Config\DataProviders\FileBackupPruner.cs" />
|
||||
<Compile Include="Config\DataProviders\InMemoryStringDataProvider.cs" />
|
||||
@@ -223,7 +233,7 @@
|
||||
<Compile Include="Config\Putty\PuttySessionsManager.cs" />
|
||||
<Compile Include="Config\Putty\AbstractPuttySessionsProvider.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\IDatabaseConnector.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\SqlDatabaseConnector.cs" />
|
||||
<Compile Include="Config\DatabaseConnectors\MySqlDatabaseConnector.cs" />
|
||||
<Compile Include="Connection\AbstractConnectionRecord.cs" />
|
||||
<Compile Include="Connection\ConnectionInfoComparer.cs" />
|
||||
<Compile Include="Connection\ConnectionInfoInheritance.cs" />
|
||||
@@ -902,6 +912,7 @@
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UI\Forms\OptionsPages\SqlServerPage.resx">
|
||||
<DependentUpon>SqlServerPage.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UI\Forms\OptionsPages\StartupExitPage.resx">
|
||||
<DependentUpon>StartupExitPage.cs</DependentUpon>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<package id="DockPanelSuite.ThemeVS2015" version="3.0.6" targetFramework="net46" />
|
||||
<package id="Geckofx45" version="45.0.32" targetFramework="net46" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net46" />
|
||||
<package id="MySql.Data" version="8.0.13" targetFramework="net46" />
|
||||
<package id="ObjectListView.Official" version="2.9.1" targetFramework="net46" />
|
||||
<package id="SSH.NET" version="2016.1.0" targetFramework="net46" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user