mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
Merge branch 'develop' into improve_credential_manager
This commit is contained in:
@@ -6,15 +6,17 @@ Added more logging/notifications options
|
||||
|
||||
|
||||
|
||||
1.75 RC1 (2017-01-27):
|
||||
1.75 (2017-03-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
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)
|
||||
Added Release Channels to the update check functionality allowing users to select one of 3 release channels for updates: Stable, Beta, Dev
|
||||
#360: Help -> About, Version # is now selectable/copyable
|
||||
#221: RDP: Optional disconnect after X number of minutes of inactivity
|
||||
|
||||
@@ -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
|
||||
@@ -37,14 +37,14 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
[Test]
|
||||
public void XDocumentHasXmlDeclaration()
|
||||
{
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false, false);
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false);
|
||||
Assert.That(xdoc.Declaration, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentHasRootConnectionElement()
|
||||
{
|
||||
var xdoc =_documentCompiler.CompileDocument(_connectionTreeModel, false, false);
|
||||
var xdoc =_documentCompiler.CompileDocument(_connectionTreeModel, false);
|
||||
var rootElementName = xdoc.Root?.Name.LocalName;
|
||||
Assert.That(rootElementName, Is.EqualTo("Connections"));
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
[Test]
|
||||
public void ConnectionNodesSerializedRecursively()
|
||||
{
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false, false);
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false);
|
||||
var con4 = xdoc.Root?.XPathSelectElement("Node[@Name='folder2']/Node[@Name='folder3']/Node[@Name='con4']");
|
||||
Assert.That(con4, Is.Not.Null);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
[Test]
|
||||
public void XmlContentEncryptedWhenFullFileEncryptionTurnedOn()
|
||||
{
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, true, false);
|
||||
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, true);
|
||||
var rootElementValue = xdoc.Root?.Value;
|
||||
Assert.That(rootElementValue, Is.Not.EqualTo(string.Empty));
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
var connectionTreeModel = SetupConnectionTreeModel();
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptoProvider, connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString());
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, connectionNodeSerializer).CompileDocument(connectionTreeModel, false, false);
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, connectionNodeSerializer).CompileDocument(connectionTreeModel, false);
|
||||
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,15 +39,6 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
Assert.That(attributeValue, Is.EqualTo("Connections"));
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void ExportValueSerialized(bool export)
|
||||
{
|
||||
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, export:export);
|
||||
var attributeValue = element.Attribute(XName.Get("Export"))?.Value;
|
||||
Assert.That(attributeValue, Is.EqualTo(export.ToString()));
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(TestCaseSources), nameof(TestCaseSources.AllEngineAndModeCombos))]
|
||||
public void EncryptionEngineSerialized(BlockCipherEngines engine, BlockCipherModes mode)
|
||||
{
|
||||
@@ -100,23 +91,13 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
Assert.That(attributeValuePlainText, Is.EqualTo(expectedPlainText));
|
||||
}
|
||||
|
||||
[TestCase("", "ThisIsNotProtected")]
|
||||
[TestCase("customPassword1", "ThisIsNotProtected")]
|
||||
public void EncryptWithDefaultPasswordWhenExporting(string customPassword, string expectedPlainText)
|
||||
{
|
||||
_rootNodeInfo.PasswordString = customPassword;
|
||||
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, export:true);
|
||||
var attributeValue = element.Attribute(XName.Get("Protected"))?.Value;
|
||||
var attributeValuePlainText = _cryptographyProvider.Decrypt(attributeValue, _rootNodeInfo.DefaultPassword.ConvertToSecureString());
|
||||
Assert.That(attributeValuePlainText, Is.EqualTo(expectedPlainText));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConfVersionSerialized()
|
||||
{
|
||||
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider);
|
||||
var attributeValue = element.Attribute(XName.Get("ConfVersion"))?.Value;
|
||||
Assert.That(attributeValue, Is.EqualTo("2.7"));
|
||||
var attributeValue = element.Attribute(XName.Get("ConfVersion"))?.Value ?? "";
|
||||
var versionAsNumber = double.Parse(attributeValue);
|
||||
Assert.That(versionAsNumber, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
private class TestCaseSources
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
@@ -79,12 +78,16 @@ namespace mRemoteNG.App
|
||||
cryptographyProvider.KeyDerivationIterations = Settings.Default.EncryptionKeyDerivationIterations;
|
||||
var rootNode = exportTarget.GetRootParent() as RootNodeInfo;
|
||||
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptographyProvider, rootNode?.PasswordString.ConvertToSecureString() ?? new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString());
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer);
|
||||
((XmlConnectionsSerializer) serializer).SaveFilter = saveFilter;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -453,7 +453,6 @@ namespace mRemoteNG.App
|
||||
if (!Settings.Default.UseSQLServer)
|
||||
connectionsSaver.ConnectionFileName = GetStartupConnectionFileName();
|
||||
|
||||
connectionsSaver.Export = false;
|
||||
connectionsSaver.SaveFilter = new SaveFilter();
|
||||
connectionsSaver.ConnectionTreeModel = ConnectionTreeModel;
|
||||
|
||||
@@ -507,7 +506,6 @@ namespace mRemoteNG.App
|
||||
|
||||
connectionsSave.SaveFormat = ConnectionsSaver.Format.mRXML;
|
||||
connectionsSave.ConnectionFileName = saveFileDialog.FileName;
|
||||
connectionsSave.Export = false;
|
||||
connectionsSave.SaveFilter = new SaveFilter();
|
||||
connectionsSave.ConnectionTreeModel = ConnectionTreeModel;
|
||||
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace mRemoteNG.Config.Connections
|
||||
|
||||
public string ConnectionFileName {get; set;}
|
||||
public TreeNode RootTreeNode {get; set;}
|
||||
public bool Export {get; set;}
|
||||
public Format SaveFormat {get; set;}
|
||||
public SaveFilter SaveFilter {get; set;}
|
||||
public ConnectionTreeModel ConnectionTreeModel { get; set; }
|
||||
@@ -72,8 +71,7 @@ namespace mRemoteNG.Config.Connections
|
||||
break;
|
||||
default:
|
||||
SaveToXml();
|
||||
if (!Export)
|
||||
FrmMain.Default.ConnectionsFileName = ConnectionFileName;
|
||||
FrmMain.Default.ConnectionsFileName = ConnectionFileName;
|
||||
break;
|
||||
}
|
||||
FrmMain.Default.AreWeUsingSqlServerForSavingConnections = SaveFormat == Format.SQL;
|
||||
@@ -248,7 +246,6 @@ namespace mRemoteNG.Config.Connections
|
||||
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptographyProvider, ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString());
|
||||
var xmlConnectionsSerializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer)
|
||||
{
|
||||
Export = Export,
|
||||
SaveFilter = SaveFilter,
|
||||
UseFullEncryption = mRemoteNG.Settings.Default.EncryptCompleteConnectionsFile
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
private XmlConnectionsDecryptor _decryptor;
|
||||
//TODO find way to inject data source info
|
||||
private string ConnectionFileName = "";
|
||||
private const double MaxSupportedConfVersion = 2.7;
|
||||
private const double MaxSupportedConfVersion = 2.8;
|
||||
private readonly RootNodeInfo _rootNodeInfo = new RootNodeInfo(RootNodeType.Connection);
|
||||
private readonly IEnumerable<ICredentialRecord> _credentialRecords;
|
||||
|
||||
@@ -123,12 +123,6 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
}
|
||||
|
||||
if (import && !IsExportFile(rootXmlElement))
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strCannotImportNormalSessionFile);
|
||||
return null;
|
||||
}
|
||||
|
||||
AddNodesFromXmlRecursive(_xmlDocument.DocumentElement, _rootNodeInfo);
|
||||
|
||||
if (!import)
|
||||
@@ -529,14 +523,5 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
return connectionInfo;
|
||||
}
|
||||
|
||||
private bool IsExportFile(XmlElement rootConnectionsNode)
|
||||
{
|
||||
var isExportFile = false;
|
||||
if (_confVersion < 1.0) return false;
|
||||
if (Convert.ToBoolean(rootConnectionsNode.Attributes["Export"].Value))
|
||||
isExportFile = true;
|
||||
return isExportFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,17 +22,17 @@ namespace mRemoteNG.Config.Serializers
|
||||
_connectionNodeSerializer = connectionNodeSerializer;
|
||||
}
|
||||
|
||||
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
|
||||
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption)
|
||||
{
|
||||
var rootNodeInfo = GetRootNodeFromConnectionTreeModel(connectionTreeModel);
|
||||
return CompileDocument(rootNodeInfo, fullFileEncryption, export);
|
||||
return CompileDocument(rootNodeInfo, fullFileEncryption);
|
||||
}
|
||||
|
||||
public XDocument CompileDocument(ConnectionInfo serializationTarget, bool fullFileEncryption, bool export)
|
||||
public XDocument CompileDocument(ConnectionInfo serializationTarget, bool fullFileEncryption)
|
||||
{
|
||||
var rootNodeInfo = GetRootNodeFromConnectionInfo(serializationTarget);
|
||||
_encryptionKey = rootNodeInfo.PasswordString.ConvertToSecureString();
|
||||
var rootElement = CompileRootNode(rootNodeInfo, fullFileEncryption, export);
|
||||
var rootElement = CompileRootNode(rootNodeInfo, fullFileEncryption);
|
||||
|
||||
CompileRecursive(serializationTarget, rootElement);
|
||||
var xmlDeclaration = new XDeclaration("1.0", "utf-8", null);
|
||||
@@ -71,10 +71,10 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
}
|
||||
|
||||
private XElement CompileRootNode(RootNodeInfo rootNodeInfo, bool fullFileEncryption, bool export)
|
||||
private XElement CompileRootNode(RootNodeInfo rootNodeInfo, bool fullFileEncryption)
|
||||
{
|
||||
var rootNodeSerializer = new XmlRootNodeSerializer();
|
||||
return rootNodeSerializer.SerializeRootNodeInfo(rootNodeInfo, _cryptographyProvider, fullFileEncryption, export);
|
||||
return rootNodeSerializer.SerializeRootNodeInfo(rootNodeInfo, _cryptographyProvider, fullFileEncryption);
|
||||
}
|
||||
|
||||
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace mRemoteNG.Config.Serializers
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer;
|
||||
|
||||
public bool Export { get; set; }
|
||||
public SaveFilter SaveFilter { get; set; } = new SaveFilter();
|
||||
public bool UseFullEncryption { get; set; }
|
||||
|
||||
@@ -44,7 +43,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
try
|
||||
{
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, _connectionNodeSerializer);
|
||||
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
|
||||
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption);
|
||||
xml = WriteXmlToString(xmlDocument);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -7,27 +7,24 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
public class XmlRootNodeSerializer
|
||||
{
|
||||
public XElement SerializeRootNodeInfo(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool fullFileEncryption = false, bool export = false)
|
||||
public XElement SerializeRootNodeInfo(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool fullFileEncryption = false)
|
||||
{
|
||||
var element = new XElement("Connections");
|
||||
element.Add(new XAttribute(XName.Get("Name"), rootNodeInfo.Name));
|
||||
element.Add(new XAttribute(XName.Get("Export"), export.ToString()));
|
||||
element.Add(new XAttribute(XName.Get("EncryptionEngine"), cryptographyProvider.CipherEngine));
|
||||
element.Add(new XAttribute(XName.Get("BlockCipherMode"), cryptographyProvider.CipherMode));
|
||||
element.Add(new XAttribute(XName.Get("KdfIterations"), cryptographyProvider.KeyDerivationIterations));
|
||||
element.Add(new XAttribute(XName.Get("FullFileEncryption"), fullFileEncryption.ToString()));
|
||||
element.Add(CreateProtectedAttribute(rootNodeInfo, cryptographyProvider, export));
|
||||
element.Add(new XAttribute(XName.Get("ConfVersion"), "2.7"));
|
||||
element.Add(CreateProtectedAttribute(rootNodeInfo, cryptographyProvider));
|
||||
element.Add(new XAttribute(XName.Get("ConfVersion"), "2.8"));
|
||||
return element;
|
||||
}
|
||||
|
||||
private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool export)
|
||||
private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider)
|
||||
{
|
||||
var attribute = new XAttribute(XName.Get("Protected"), "");
|
||||
var plainText = rootNodeInfo.Password && !export ? "ThisIsProtected" : "ThisIsNotProtected";
|
||||
var encryptionPassword = export
|
||||
? rootNodeInfo.DefaultPassword.ConvertToSecureString()
|
||||
: rootNodeInfo.PasswordString.ConvertToSecureString();
|
||||
var plainText = rootNodeInfo.Password ? "ThisIsProtected" : "ThisIsNotProtected";
|
||||
var encryptionPassword = rootNodeInfo.PasswordString.ConvertToSecureString();
|
||||
attribute.Value = cryptographyProvider.Encrypt(plainText, encryptionPassword);
|
||||
return attribute;
|
||||
}
|
||||
|
||||
141
mRemoteV1/Schemas/mremoteng_confcons_v2_8.xsd
Normal file
141
mRemoteV1/Schemas/mremoteng_confcons_v2_8.xsd
Normal file
@@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema id="mremoteng_confcons_v2_8"
|
||||
targetNamespace="http://mremoteng.org"
|
||||
elementFormDefault="qualified"
|
||||
xmlns="http://mremoteng.org"
|
||||
xmlns:mrng="http://mremoteng.org"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
>
|
||||
|
||||
|
||||
<xs:element name="Connections">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Node" type="mrng:connectioninfo" />
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Name" type="xs:string" use="required" />
|
||||
<xs:attribute name="EncryptionEngine" type="xs:string" use="required" />
|
||||
<xs:attribute name="BlockCipherMode" type="xs:string" use="required" />
|
||||
<xs:attribute name="KdfIterations" type="xs:int" use="optional" />
|
||||
<xs:attribute name="FullFileEncryption" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="Protected" type="xs:string" use="required" />
|
||||
<xs:attribute name="ConfVersion" type="xs:float" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<xs:complexType name="connectioninfo">
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="Node" type="mrng:connectioninfo" />
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Name" type="xs:string" use="required" />
|
||||
<xs:attribute name="Type" type="xs:string" use="required" />
|
||||
<xs:attribute name="Descr" type="xs:string" use="required" />
|
||||
<xs:attribute name="Icon" type="xs:string" use="required" />
|
||||
<xs:attribute name="Panel" type="xs:string" use="required" />
|
||||
<xs:attribute name="CredentialId" type="xs:string" use="required" />
|
||||
<xs:attribute name="Hostname" type="xs:string" use="required" />
|
||||
<xs:attribute name="Protocol" type="xs:string" use="required" />
|
||||
<xs:attribute name="PuttySession" type="xs:string" use="required" />
|
||||
<xs:attribute name="Port" type="xs:int" use="required" />
|
||||
<xs:attribute name="ConnectToConsole" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="UseCredSsp" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RenderingEngine" type="xs:string" use="required" />
|
||||
<xs:attribute name="ICAEncryptionStrength" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDPAuthenticationLevel" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDPMinutesToIdleTimeout" type="xs:int" use="required" />
|
||||
<xs:attribute name="LoadBalanceInfo" type="xs:string" use="required" />
|
||||
<xs:attribute name="Colors" type="xs:string" use="required" />
|
||||
<xs:attribute name="Resolution" type="xs:string" use="required" />
|
||||
<xs:attribute name="AutomaticResize" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="DisplayWallpaper" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="DisplayThemes" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="EnableFontSmoothing" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="EnableDesktopComposition" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="CacheBitmaps" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RedirectDiskDrives" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RedirectPorts" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RedirectPrinters" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RedirectSmartCards" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RedirectSound" type="xs:string" use="required" />
|
||||
<xs:attribute name="SoundQuality" type="xs:string" use="required" />
|
||||
<xs:attribute name="RedirectKeys" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="Connected" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="PreExtApp" type="xs:string" use="required" />
|
||||
<xs:attribute name="PostExtApp" type="xs:string" use="required" />
|
||||
<xs:attribute name="MacAddress" type="xs:string" use="required" />
|
||||
<xs:attribute name="UserField" type="xs:string" use="required" />
|
||||
<xs:attribute name="ExtApp" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCCompression" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCEncoding" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCAuthMode" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCProxyType" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCProxyIP" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCProxyPort" type="xs:int" use="required" />
|
||||
<xs:attribute name="VNCProxyUsername" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCProxyPassword" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCColors" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCSmartSizeMode" type="xs:string" use="required" />
|
||||
<xs:attribute name="VNCViewOnly" type="xs:boolean" use="required" />
|
||||
<xs:attribute name="RDGatewayUsageMethod" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDGatewayHostname" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDGatewayUseConnectionCredentials" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDGatewayUsername" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDGatewayPassword" type="xs:string" use="required" />
|
||||
<xs:attribute name="RDGatewayDomain" type="xs:string" use="required" />
|
||||
<xs:attribute name="InheritCredentialRecord" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritCacheBitmaps" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritColors" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritDescription" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritDisplayThemes" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritDisplayWallpaper" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritEnableFontSmoothing" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritEnableDesktopComposition" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritDomain" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritIcon" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPanel" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPassword" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPort" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritProtocol" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPuttySession" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectDiskDrives" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectKeys" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectPorts" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectPrinters" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectSmartCards" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRedirectSound" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritSoundQuality" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritResolution" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritAutomaticResize" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritUseConsoleSession" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritUseCredSsp" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRenderingEngine" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritUsername" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritICAEncryptionStrength" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDPAuthenticationLevel" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDPMinutesToIdleTimeout" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritLoadBalanceInfo" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPreExtApp" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritPostExtApp" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritMacAddress" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritUserField" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritExtApp" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCCompression" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCEncoding" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCAuthMode" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCProxyType" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCProxyIP" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCProxyPort" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCProxyUsername" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCProxyPassword" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCColors" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCSmartSizeMode" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritVNCViewOnly" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayUsageMethod" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayHostname" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayUseConnectionCredentials" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayUsername" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayPassword" type="xs:boolean" use="optional" />
|
||||
<xs:attribute name="InheritRDGatewayDomain" type="xs:boolean" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
@@ -99,8 +99,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 +249,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,12 +213,10 @@ namespace mRemoteNG.UI.Window
|
||||
set
|
||||
{
|
||||
_btnShowProperties.Checked = value;
|
||||
if (value)
|
||||
{
|
||||
_btnShowInheritance.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
}
|
||||
if (!value) return;
|
||||
_btnShowInheritance.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,12 +229,10 @@ namespace mRemoteNG.UI.Window
|
||||
set
|
||||
{
|
||||
_btnShowInheritance.Checked = value;
|
||||
if (value)
|
||||
{
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
}
|
||||
if (!value) return;
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,12 +245,10 @@ namespace mRemoteNG.UI.Window
|
||||
set
|
||||
{
|
||||
_btnShowDefaultProperties.Checked = value;
|
||||
if (value)
|
||||
{
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowInheritance.Checked = false;
|
||||
}
|
||||
if (!value) return;
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultInheritance.Checked = false;
|
||||
_btnShowInheritance.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,12 +258,10 @@ namespace mRemoteNG.UI.Window
|
||||
set
|
||||
{
|
||||
_btnShowDefaultInheritance.Checked = value;
|
||||
if (value)
|
||||
{
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
_btnShowInheritance.Checked = false;
|
||||
}
|
||||
if (!value) return;
|
||||
_btnShowProperties.Checked = false;
|
||||
_btnShowDefaultProperties.Checked = false;
|
||||
_btnShowInheritance.Checked = false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -292,7 +284,7 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, Keys keyData)
|
||||
{
|
||||
// Main form handle command key events
|
||||
// Main form handle command key events
|
||||
// Adapted from http://kiwigis.blogspot.com/2009/05/adding-tab-key-support-to-propertygrid.html
|
||||
if ((keyData & Keys.KeyCode) == Keys.Tab)
|
||||
{
|
||||
@@ -311,19 +303,23 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
var newItem = selectedItem;
|
||||
|
||||
if (keyData == (Keys.Tab | Keys.Shift))
|
||||
newItem = FindPreviousGridItemProperty(gridItems, selectedItem);
|
||||
else if (keyData == Keys.Tab)
|
||||
newItem = FindNextGridItemProperty(gridItems, selectedItem);
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (keyData)
|
||||
{
|
||||
case (Keys.Tab | Keys.Shift):
|
||||
newItem = FindPreviousGridItemProperty(gridItems, selectedItem);
|
||||
break;
|
||||
case Keys.Tab:
|
||||
newItem = FindNextGridItemProperty(gridItems, selectedItem);
|
||||
break;
|
||||
}
|
||||
|
||||
_pGrid.SelectedGridItem = newItem;
|
||||
|
||||
return true; // Handled
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
private void FindChildGridItems(GridItem item, ref List<GridItem> gridItems)
|
||||
@@ -378,9 +374,7 @@ namespace mRemoteNG.UI.Window
|
||||
break;
|
||||
}
|
||||
|
||||
if (!previousIndexValid)
|
||||
return null;
|
||||
return gridItems[previousIndex];
|
||||
return !previousIndexValid ? null : gridItems[previousIndex];
|
||||
}
|
||||
|
||||
private GridItem FindNextGridItemProperty(IList<GridItem> gridItems, GridItem startItem)
|
||||
@@ -402,12 +396,10 @@ namespace mRemoteNG.UI.Window
|
||||
var nextIndexValid = false;
|
||||
for (var index = startIndex; index <= gridItems.Count - 1; index++)
|
||||
{
|
||||
if (gridItems[index].GridItemType == GridItemType.Property)
|
||||
{
|
||||
nextIndex = index;
|
||||
nextIndexValid = true;
|
||||
break;
|
||||
}
|
||||
if (gridItems[index].GridItemType != GridItemType.Property) continue;
|
||||
nextIndex = index;
|
||||
nextIndexValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextIndexValid)
|
||||
@@ -415,17 +407,13 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
for (var index = 0; index <= startIndex - 1; index++)
|
||||
{
|
||||
if (gridItems[index].GridItemType == GridItemType.Property)
|
||||
{
|
||||
nextIndex = index;
|
||||
nextIndexValid = true;
|
||||
break;
|
||||
}
|
||||
if (gridItems[index].GridItemType != GridItemType.Property) continue;
|
||||
nextIndex = index;
|
||||
nextIndexValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nextIndexValid)
|
||||
return null;
|
||||
return gridItems[nextIndex];
|
||||
return !nextIndexValid ? null : gridItems[nextIndex];
|
||||
}
|
||||
|
||||
public void SetPropertyGridObject(object propertyGridObject)
|
||||
@@ -450,6 +438,7 @@ namespace mRemoteNG.UI.Window
|
||||
var gridObjectAsRootNodeInfo = propertyGridObject as RootNodeInfo;
|
||||
if (gridObjectAsRootNodeInfo != null) // ROOT
|
||||
{
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (gridObjectAsRootNodeInfo.Type)
|
||||
{
|
||||
case RootNodeType.Connection:
|
||||
@@ -649,11 +638,9 @@ namespace mRemoteNG.UI.Window
|
||||
foreach (Control control in _pGrid.Controls)
|
||||
{
|
||||
toolStrip = control as ToolStrip;
|
||||
if (toolStrip != null)
|
||||
{
|
||||
propertyGridToolStrip = toolStrip;
|
||||
break;
|
||||
}
|
||||
if (toolStrip == null) continue;
|
||||
propertyGridToolStrip = toolStrip;
|
||||
break;
|
||||
}
|
||||
|
||||
if (toolStrip == null)
|
||||
@@ -673,11 +660,9 @@ namespace mRemoteNG.UI.Window
|
||||
propertyGridToolStrip.Items[_originalPropertyGridToolStripItemCount - 1].Visible = false;
|
||||
|
||||
var expectedToolStripItemCount = _originalPropertyGridToolStripItemCount + customToolStrip.Items.Count;
|
||||
if (propertyGridToolStrip.Items.Count != expectedToolStripItemCount)
|
||||
{
|
||||
propertyGridToolStrip.AllowMerge = true;
|
||||
ToolStripManager.Merge(customToolStrip, propertyGridToolStrip);
|
||||
}
|
||||
if (propertyGridToolStrip.Items.Count == expectedToolStripItemCount) return;
|
||||
propertyGridToolStrip.AllowMerge = true;
|
||||
ToolStripManager.Merge(customToolStrip, propertyGridToolStrip);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -745,7 +730,7 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
|
||||
if (selectedGridObject is DefaultConnectionInfo)
|
||||
DefaultConnectionInfo.Instance.SaveTo(Settings.Default, (a)=>"ConDefault"+a);
|
||||
DefaultConnectionInfo.Instance.SaveTo(Settings.Default, a=>"ConDefault"+a);
|
||||
}
|
||||
|
||||
private void UpdateRootInfoNode(PropertyValueChangedEventArgs e)
|
||||
@@ -753,6 +738,7 @@ namespace mRemoteNG.UI.Window
|
||||
var rootInfo = _pGrid.SelectedObject as RootNodeInfo;
|
||||
if (rootInfo == null) return;
|
||||
if (e.ChangedItem.PropertyDescriptor == null) return;
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (e.ChangedItem.PropertyDescriptor.Name)
|
||||
{
|
||||
case "Password":
|
||||
@@ -779,7 +765,7 @@ namespace mRemoteNG.UI.Window
|
||||
private void UpdateInheritanceNode()
|
||||
{
|
||||
if (!(_pGrid.SelectedObject is DefaultConnectionInheritance)) return;
|
||||
DefaultConnectionInheritance.Instance.SaveTo(Settings.Default, (a)=>"InhDefault"+a);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(Settings.Default, a=>"InhDefault"+a);
|
||||
}
|
||||
|
||||
private void pGrid_PropertySortChanged(object sender, EventArgs e)
|
||||
@@ -860,6 +846,7 @@ namespace mRemoteNG.UI.Window
|
||||
else if (_pGrid.SelectedObject is ConnectionInfo)
|
||||
{
|
||||
var conI = (ConnectionInfo)_pGrid.SelectedObject;
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (conI.Protocol)
|
||||
{
|
||||
case ProtocolType.RDP:
|
||||
@@ -1585,24 +1572,15 @@ namespace mRemoteNG.UI.Window
|
||||
try
|
||||
{
|
||||
var connectionInfo = (ConnectionInfo)_pGrid.SelectedObject;
|
||||
if (connectionInfo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (connectionInfo == null) return;
|
||||
|
||||
var selectedMenuItem = (ToolStripMenuItem)sender;
|
||||
|
||||
var iconName = selectedMenuItem?.Text;
|
||||
if (string.IsNullOrEmpty(iconName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(iconName)) return;
|
||||
|
||||
var connectionIcon = ConnectionIcon.FromString(iconName);
|
||||
if (connectionIcon == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (connectionIcon == null) return;
|
||||
|
||||
_btnIcon.Image = connectionIcon.ToBitmap();
|
||||
|
||||
@@ -1675,17 +1653,9 @@ namespace mRemoteNG.UI.Window
|
||||
_btnHostStatus.Image = Resources.HostStatus_Check;
|
||||
// To check status, ConnectionInfo must be an mRemoteNG.Connection.Info that is not a container
|
||||
var info = connectionInfo as ConnectionInfo;
|
||||
if (info != null)
|
||||
{
|
||||
if (info.IsContainer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (info == null) return;
|
||||
|
||||
if (info.IsContainer) return;
|
||||
|
||||
_btnHostStatus.Tag = "checking";
|
||||
_hostName = ((ConnectionInfo)connectionInfo).Hostname;
|
||||
@@ -1712,7 +1682,7 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenu_Opening() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenu_Opening() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1728,7 +1698,7 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenuReset_Click() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenuReset_Click() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -897,6 +897,9 @@
|
||||
<None Include="Schemas\mremoteng_confcons_v2_5.xsd">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Schemas\mremoteng_confcons_v2_8.xsd">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Schemas\mremoteng_confcons_v2_7.xsd">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
|
||||
Reference in New Issue
Block a user