Merge branch 'master' into develop

# Conflicts:
#	CHANGELOG.TXT
#	CREDITS.TXT
#	README.MD
#	Tools/postbuild_installer.ps1
#	Tools/set_LargeAddressAware.ps1
#	mRemoteNGTests/mRemoteNGTests.csproj
#	mRemoteNGTests/packages.config
#	mRemoteV1/App/Logger.cs
#	mRemoteV1/App/Runtime.cs
#	mRemoteV1/App/Startup.cs
#	mRemoteV1/Connection/DefaultConnectionInfo.cs
#	mRemoteV1/Connection/Protocol/IntegratedProgram.cs
#	mRemoteV1/Connection/Protocol/PuttyBase.cs
#	mRemoteV1/Messages/MessageCollector.cs
#	mRemoteV1/Properties/AssemblyInfo.cs
#	mRemoteV1/Resources/Language/Language.Designer.cs
#	mRemoteV1/Resources/PuTTYNG.exe
#	mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
#	mRemoteV1/Tools/ExternalToolArgumentParser.cs
#	mRemoteV1/Tools/IeBrowserEmulation.cs
#	mRemoteV1/Tools/NotificationAreaIcon.cs
#	mRemoteV1/Tools/PortScanner.cs
#	mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
#	mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
#	mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Window/AboutWindow.cs
#	mRemoteV1/UI/Window/PortScanWindow.cs
This commit is contained in:
David Sparer
2017-11-03 11:15:20 -05:00
26 changed files with 605 additions and 282 deletions

View File

@@ -14,11 +14,34 @@ Improved compatability between environments when building mRemoteNG from source
#493: Changed backup file name time stamp to use local system time rather than UTC
1.75.7009 (2017-07-XX):
1.75.7010 (2017-10-29):
Fixes:
------
#596: Exception when launching ExtTool without a connection selected
#756: CustomConsPath always null
1.75.7009 (2017-10-28):
Fixes:
------
#676: Portable version ignores /cons param on first run
#675: Attempting to add new connection/folder does not work in some situations
#665: Can not add new connection or new folder in some situations
#658: Keep Port Scan tab open after import
#646: Exception after click on import port scan
#635: Updated PuTTYNG to 0.70
#610: mRemoteNG cannot start /crashes for some users on Windows server 2012 R2 server
#600: Missing horizontal scrollbar on Connections Panel
#596: Exception when launching external tool without a connection selected
#550: Sometimes double-clicking connection tree node began rename instead of connecting
#536: Prevented log file creation when writeLogFile option is not set
#529: Erratic Tree Selection when using SQL Database
#482: Default connection password not decrypted when loaded
#335: The Quick Connect Toolbar > Connection view does not show open connections with the play icon
#176: Unable to enter text in Quick Connect when SSH connection active
Minor error message correction
Minor code refactoring
NO.RELEASE (2017-06-15):

View File

@@ -13,6 +13,10 @@ countchappy (github.com/countchappy)
Tony Lambert
Julien Roncaglia (github.com/vbfox)
github.com/peterchenadded
Brandon Wulf (github.com/mrwulf)
Pedro Rodrigues (github.com/pedro2555)
github.com/dekelMP
Past Contributors

View File

@@ -32,12 +32,12 @@ node('windows') {
withCredentials([file(credentialsId: '9b674d57-6792-48e3-984a-4d1bab2abb64', variable: 'CODE_SIGNING_CERT')]) {
withCredentials([usernamePassword(credentialsId: '05b7449b-05c0-490f-8661-236242526e62', passwordVariable: 'MRNG_CERT_PASSWORD', usernameVariable: 'NO_USERNAME')]) {
stage ('Build mRemoteNG (Normal - MSI)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
}
stage ('Build mRemoteNG (Portable)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
}
}
@@ -50,6 +50,11 @@ node('windows') {
stage ('Run Unit Tests (Portable)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release Portable\\mRemoteNGTests.dll\""
}
stage ('Generate UpdateCheck Files') {
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\create_upg_chk_files.ps1\" -TagName \"${env.TagName}\" -UpdateChannel \"${env.UpdateChannel}\""
archiveArtifacts artifacts: "Release\\*.txt", caseSensitive: false, onlyIfSuccessful: true
}
stage ('Publish to GitHub') {
withCredentials([string(credentialsId: '5443a369-dbe8-42d3-b4e8-04d0b4e9039a', variable: 'GH_AUTH_TOKEN')]) {

View File

@@ -1,42 +1,109 @@
#Requires -Version 4.0
param (
[string]
[Parameter(Mandatory=$true)]
$TagName,
[string]
[Parameter(Mandatory=$true)]
[ValidateSet("Stable","Beta","Development")]
$UpdateChannel
)
function New-MsiUpdateFileContent {
param (
[System.IO.FileInfo]
[Parameter(Mandatory=$true)]
$MsiFile,
[string]
[Parameter(Mandatory=$true)]
$TagName
)
$version = $MsiFile.BaseName -replace "[a-zA-Z-]*"
$certThumbprint = (Get-AuthenticodeSignature -FilePath $MsiFile).SignerCertificate.Thumbprint
$hash = Get-FileHash -Algorithm SHA512 $MsiFile | % { $_.Hash }
$fileContents = `
"Version: $version
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$TagName/$($MsiFile.Name)
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$TagName/CHANGELOG.TXT
CertificateThumbprint: $certThumbprint
Checksum: $hash"
Write-Output $fileContents
}
function New-ZipUpdateFileContent {
param (
[System.IO.FileInfo]
[Parameter(Mandatory=$true)]
$ZipFile,
[string]
[Parameter(Mandatory=$true)]
$TagName
)
$version = $ZipFile.BaseName -replace "[a-zA-Z-]*"
$hash = Get-FileHash -Algorithm SHA512 $ZipFile | % { $_.Hash }
$fileContents = `
"Version: $version
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$TagName/$($ZipFile.Name)
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$TagName/CHANGELOG.TXT
Checksum: $hash"
Write-Output $fileContents
}
function Resolve-UpdateCheckFileName {
param (
[string]
[Parameter(Mandatory=$true)]
[ValidateSet("Stable","Beta","Development")]
$UpdateChannel,
[string]
[Parameter(Mandatory=$true)]
[ValidateSet("Normal","Portable")]
$Type
)
$fileName = ""
if ($UpdateChannel -eq "Beta") { $fileName += "beta-" }
elseif ($UpdateChannel -eq "Development") { $fileName += "dev-" }
$fileName += "update"
if ($Type -eq "Portable") { $fileName += "-portable" }
$fileName += ".txt"
Write-Output $fileName
}
$releaseFolder = Join-Path -Path $PSScriptRoot -ChildPath "..\Release" -Resolve
$tag = Read-Host -Prompt 'Tag name'
Write-Host
Write-Host
Write-Host
# build msi update file
$msiFile = Get-ChildItem -Path "$releaseFolder\*.msi" | sort LastWriteTime | select -last 1
$msiUpdateContents = New-MsiUpdateFileContent -MsiFile $msiFile -TagName $TagName
$msiUpdateFileName = Resolve-UpdateCheckFileName -UpdateChannel $UpdateChannel -Type Normal
Write-Output "`n`nMSI Update Check File Contents ($msiUpdateFileName)`n------------------------------"
Tee-Object -InputObject $msiUpdateContents -FilePath "$releaseFolder\$msiUpdateFileName"
Write-Host PORTABLE
Write-Host --------
$file = Get-ChildItem -Path "$releaseFolder\*.zip" | sort LastWriteTime | select -last 1 | % { $_.FullName }
$filename = $file.Split("\") | select -last 1
$version = $file.tostring().Split("-")[2].trim(".zip")
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 SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash
Write-Host
Write-Host
Write-Host
Write-Host MSI
Write-Host ---
$file = Get-ChildItem -Path "$releaseFolder\*.msi" | sort LastWriteTime | select -last 1 | % { $_.FullName }
$filename = $file.Split("\") | select -last 1
$version = $file.tostring().Split("-")[2].trim(".msi")
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
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash
# build zip update file
$zipFile = Get-ChildItem -Path "$releaseFolder\*.zip" | sort LastWriteTime | select -last 1
$zipUpdateContents = New-ZipUpdateFileContent -ZipFile $zipFile -TagName $TagName
$zipUpdateFileName = Resolve-UpdateCheckFileName -UpdateChannel $UpdateChannel -Type Portable
Write-Output "`n`nZip Update Check File Contents ($zipUpdateFileName)`n------------------------------"
Tee-Object -InputObject $zipUpdateContents -FilePath "$releaseFolder\$zipUpdateFileName"

220
Tools/github_functions.ps1 Normal file
View File

@@ -0,0 +1,220 @@
$githubUrl = 'https://api.github.com'
function Publish-GitHubRelease {
param (
[string]
[Parameter(Mandatory=$true)]
#
$Owner,
[string]
[Parameter(Mandatory=$true)]
#
$Repository,
[string]
[Parameter(Mandatory=$true)]
#
$ReleaseTitle,
[string]
[Parameter(Mandatory=$true)]
#
$TagName,
[string]
[Parameter(Mandatory=$true)]
# Either the SHA of the commit to target or the branch name.
$TargetCommitish,
[string]
[Parameter(Mandatory=$true)]
#
$Description,
[bool]
[Parameter(Mandatory=$true)]
#
$IsDraft,
[bool]
[Parameter(Mandatory=$true)]
#
$IsPrerelease,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$body = New-GitHubReleaseRequestBody -TagName $TagName -TargetCommitish $TargetCommitish -ReleaseTitle $ReleaseTitle -Description $Description -IsDraft $IsDraft -IsPrerelease $IsPrerelease
$req_publishRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases" -Method Post -Headers @{"Authorization"="token $AuthToken"} -Body $body -ErrorAction Stop
$response_publishRelease = ConvertFrom-Json -InputObject $req_publishRelease.Content
Write-Output $response_publishRelease
}
function Edit-GitHubRelease {
param (
[string]
#[Parameter(Mandatory=$true)]
#
$Owner,
[string]
#[Parameter(Mandatory=$true)]
#
$Repository,
[string]
#[Parameter(Mandatory=$true)]
#
$ReleaseId,
[string]
#
$ReleaseTitle,
[string]
#
$TagName,
[string]
# Either the SHA of the commit to target or the branch name.
$TargetCommitish,
[string]
#
$Description,
[bool]
#
$IsDraft,
[bool]
#
$IsPrerelease,
[string]
#[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$body_params = @{
"TagName" = $TagName
"TargetCommitish" = $TargetCommitish
"ReleaseTitle" = $ReleaseTitle
"Description" = $Description
}
if ($PSBoundParameters.ContainsKey("IsDraft")) { $body_params.Add("IsDraft", $IsDraft) }
if ($PSBoundParameters.ContainsKey("IsPrerelease")) { $body_params.Add("IsPrerelease", $IsPrerelease) }
$body = New-GitHubReleaseRequestBody @body_params
$req_editRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases/$ReleaseId" -Method Post -Headers @{"Authorization"="token $AuthToken"} -Body $body -ErrorAction Stop
$response_editRelease = ConvertFrom-Json -InputObject $req_editRelease.Content
Write-Output $response_editRelease
}
function Get-GitHubRelease {
param (
[string]
[Parameter(Mandatory=$true)]
#
$Owner,
[string]
[Parameter(Mandatory=$true)]
#
$Repository,
[string]
[Parameter(Mandatory=$true)]
#
$ReleaseId,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$req_getRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases/$ReleaseId" -Method Get -Headers @{"Authorization"="token $AuthToken"} -ErrorAction Stop
$response_getRelease = ConvertFrom-Json -InputObject $req_getRelease.Content
Write-Output $response_getRelease
}
function Upload-GitHubReleaseAsset {
param (
[string]
[Parameter(Mandatory=$true)]
$UploadUri,
[string]
[Parameter(Mandatory=$true)]
# Path to the file to upload with the release
$FilePath,
[string]
[Parameter(Mandatory=$true)]
# Content type of the file
$ContentType,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
$file = Get-Item -Path $FilePath
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
}
function New-GitHubReleaseRequestBody {
param (
[string]
#
$TagName,
[string]
# Either the SHA of the commit to target or the branch name.
$TargetCommitish,
[string]
# Title of the release
$ReleaseTitle,
[string]
# Description of the release
$Description,
[bool]
# Is this a draft?
$IsDraft,
[bool]
# Is this a pre-release?
$IsPrerelease
)
$body_params = [ordered]@{}
if ($TagName -ne "") { $body_params.Add("tag_name", $TagName) }
if ($TargetCommitish -ne "") { $body_params.Add("target_commitish", $TargetCommitish) }
if ($ReleaseTitle -ne "") { $body_params.Add("name", $ReleaseTitle) }
if ($Description -ne "") { $body_params.Add("body", $Description) }
if ($PSBoundParameters.ContainsKey("IsDraft")) { $body_params.Add("draft", $IsDraft) }
if ($PSBoundParameters.ContainsKey("IsPrerelease")) { $body_params.Add("prerelease", $IsPrerelease) }
$json_body = ConvertTo-Json -InputObject $body_params -Compress
Write-Output $json_body
}

View File

@@ -0,0 +1,25 @@
param (
[string]
[Parameter(Mandatory=$true)]
#
$Owner,
[string]
[Parameter(Mandatory=$true)]
#
$Repository,
[string]
[Parameter(Mandatory=$true)]
#
$ReleaseId,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
. "$PSScriptRoot\github_functions.ps1"
Edit-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $ReleaseId -AuthToken $AuthToken -IsDraft $false

View File

@@ -62,137 +62,15 @@ param (
)
$githubUrl = 'https://api.github.com'
if ($DescriptionIsBase64Encoded) {
$Description = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Description)))
}
function Publish-Release {
param (
[string]
[Parameter(Mandatory=$true)]
#
$Owner,
[string]
[Parameter(Mandatory=$true)]
#
$Repository,
[string]
[Parameter(Mandatory=$true)]
#
$ReleaseTitle,
[string]
[Parameter(Mandatory=$true)]
#
$TagName,
[string]
[Parameter(Mandatory=$true)]
# Either the SHA of the commit to target or the branch name.
$TargetCommitish,
[string]
[Parameter(Mandatory=$true)]
#
$Description,
[bool]
[Parameter(Mandatory=$true)]
#
$IsDraft,
[bool]
[Parameter(Mandatory=$true)]
#
$IsPrerelease,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$body_publishRelease = @{
"tag_name" = $TagName
"target_commitish" = $TargetCommitish
"name" = $ReleaseTitle
"body" = $Description
"draft" = $IsDraft
"prerelease" = $IsPrerelease
}
$req_publishRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases" -Method Post -Headers @{"Authorization"="token $AuthToken"} -Body (ConvertTo-Json -InputObject $body_publishRelease -Compress) -ErrorAction Stop
$response_publishRelease = ConvertFrom-Json -InputObject $req_publishRelease.Content
Write-Output $response_publishRelease
}
. "$PSScriptRoot\github_functions.ps1"
function Get-GitHubRelease {
param (
[string]
[Parameter(Mandatory=$true)]
#
$Owner,
[string]
[Parameter(Mandatory=$true)]
#
$Repository,
[string]
[Parameter(Mandatory=$true)]
#
$ReleaseId,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$req_getRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases/$ReleaseId" -Method Get -Headers @{"Authorization"="token $AuthToken"} -ErrorAction Stop
$response_getRelease = ConvertFrom-Json -InputObject $req_getRelease.Content
Write-Output $response_getRelease
}
function Upload-ReleaseAsset {
param (
[string]
[Parameter(Mandatory=$true)]
$UploadUri,
[string]
[Parameter(Mandatory=$true)]
# Path to the file to upload with the release
$FilePath,
[string]
[Parameter(Mandatory=$true)]
# Content type of the file
$ContentType,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken
)
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
$file = Get-Item -Path $FilePath
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
}
$release = Publish-Release -Owner $Owner -Repository $Repository -ReleaseTitle $ReleaseTitle -TagName $TagName -TargetCommitish $TargetCommitish -Description $Description -IsDraft ([bool]::Parse($IsDraft)) -IsPrerelease ([bool]::Parse($IsPrerelease)) -AuthToken $AuthToken
$zipUpload = Upload-ReleaseAsset -UploadUri $release.upload_url -FilePath $ZipFilePath -ContentType "application/zip" -AuthToken $AuthToken
$msiUpload = Upload-ReleaseAsset -UploadUri $release.upload_url -FilePath $MsiFilePath -ContentType "application/octet-stream" -AuthToken $AuthToken
$release = Publish-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseTitle $ReleaseTitle -TagName $TagName -TargetCommitish $TargetCommitish -Description $Description -IsDraft ([bool]::Parse($IsDraft)) -IsPrerelease ([bool]::Parse($IsPrerelease)) -AuthToken $AuthToken
$zipUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $ZipFilePath -ContentType "application/zip" -AuthToken $AuthToken
$msiUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $MsiFilePath -ContentType "application/octet-stream" -AuthToken $AuthToken
Write-Output (Get-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $release.id -AuthToken $AuthToken)

View File

@@ -0,0 +1,17 @@
# $FullPath Full path to the Microsoft executable to validate
param (
[string]
[Parameter(Mandatory=$true)]
$FullPath
)
$validMSCertThumbprints = @("3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC", "108E2BA23632620C427C570B6D9DB51AC31387FE", "98ED99A67886D020C564923B7DF25E9AC019DF26", "5EAD300DC7E4D637948ECB0ED829A072BD152E17")
$exeSignature = Get-AuthenticodeSignature -FilePath $FullPath
$baseErrorMsg = "Could not validate the certificate of $FullPath. "
if ($exeSignature.Status -ne "Valid") {
Write-Error -Message ($baseErrorMsg+"The signature was invalid.") -ErrorAction Stop
}
elseif ($validMSCertThumbprints -notcontains $exeSignature.SignerCertificate.Thumbprint) {
Write-Error -Message ($baseErrorMsg+"The certificate thumbprint ($($exeSignature.SignerCertificate.Thumbprint)) is not trusted.") -ErrorAction Stop
}

View File

@@ -310,11 +310,11 @@
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,14 +1,14 @@
using System;
using System;
using System.IO;
using System.Windows.Forms;
using log4net;
using log4net.Appender;
using log4net.Config;
using System.IO;
using System.Windows.Forms;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.App
{
public class Logger
public class Logger
{
public static readonly Logger Instance = new Logger();

View File

@@ -1,30 +1,28 @@
using mRemoteNG.App.Info;
using mRemoteNG.Config.Connections;
using mRemoteNG.Connection;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
using System;
using System.IO;
using System.Security;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App.Info;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Messages;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.TaskDialog;
namespace mRemoteNG.App
{
public static class Runtime
public static class Runtime
{
#region Public Properties
public static bool IsPortableEdition
{
get
@@ -42,12 +40,11 @@ namespace mRemoteNG.App
public static NotificationAreaIcon NotificationAreaIcon { get; set; }
public static RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; }
// ReSharper disable once UnusedAutoPropertyAccessor.Local
private static DateTime LastSqlUpdate { get; set; }
public static DateTime LastSqlUpdate { get; set; }
public static ExternalToolsService ExternalToolsService { get; } = new ExternalToolsService();
public static SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
public static ICredentialRepositoryList CredentialProviderCatalog { get; } = new CredentialRepositoryList();
public static ConnectionsService ConnectionsService { get; } = new ConnectionsService();
#endregion
#region Connections Loading/Saving
public static void LoadConnectionsAsync()

View File

@@ -57,7 +57,15 @@ namespace mRemoteNG.Config.Connections
private bool DatabaseIsMoreUpToDateThanUs()
{
return GetLastUpdateTimeFromDbResponse() > _lastUpdateTime;
var lastUpdateInDb = GetLastUpdateTimeFromDbResponse();
var IAmTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
return (lastUpdateInDb > _lastUpdateTime && !IAmTheLastoneUpdated);
}
private bool CheckIfIAmTheLastOneUpdated(DateTime lastUpdateInDb)
{
DateTime LastSqlUpdateWithoutMilliseconds = new DateTime(Runtime.LastSqlUpdate.Ticks - (Runtime.LastSqlUpdate.Ticks % TimeSpan.TicksPerSecond), Runtime.LastSqlUpdate.Kind);
return lastUpdateInDb == LastSqlUpdateWithoutMilliseconds;
}
private DateTime GetLastUpdateTimeFromDbResponse()

View File

@@ -1,4 +1,5 @@
using System;
using mRemoteNG.App;
namespace mRemoteNG.Connection
@@ -17,11 +18,17 @@ namespace mRemoteNG.Connection
public void LoadFrom<TSource>(TSource sourceInstance, Func<string,string> propertyNameMutator = null)
{
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
if (propertyNameMutator == null) propertyNameMutator = a => a;
var inheritanceProperties = GetProperties();
foreach (var property in inheritanceProperties)
{
var propertyFromSettings = typeof(TSource).GetProperty(propertyNameMutator(property.Name));
if (propertyFromSettings == null)
{
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg,
$"DefaultConInherit-LoadFrom: Could not load {property.Name}", true);
continue;
}
var valueFromSettings = propertyFromSettings.GetValue(sourceInstance, null);
property.SetValue(Instance, valueFromSettings, null);
}
@@ -29,12 +36,18 @@ namespace mRemoteNG.Connection
public void SaveTo<TDestination>(TDestination destinationInstance, Func<string, string> propertyNameMutator = null)
{
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
if (propertyNameMutator == null) propertyNameMutator = a => a;
var inheritanceProperties = GetProperties();
foreach (var property in inheritanceProperties)
{
var propertyFromSettings = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
var localValue = property.GetValue(Instance, null);
if (propertyFromSettings == null)
{
Runtime.MessageCollector?.AddMessage(Messages.MessageClass.ErrorMsg,
$"DefaultConInherit-SaveTo: Could not load {property.Name}", true);
continue;
}
propertyFromSettings.SetValue(destinationInstance, localValue, null);
}
}

View File

@@ -1,12 +1,11 @@
using mRemoteNG.App;
using mRemoteNG.Tools;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
namespace mRemoteNG.Connection.Protocol
{
@@ -63,9 +62,9 @@ namespace mRemoteNG.Connection.Protocol
_process.Exited += ProcessExited;
_process.Start();
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
var startTicks = Environment.TickCount;
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
var startTicks = Environment.TickCount;
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + Settings.Default.MaxPuttyWaitTime * 1000)
{
_process.Refresh();

View File

@@ -8,18 +8,18 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace mRemoteNG {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
namespace mRemoteNG
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Language {
@@ -529,7 +529,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to You cannot import a normal connection file.
/// Looks up a localized string similar to You cannot import a normal connection file.
///Please use File - Load Connections for normal connection files!.
/// </summary>
internal static string strCannotImportNormalSessionFile {
@@ -665,9 +665,9 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to The (RDP) Sessions feature requires that you have a copy of eolwtscom.dll registered on your system.
///mRemoteNG ships with this component but it is not registered automatically if you do not use the mRemoteNG Installer.
///To register it manually, run the following command from an elevated command prompt: regsvr32 &quot;C:\Program Files\mRemoteNG\eolwtscom.dll&quot; (where C:\Program Files\mRemoteNG\ is the path to your mRemoteNG installation).
/// Looks up a localized string similar to The (RDP) Sessions feature requires that you have a copy of eolwtscom.dll registered on your system.
///mRemoteNG ships with this component but it is not registered automatically if you do not use the mRemoteNG Installer.
///To register it manually, run the following command from an elevated command prompt: regsvr32 &quot;C:\Program Files\mRemoteNG\eolwtscom.dll&quot; (where C:\Program Files\mRemoteNG\ is the path to your mRemoteNG installation).
///If this check still fails or you are unable to use the (RDP) Sessions feature [rest of string was truncated]&quot;;.
/// </summary>
internal static string strCcEOLFailed {
@@ -686,9 +686,9 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to To use the Gecko Rendering Engine you need to have XULrunner 1.8.1.x and the path to the installation set in your Options.
///You can download XULrunner 1.8.1.3 here: ftp://ftp.mozilla.org/pub/xulrunner/releases/1.8.1.3/contrib/win32/
///When you are finished downloading extract the package to a path of your choice. Then in mRemoteNG go to Tools - Options - Advanced and enter the correct path in the XULrunner path field.
/// Looks up a localized string similar to To use the Gecko Rendering Engine you need to have XULrunner 1.8.1.x and the path to the installation set in your Options.
///You can download XULrunner 1.8.1.3 here: ftp://ftp.mozilla.org/pub/xulrunner/releases/1.8.1.3/contrib/win32/
///When you are finished downloading extract the package to a path of your choice. Then in mRemoteNG go to Tools - Options - Advanced and enter the correct path in the XULrunner path field.
///If you are still not able to pass this check or use the Gecko Engine in mRemoteNG please cons [rest of string was truncated]&quot;;.
/// </summary>
internal static string strCcGeckoFailed {
@@ -707,8 +707,8 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to ICA requires that the XenDesktop Online Plugin is installed and that the wfica.ocx library is registered. You can download the client here: http://www.citrix.com/download/
///If you have the XenDesktop Online Plugin installed and the check still fails, try to register wfica.ocx manually.
/// Looks up a localized string similar to ICA requires that the XenDesktop Online Plugin is installed and that the wfica.ocx library is registered. You can download the client here: http://www.citrix.com/download/
///If you have the XenDesktop Online Plugin installed and the check still fails, try to register wfica.ocx manually.
///To do this open up the run dialog (Start - Run) and enter the following: regsvr32 &quot;c:\Program Files\Citrix\ICA Client\wfica.ocx&quot; (Where c:\Program Files\Citrix\ICA Client\ is the path to your XenDesktop Online Plugin installat [rest of string was truncated]&quot;;.
/// </summary>
internal static string strCcICAFailed {
@@ -718,7 +718,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to All ICA components were found and seem to be registered properly.
/// Looks up a localized string similar to All ICA components were found and seem to be registered properly.
///Citrix ICA Client Control Version {0}.
/// </summary>
internal static string strCcICAOK {
@@ -737,7 +737,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to The SSH, Telnet, Rlogin and RAW protocols need PuTTY to work. PuTTY comes with every mRemoteNG package and is located in the installation path.
/// Looks up a localized string similar to The SSH, Telnet, Rlogin and RAW protocols need PuTTY to work. PuTTY comes with every mRemoteNG package and is located in the installation path.
///Please make sure that either you have the Putty.exe in your mRemoteNG directory (default: c:\Program Files\mRemoteNG\) or that you specified a valid path to your PuTTY executable in the Options (Tools - Options - Advanced - Custom PuTTY path).
/// </summary>
internal static string strCcPuttyFailed {
@@ -756,7 +756,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to For RDP to work properly you need to have at least Remote Desktop Connection (Terminal Services) Client 8.0 installed. You can download it here: http://support.microsoft.com/kb/925876
/// Looks up a localized string similar to For RDP to work properly you need to have at least Remote Desktop Connection (Terminal Services) Client 8.0 installed. You can download it here: http://support.microsoft.com/kb/925876
///If this check still fails or you are unable to use RDP, please consult the mRemoteNG Forum at http://forum.mremoteng.org/..
/// </summary>
internal static string strCcRDPFailed {
@@ -766,7 +766,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to All RDP components were found and seem to be registered properly.
/// Looks up a localized string similar to All RDP components were found and seem to be registered properly.
///Remote Desktop Connection Control Version {0}.
/// </summary>
internal static string strCcRDPOK {
@@ -776,8 +776,8 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to VNC requires VncSharp.dll to be located in your mRemoteNG application folder.
///Please make sure that you have the VncSharp.dll file in your mRemoteNG application folder (usually C:\Program Files\mRemoteNG\).
/// Looks up a localized string similar to VNC requires VncSharp.dll to be located in your mRemoteNG application folder.
///Please make sure that you have the VncSharp.dll file in your mRemoteNG application folder (usually C:\Program Files\mRemoteNG\).
///If you are still not able to pass this check or use VNC in mRemoteNG please consult the mRemoteNG Forum at http://forum.mremoteng.org/.
/// </summary>
internal static string strCcVNCFailed {
@@ -787,7 +787,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to All VNC components were found and seem to be registered properly.
/// Looks up a localized string similar to All VNC components were found and seem to be registered properly.
///VncSharp Control Version {0}.
/// </summary>
internal static string strCcVNCOK {
@@ -1166,7 +1166,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to Do you want to close the connection:
/// Looks up a localized string similar to Do you want to close the connection:
///&quot;{0}&quot;?.
/// </summary>
internal static string strConfirmCloseConnectionMainInstruction {
@@ -1347,8 +1347,8 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to RDP error!
///Error Code: {0}
/// Looks up a localized string similar to RDP error!
///Error Code: {0}
///Error Description: {1}.
/// </summary>
internal static string strConnectionRdpErrorDetail {
@@ -1403,7 +1403,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to Connections file &quot;{0}&quot; could not be loaded!
/// Looks up a localized string similar to Connections file &quot;{0}&quot; could not be loaded!
///Starting with new connections file..
/// </summary>
internal static string strConnectionsFileCouldNotBeLoadedNew {
@@ -1539,8 +1539,8 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to In v1.76 we have introduced a credential management system. This feature requires a significant change in how we store and interact with credentials within mRemoteNG. You will be required to perform a one-way upgrade of your mRemoteNG connections file.
///
/// Looks up a localized string similar to In v1.76 we have introduced a credential management system. This feature requires a significant change in how we store and interact with credentials within mRemoteNG. You will be required to perform a one-way upgrade of your mRemoteNG connections file.
///
///This page will walk you through the process of upgrading your connections file or give you a chance to open a different connections file if you do not want to perform the upgrade..
/// </summary>
internal static string strCredentialManagerUpgradeDescription {
@@ -1838,10 +1838,10 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to The Windows security setting, &quot;System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing&quot;, is enabled. This setting is not compatible with {0}.
///
///See the Microsoft Support article at http://support.microsoft.com/kb/811833 for more information.
///
/// Looks up a localized string similar to The Windows security setting, &quot;System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing&quot;, is enabled. This setting is not compatible with {0}.
///
///See the Microsoft Support article at http://support.microsoft.com/kb/811833 for more information.
///
///{0} will now close..
/// </summary>
internal static string strErrorFipsPolicyIncompatible {
@@ -3867,7 +3867,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to You are trying to load a connection file that was created using an very early version of mRemote, this could result in an runtime error.
/// Looks up a localized string similar to You are trying to load a connection file that was created using an very early version of mRemote, this could result in an runtime error.
///If you run into such an error, please create a new connection file!.
/// </summary>
internal static string strOldConffile {
@@ -5236,8 +5236,8 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to Protocol Event Disconnected.
///Message:
/// Looks up a localized string similar to Protocol Event Disconnected.
///Message:
///{0}.
/// </summary>
internal static string strProtocolEventDisconnected {
@@ -5247,7 +5247,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to Protocol Event Disconnected failed.
/// Looks up a localized string similar to Protocol Event Disconnected failed.
///{0}.
/// </summary>
internal static string strProtocolEventDisconnectFailed {
@@ -7093,7 +7093,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to Download complete!
/// Looks up a localized string similar to Download complete!
///mRemoteNG will now quit and begin with the installation..
/// </summary>
internal static string strUpdateDownloadComplete {

View File

@@ -246,7 +246,7 @@
</data>
<data name="strCannotImportNormalSessionFile" xml:space="preserve">
<value>You cannot import a normal connection file.
Please use File - Load Connections for normal connection files!</value>
Please use File - Open Connection File for normal connection files!</value>
</data>
<data name="strCannotStartPortScan" xml:space="preserve">
<value>IPアドレスのフォーマットが正しくないのでポートスキャンの開始に失敗しました</value>

View File

@@ -245,7 +245,7 @@
</data>
<data name="strCannotImportNormalSessionFile" xml:space="preserve">
<value>You cannot import a normal connection file.
Please use File - Load Connections for normal connection files!</value>
Please use File - Open Connection File for normal connection files!</value>
</data>
<data name="strCannotStartPortScan" xml:space="preserve">
<value>Cannot start Port Scan, incorrect IP format!</value>

Binary file not shown.

View File

@@ -6,16 +6,15 @@ using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Tree;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tools
{
public class ConnectionsTreeToMenuItemsConverter
public class ConnectionsTreeToMenuItemsConverter
{
private readonly StatusImageList _statusImageList = new StatusImageList();
public MouseEventHandler MouseUpEventHandler { get; set; }
public IEnumerable<ToolStripDropDownItem> CreateToolStripDropDownItems(ConnectionTreeModel connectionTreeModel)
{
var rootNodes = connectionTreeModel.RootNodes;
@@ -50,15 +49,26 @@ namespace mRemoteNG.Tools
var menuItem = new ToolStripMenuItem
{
Text = node.Name,
Tag = node,
Image = _statusImageList.GetImage(node)
Tag = node
};
var nodeAsContainer = node as ContainerInfo;
if (nodeAsContainer != null)
{
menuItem.Image = Resources.Folder;
menuItem.Tag = nodeAsContainer;
AddSubMenuNodes(nodeAsContainer.Children, menuItem);
}
else if (node.GetTreeNodeType() == TreeNodeType.PuttySession)
{
menuItem.Image = Resources.PuttySessions;
menuItem.Tag = node;
}
else if (node.GetTreeNodeType() == TreeNodeType.Connection)
{
menuItem.Image = node.OpenConnections.Count > 0 ? Resources.Play : Resources.Pause;
menuItem.Tag = node;
}
menuItem.MouseUp += MouseUpEventHandler;
return menuItem;

View File

@@ -112,7 +112,7 @@ namespace mRemoteNG.Tools
private void SetConnectionInfoFields(ConnectionInfo newConnectionInfo)
{
newConnectionInfo.Protocol = ProtocolType.IntApp;
newConnectionInfo.ExtApp = DisplayName;
newConnectionInfo.ExtApp = FileName;
newConnectionInfo.Name = DisplayName;
newConnectionInfo.Panel = Language.strMenuExternalTools;
}

View File

@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools.Cmdline;
namespace mRemoteNG.Tools
{
public class ExternalToolArgumentParser
public class ExternalToolArgumentParser
{
private readonly ConnectionInfo _connectionInfo;
@@ -170,12 +172,26 @@ namespace mRemoteNG.Tools
break;
case "username":
replacement = _connectionInfo.Username;
if (string.IsNullOrEmpty(replacement))
if (Settings.Default.EmptyCredentials == "windows")
replacement = Environment.UserName;
else if (Settings.Default.EmptyCredentials == "custom")
replacement = Settings.Default.DefaultUsername;
break;
case "password":
replacement = _connectionInfo.Password;
if (string.IsNullOrEmpty(replacement) && Settings.Default.EmptyCredentials == "custom")
replacement = new LegacyRijndaelCryptographyProvider()
.Decrypt(Convert.ToString(Settings.Default.DefaultPassword),
Runtime.EncryptionKey);
break;
case "domain":
replacement = _connectionInfo.Domain;
if (string.IsNullOrEmpty(replacement))
if (Settings.Default.EmptyCredentials == "windows")
replacement = Environment.UserDomainName;
else if (Settings.Default.EmptyCredentials == "custom")
replacement = Settings.Default.DefaultDomain;
break;
case "description":
replacement = _connectionInfo.Description;

View File

@@ -7,7 +7,7 @@ using mRemoteNG.App;
namespace mRemoteNG.Tools
{
public class IeBrowserEmulation
public class IeBrowserEmulation
{
// found this here:
// http://www.neowin.net/forum/topic/1077469-vbnet-webbrowser-control-does-not-load-javascript/#comment-596755046
@@ -205,7 +205,7 @@ namespace mRemoteNG.Tools
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("IeBrowserEmulation.Register() failed.", ex);
Runtime.MessageCollector?.AddExceptionMessage("IeBrowserEmulation.Register() failed.", ex);
}
}
@@ -219,7 +219,7 @@ namespace mRemoteNG.Tools
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("IeBrowserEmulation.Unregister() failed.", ex);
Runtime.MessageCollector?.AddExceptionMessage("IeBrowserEmulation.Unregister() failed.", ex);
}
#endif
}

View File

@@ -22,10 +22,10 @@ namespace mRemoteNG.UI.Controls
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
private readonly StatusImageList _statusImageList = new StatusImageList();
public ConnectionInfo SelectedNode
{
get { return (ConnectionInfo) SelectedObject; }
}
private bool _allowEdit;
private bool _isUpdatingColumnWidth;
public ConnectionInfo SelectedNode => (ConnectionInfo) SelectedObject;
public NodeSearcher NodeSearcher { get; private set; }
@@ -103,30 +103,49 @@ namespace mRemoteNG.UI.Controls
Collapsed += (sender, args) =>
{
var container = args.Model as ContainerInfo;
if (container != null)
container.IsExpanded = false;
if (container == null) return;
container.IsExpanded = false;
UpdateColumnWidth();
};
Expanded += (sender, args) =>
{
var container = args.Model as ContainerInfo;
if (container != null)
container.IsExpanded = true;
if (container == null) return;
container.IsExpanded = true;
UpdateColumnWidth();
};
SizeChanged += OnSizeChanged;
SelectionChanged += tvConnections_AfterSelect;
MouseDoubleClick += OnMouse_DoubleClick;
MouseClick += OnMouse_SingleClick;
CellToolTipShowing += tvConnections_CellToolTipShowing;
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
BeforeLabelEdit += HandleCheckForValidEdit;
}
private void OnSizeChanged(object o, EventArgs eventArgs)
{
if (_isUpdatingColumnWidth)
return;
UpdateColumnWidth();
}
private void UpdateColumnWidth()
{
_isUpdatingColumnWidth = true;
AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
Columns[0].Width += SmallImageSize.Width;
_isUpdatingColumnWidth = false;
}
private void PopulateTreeView()
{
UnregisterModelUpdateHandlers();
SetObjects(ConnectionTreeModel.RootNodes);
ResizeColumns();
RegisterModelUpdateHandlers();
NodeSearcher = new NodeSearcher(ConnectionTreeModel);
UpdateColumnWidth();
ExecutePostSetupActions();
}
@@ -147,12 +166,12 @@ namespace mRemoteNG.UI.Controls
private void OnPuttySessionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
RefreshObjects(GetRootPuttyNodes().ToList());
ResizeColumns();
}
private void HandleCollectionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
// for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
// Removed "TO DO" from above comment. Per #142 it apperas that this no longer occurs with ObjectListView 2.9.1
var property = propertyChangedEventArgs.PropertyName;
if (property != nameof(ConnectionInfo.Name)
&& property != nameof(ConnectionInfo.OpenConnections)
@@ -162,9 +181,11 @@ namespace mRemoteNG.UI.Controls
}
var senderAsConnectionInfo = sender as ConnectionInfo;
if (senderAsConnectionInfo != null)
RefreshObject(senderAsConnectionInfo);
ResizeColumns();
if (senderAsConnectionInfo == null)
return;
RefreshObject(senderAsConnectionInfo);
UpdateColumnWidth();
}
private void ExecutePostSetupActions()
@@ -223,11 +244,12 @@ namespace mRemoteNG.UI.Controls
private void AddNode(ConnectionInfo newNode)
{
if (SelectedNode == null) return;
// use root node if no node is selected
ConnectionInfo parentNode = SelectedNode ?? GetRootConnectionNode();
DefaultConnectionInfo.Instance.SaveTo(newNode);
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
var selectedContainer = SelectedNode as ContainerInfo;
var parent = selectedContainer ?? SelectedNode?.Parent;
var selectedContainer = parentNode as ContainerInfo;
var parent = selectedContainer ?? parentNode?.Parent;
newNode.SetParent(parent);
Expand(parent);
SelectObject(newNode, true);
@@ -245,10 +267,24 @@ namespace mRemoteNG.UI.Controls
public void RenameSelectedNode()
{
_allowEdit = true;
SelectedItem.BeginEdit();
Runtime.SaveConnectionsAsync();
}
public void HandleCheckForValidEdit(object sender, LabelEditEventArgs e)
{
if (!(sender is ConnectionTree)) return;
if (_allowEdit)
{
_allowEdit = false;
}
else
{
e.CancelEdit = true;
}
}
public void DeleteSelectedNode()
{
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
@@ -274,7 +310,6 @@ namespace mRemoteNG.UI.Controls
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
RefreshObject(sender);
ResizeColumns();
}
private void tvConnections_AfterSelect(object sender, EventArgs e)
@@ -321,16 +356,6 @@ namespace mRemoteNG.UI.Controls
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_MouseMove (UI.Window.ConnectionTreeWindow) failed", ex);
}
}
private void ResizeColumns()
{
foreach (OLVColumn column in Columns)
{
column.FreeSpaceProportion = 95;
column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
}
}
#endregion
}
}

View File

@@ -3,11 +3,12 @@ using mRemoteNG.Connection;
namespace mRemoteNG.UI.Controls
{
public class NameColumn : OLVColumn
public class NameColumn : OLVColumn
{
public NameColumn(ImageGetterDelegate imageGetterDelegate)
{
AspectName = "Name";
FillsFreeSpace = false;
AspectGetter = item => ((ConnectionInfo) item).Name;
ImageGetter = imageGetterDelegate;
}

View File

@@ -1,5 +1,8 @@
using mRemoteNG.Connection;
using mRemoteNG.Tree;
namespace mRemoteNG.UI.Window
{
public partial class ConnectionTreeWindow : BaseWindow
@@ -19,6 +22,9 @@ namespace mRemoteNG.UI.Window
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
mRemoteNG.Tree.TreeNodeCompositeClickHandler treeNodeCompositeClickHandler1 = new mRemoteNG.Tree.TreeNodeCompositeClickHandler();
mRemoteNG.Tree.AlwaysConfirmYes alwaysConfirmYes1 = new mRemoteNG.Tree.AlwaysConfirmYes();
mRemoteNG.Tree.TreeNodeCompositeClickHandler treeNodeCompositeClickHandler2 = new mRemoteNG.Tree.TreeNodeCompositeClickHandler();
this.olvConnections = new mRemoteNG.UI.Controls.ConnectionTree();
this.pnlConnections = new System.Windows.Forms.Panel();
this.PictureBox1 = new System.Windows.Forms.PictureBox();
@@ -48,22 +54,31 @@ namespace mRemoteNG.UI.Window
| System.Windows.Forms.AnchorStyles.Right)));
this.olvConnections.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.olvConnections.CellEditUseWholeCell = false;
this.olvConnections.ConnectionTreeModel = new ConnectionTreeModel();
this.olvConnections.Cursor = System.Windows.Forms.Cursors.Default;
treeNodeCompositeClickHandler1.ClickHandlers = new ITreeNodeClickHandler<ConnectionInfo>[0];
this.olvConnections.DoubleClickHandler = treeNodeCompositeClickHandler1;
this.olvConnections.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.olvConnections.HideSelection = false;
this.olvConnections.IsSimpleDragSource = true;
this.olvConnections.IsSimpleDropSink = true;
this.olvConnections.LabelEdit = true;
this.olvConnections.Location = new System.Drawing.Point(0, 0);
this.olvConnections.MultiSelect = false;
this.olvConnections.Name = "olvConnections";
this.olvConnections.NodeDeletionConfirmer = alwaysConfirmYes1;
this.olvConnections.PostSetupActions = new mRemoteNG.UI.Controls.IConnectionTreeDelegate[0];
this.olvConnections.SelectedBackColor = System.Drawing.SystemColors.Highlight;
this.olvConnections.SelectedForeColor = System.Drawing.SystemColors.HighlightText;
this.olvConnections.ShowGroups = false;
treeNodeCompositeClickHandler2.ClickHandlers = new mRemoteNG.Tree.ITreeNodeClickHandler<ConnectionInfo>[0];
this.olvConnections.SingleClickHandler = treeNodeCompositeClickHandler2;
this.olvConnections.Size = new System.Drawing.Size(192, 410);
this.olvConnections.TabIndex = 20;
this.olvConnections.UnfocusedSelectedBackColor = System.Drawing.SystemColors.Highlight;
this.olvConnections.UnfocusedSelectedForeColor = System.Drawing.SystemColors.HighlightText;
this.olvConnections.UseCompatibleStateImageBehavior = false;
this.olvConnections.UseOverlays = false;
this.olvConnections.View = System.Windows.Forms.View.Details;
this.olvConnections.VirtualMode = true;
//

View File

@@ -1,12 +1,12 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using mRemoteNG.App;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using WeifenLuo.WinFormsUI.Docking;
using static mRemoteNG.Tools.MiscTools;
namespace mRemoteNG.UI.Window