diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT
index e6ae6d7cd..8c8cf5e0a 100644
--- a/CHANGELOG.TXT
+++ b/CHANGELOG.TXT
@@ -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):
diff --git a/CREDITS.TXT b/CREDITS.TXT
index 5b80d2a0e..5a4f7baa7 100644
--- a/CREDITS.TXT
+++ b/CREDITS.TXT
@@ -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
diff --git a/Jenkinsfile_publish.groovy b/Jenkinsfile_publish.groovy
index 12640d98e..2c30f8792 100644
--- a/Jenkinsfile_publish.groovy
+++ b/Jenkinsfile_publish.groovy
@@ -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')]) {
diff --git a/Tools/create_upg_chk_files.ps1 b/Tools/create_upg_chk_files.ps1
index 28d539549..acf2e88a9 100644
--- a/Tools/create_upg_chk_files.ps1
+++ b/Tools/create_upg_chk_files.ps1
@@ -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
\ No newline at end of file
+# 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"
\ No newline at end of file
diff --git a/Tools/github_functions.ps1 b/Tools/github_functions.ps1
new file mode 100644
index 000000000..8f38fbda4
--- /dev/null
+++ b/Tools/github_functions.ps1
@@ -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
+}
\ No newline at end of file
diff --git a/Tools/publish_draft_github_release.ps1 b/Tools/publish_draft_github_release.ps1
new file mode 100644
index 000000000..ab5f0ec87
--- /dev/null
+++ b/Tools/publish_draft_github_release.ps1
@@ -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
\ No newline at end of file
diff --git a/Tools/publish_to_github.ps1 b/Tools/publish_to_github.ps1
index 6a8344321..4f920a0d8 100644
--- a/Tools/publish_to_github.ps1
+++ b/Tools/publish_to_github.ps1
@@ -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)
\ No newline at end of file
diff --git a/Tools/validate_microsoft_tool.ps1 b/Tools/validate_microsoft_tool.ps1
new file mode 100644
index 000000000..96329658a
--- /dev/null
+++ b/Tools/validate_microsoft_tool.ps1
@@ -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
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj
index 8e381f8b1..9f544709f 100644
--- a/mRemoteNGTests/mRemoteNGTests.csproj
+++ b/mRemoteNGTests/mRemoteNGTests.csproj
@@ -310,11 +310,11 @@
-
\ No newline at end of file
diff --git a/mRemoteV1/App/Logger.cs b/mRemoteV1/App/Logger.cs
index 2f015f54a..4031e0587 100644
--- a/mRemoteV1/App/Logger.cs
+++ b/mRemoteV1/App/Logger.cs
@@ -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();
diff --git a/mRemoteV1/App/Runtime.cs b/mRemoteV1/App/Runtime.cs
index 317c34249..5a650713c 100644
--- a/mRemoteV1/App/Runtime.cs
+++ b/mRemoteV1/App/Runtime.cs
@@ -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()
diff --git a/mRemoteV1/Config/Connections/Multiuser/SqlConnectionsUpdateChecker.cs b/mRemoteV1/Config/Connections/Multiuser/SqlConnectionsUpdateChecker.cs
index d88b88987..8cc7daf4b 100644
--- a/mRemoteV1/Config/Connections/Multiuser/SqlConnectionsUpdateChecker.cs
+++ b/mRemoteV1/Config/Connections/Multiuser/SqlConnectionsUpdateChecker.cs
@@ -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()
diff --git a/mRemoteV1/Connection/DefaultConnectionInheritance.cs b/mRemoteV1/Connection/DefaultConnectionInheritance.cs
index 1dc37f64a..b55ca8634 100644
--- a/mRemoteV1/Connection/DefaultConnectionInheritance.cs
+++ b/mRemoteV1/Connection/DefaultConnectionInheritance.cs
@@ -1,4 +1,5 @@
using System;
+using mRemoteNG.App;
namespace mRemoteNG.Connection
@@ -17,11 +18,17 @@ namespace mRemoteNG.Connection
public void LoadFrom(TSource sourceInstance, Func 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 destinationInstance, Func 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);
}
}
diff --git a/mRemoteV1/Connection/Protocol/IntegratedProgram.cs b/mRemoteV1/Connection/Protocol/IntegratedProgram.cs
index 9c24c2d0e..e807ecd53 100644
--- a/mRemoteV1/Connection/Protocol/IntegratedProgram.cs
+++ b/mRemoteV1/Connection/Protocol/IntegratedProgram.cs
@@ -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();
diff --git a/mRemoteV1/Resources/Language/Language.Designer.cs b/mRemoteV1/Resources/Language/Language.Designer.cs
index 3055c2219..e4699c9ed 100644
--- a/mRemoteV1/Resources/Language/Language.Designer.cs
+++ b/mRemoteV1/Resources/Language/Language.Designer.cs
@@ -8,18 +8,18 @@
//
//------------------------------------------------------------------------------
-namespace mRemoteNG {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // 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
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // 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 {
}
///
- /// 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!.
///
internal static string strCannotImportNormalSessionFile {
@@ -665,9 +665,9 @@ namespace mRemoteNG {
}
///
- /// 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 "C:\Program Files\mRemoteNG\eolwtscom.dll" (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 "C:\Program Files\mRemoteNG\eolwtscom.dll" (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]";.
///
internal static string strCcEOLFailed {
@@ -686,9 +686,9 @@ namespace mRemoteNG {
}
///
- /// 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]";.
///
internal static string strCcGeckoFailed {
@@ -707,8 +707,8 @@ namespace mRemoteNG {
}
///
- /// 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 "c:\Program Files\Citrix\ICA Client\wfica.ocx" (Where c:\Program Files\Citrix\ICA Client\ is the path to your XenDesktop Online Plugin installat [rest of string was truncated]";.
///
internal static string strCcICAFailed {
@@ -718,7 +718,7 @@ namespace mRemoteNG {
}
///
- /// 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}.
///
internal static string strCcICAOK {
@@ -737,7 +737,7 @@ namespace mRemoteNG {
}
///
- /// 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).
///
internal static string strCcPuttyFailed {
@@ -756,7 +756,7 @@ namespace mRemoteNG {
}
///
- /// 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/..
///
internal static string strCcRDPFailed {
@@ -766,7 +766,7 @@ namespace mRemoteNG {
}
///
- /// 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}.
///
internal static string strCcRDPOK {
@@ -776,8 +776,8 @@ namespace 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\).
+ /// 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/.
///
internal static string strCcVNCFailed {
@@ -787,7 +787,7 @@ namespace mRemoteNG {
}
///
- /// 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}.
///
internal static string strCcVNCOK {
@@ -1166,7 +1166,7 @@ namespace mRemoteNG {
}
///
- /// 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:
///"{0}"?.
///
internal static string strConfirmCloseConnectionMainInstruction {
@@ -1347,8 +1347,8 @@ namespace mRemoteNG {
}
///
- /// 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}.
///
internal static string strConnectionRdpErrorDetail {
@@ -1403,7 +1403,7 @@ namespace mRemoteNG {
}
///
- /// Looks up a localized string similar to Connections file "{0}" could not be loaded!
+ /// Looks up a localized string similar to Connections file "{0}" could not be loaded!
///Starting with new connections file..
///
internal static string strConnectionsFileCouldNotBeLoadedNew {
@@ -1539,8 +1539,8 @@ namespace mRemoteNG {
}
///
- /// 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..
///
internal static string strCredentialManagerUpgradeDescription {
@@ -1838,10 +1838,10 @@ namespace mRemoteNG {
}
///
- /// Looks up a localized string similar to The Windows security setting, "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing", 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, "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing", 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..
///
internal static string strErrorFipsPolicyIncompatible {
@@ -3867,7 +3867,7 @@ namespace mRemoteNG {
}
///
- /// 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!.
///
internal static string strOldConffile {
@@ -5236,8 +5236,8 @@ namespace mRemoteNG {
}
///
- /// Looks up a localized string similar to Protocol Event Disconnected.
- ///Message:
+ /// Looks up a localized string similar to Protocol Event Disconnected.
+ ///Message:
///{0}.
///
internal static string strProtocolEventDisconnected {
@@ -5247,7 +5247,7 @@ namespace mRemoteNG {
}
///
- /// Looks up a localized string similar to Protocol Event Disconnected failed.
+ /// Looks up a localized string similar to Protocol Event Disconnected failed.
///{0}.
///
internal static string strProtocolEventDisconnectFailed {
@@ -7093,7 +7093,7 @@ namespace mRemoteNG {
}
///
- /// 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..
///
internal static string strUpdateDownloadComplete {
diff --git a/mRemoteV1/Resources/Language/Language.ja-JP.resx b/mRemoteV1/Resources/Language/Language.ja-JP.resx
index 69086f585..dd31088d5 100644
--- a/mRemoteV1/Resources/Language/Language.ja-JP.resx
+++ b/mRemoteV1/Resources/Language/Language.ja-JP.resx
@@ -246,7 +246,7 @@
You cannot import a normal connection file.
-Please use File - Load Connections for normal connection files!
+Please use File - Open Connection File for normal connection files!
IPアドレスのフォーマットが正しくないのでポートスキャンの開始に失敗しました
diff --git a/mRemoteV1/Resources/Language/Language.resx b/mRemoteV1/Resources/Language/Language.resx
index 06c729829..2f6014289 100644
--- a/mRemoteV1/Resources/Language/Language.resx
+++ b/mRemoteV1/Resources/Language/Language.resx
@@ -245,7 +245,7 @@
You cannot import a normal connection file.
-Please use File - Load Connections for normal connection files!
+Please use File - Open Connection File for normal connection files!
Cannot start Port Scan, incorrect IP format!
diff --git a/mRemoteV1/Resources/PuTTYNG.exe b/mRemoteV1/Resources/PuTTYNG.exe
index 78dbd246e..429c3e636 100644
Binary files a/mRemoteV1/Resources/PuTTYNG.exe and b/mRemoteV1/Resources/PuTTYNG.exe differ
diff --git a/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs b/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
index b36aff7a9..bf6cfa005 100644
--- a/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
+++ b/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
@@ -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 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;
diff --git a/mRemoteV1/Tools/ExternalTool.cs b/mRemoteV1/Tools/ExternalTool.cs
index d38bf8095..31c384405 100644
--- a/mRemoteV1/Tools/ExternalTool.cs
+++ b/mRemoteV1/Tools/ExternalTool.cs
@@ -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;
}
diff --git a/mRemoteV1/Tools/ExternalToolArgumentParser.cs b/mRemoteV1/Tools/ExternalToolArgumentParser.cs
index 6e697ea12..edbb1d2b3 100644
--- a/mRemoteV1/Tools/ExternalToolArgumentParser.cs
+++ b/mRemoteV1/Tools/ExternalToolArgumentParser.cs
@@ -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;
diff --git a/mRemoteV1/Tools/IeBrowserEmulation.cs b/mRemoteV1/Tools/IeBrowserEmulation.cs
index 11a0fe10a..b7e9fba87 100644
--- a/mRemoteV1/Tools/IeBrowserEmulation.cs
+++ b/mRemoteV1/Tools/IeBrowserEmulation.cs
@@ -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
}
diff --git a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
index 5c3a5cc70..0b3146e54 100644
--- a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
+++ b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
@@ -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
}
}
\ No newline at end of file
diff --git a/mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs b/mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
index 5d6c0d6a4..d6f8ec24a 100644
--- a/mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
+++ b/mRemoteV1/UI/Controls/ConnectionTree/NameColumn.cs
@@ -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;
}
diff --git a/mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs b/mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
index f0de81334..a54be6e3b 100644
--- a/mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
+++ b/mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
@@ -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[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[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;
//
diff --git a/mRemoteV1/UI/Window/PortScanWindow.cs b/mRemoteV1/UI/Window/PortScanWindow.cs
index 8e9bb83ca..d8cdced92 100644
--- a/mRemoteV1/UI/Window/PortScanWindow.cs
+++ b/mRemoteV1/UI/Window/PortScanWindow.cs
@@ -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