Compare commits

...

63 Commits

Author SHA1 Message Date
David Sparer
9e358309e4 Merge branch 'master' into resolve_sql_deserialization_issue 2017-03-24 12:14:26 -06:00
David Sparer
485438f38d Merge pull request #472 from mRemoteNG/fix_jenkinsfile_publish
fixed hard coded branch names in jenkinsfile_publish
2017-03-24 12:06:55 -06:00
David Sparer
fe26a60337 fixed hard coded branch names in jenkinsfile_publish 2017-03-24 12:04:52 -06:00
David Sparer
d2c2de4dd7 Merge branch 'master' into resolve_sql_deserialization_issue 2017-03-24 11:42:01 -06:00
David Sparer
d49d58f7f8 fixed parent reference update issue in mRemoteNGImporter 2017-03-24 11:40:28 -06:00
David Sparer
164d4fff8b Merge pull request #470 from mRemoteNG/pipeline_tests
Create jenkins pipeline script for release automation
2017-03-23 16:46:13 -06:00
David Sparer
7726406674 added loggers to the test runners 2017-03-23 09:40:31 -06:00
David Sparer
ed38b39fec attempting to resolve bug with accessing correct key store 2017-03-23 08:59:09 -06:00
David Sparer
9188d4316e fix variable issue 2017-03-23 08:52:24 -06:00
David Sparer
cf374c6b8b added cert password as an auto-injected resource 2017-03-23 08:29:47 -06:00
David Sparer
82388dcbc3 added finger-printing to artifacting step 2017-03-23 08:26:18 -06:00
David Sparer
7a6a99e2b6 attempting to use the publishing jenkinsfile from scm 2017-03-23 08:08:29 -06:00
David Sparer
c383736834 more debug code 2017-03-22 17:06:30 -06:00
David Sparer
6e5e78df3b investigating certificate unlock issues 2017-03-22 17:03:38 -06:00
David Sparer
311bf1b641 fix issue with retrieving fuzzy file name 2017-03-22 16:48:38 -06:00
David Sparer
5c9933791c do base64 decoding in the script 2017-03-22 16:39:47 -06:00
David Sparer
039d4d11aa add a cast to help aleviate bat file issues 2017-03-22 16:33:12 -06:00
David Sparer
c0f2d2aa84 fixed bug 2017-03-22 16:27:28 -06:00
David Sparer
45099bfa07 try to get around weird type casting issue 2017-03-22 16:22:53 -06:00
David Sparer
695ae9d970 added script for publishing a release to github 2017-03-22 14:41:35 -06:00
David Sparer
21eb0064b1 enable code signing for installer 2017-03-22 08:45:25 -06:00
David Sparer
513fe402af signed the firefox binaries 2017-03-21 12:47:47 -06:00
David Sparer
b27e5754e8 fix arg passing 2017-03-21 12:07:49 -06:00
David Sparer
fa7231d77b added puttyng.exe to the sign files exclusion list 2017-03-21 11:52:52 -06:00
David Sparer
f5a30ecb33 added some more support for excluding files from signing 2017-03-21 11:42:50 -06:00
David Sparer
7f22289889 add previously signed puttyng binary 2017-03-21 11:21:12 -06:00
David Sparer
f80c39077a Added ability to exclude items from signing 2017-03-21 11:19:09 -06:00
David Sparer
75c60a1cc4 release certificate resources after we've used them 2017-03-21 11:16:05 -06:00
David Sparer
2cf38d6b7c removed some debug code 2017-03-21 11:15:16 -06:00
David Sparer
482c9c1574 added some temp debugging code 2017-03-21 11:10:33 -06:00
David Sparer
882e59a260 normalized the unit test output folder for the portable builds 2017-03-21 10:55:18 -06:00
David Sparer
7a036956b7 added some certificate checks to be more sure that the editbin we're using is legit 2017-03-21 10:29:48 -06:00
David Sparer
7520b20cf9 fixed bug in setting largeaddressaware 2017-03-21 10:28:49 -06:00
David Sparer
d47ccd75d5 Revert "removed unnecessary build configs for the unit tests project"
This reverts commit 56ff81a0ed.
2017-03-21 10:20:20 -06:00
David Sparer
56ff81a0ed removed unnecessary build configs for the unit tests project
im not even sure we need to distinguish between debug and portable builds, but ill leave it like this for now
2017-03-21 10:10:48 -06:00
David Sparer
8db76f5324 actually fix the sensitive param leakage 2017-03-18 17:25:30 -06:00
David Sparer
a9442ea06e added some error output for cert loading action 2017-03-18 16:30:03 -06:00
David Sparer
92bd0d3ea0 do not echo sensitive params 2017-03-18 16:29:44 -06:00
David Sparer
512d7322b2 request cert path and password as script parameters 2017-03-18 16:13:20 -06:00
David Sparer
45645c439f test of msbuild param passing 2017-03-18 15:13:23 -06:00
David Sparer
84ebb82cae the installer project now uses a powershell script for post build actions 2017-03-18 00:24:39 -06:00
David Sparer
576f6a3bd6 fixed issue with tidying release files 2017-03-18 00:24:07 -06:00
David Sparer
96df821eca changed signature failures from errors to warnings 2017-03-18 00:23:44 -06:00
David Sparer
8589778e92 split postbuild actions into powershell scripts 2017-03-17 23:53:59 -06:00
David Sparer
a8a7de9ee6 began converting all post build actions to powershell 2017-03-17 18:01:08 -06:00
David Sparer
1d99340425 remove quoting 2017-03-17 16:33:27 -06:00
David Sparer
a8cdfb56f3 single quote might be safer 2017-03-17 16:18:20 -06:00
David Sparer
0958cdaa2d ensure paths are quoted 2017-03-17 16:13:12 -06:00
David Sparer
ebfb3dd31e added a build config for the installer 2017-03-17 16:01:50 -06:00
David Sparer
3943b8753f split releases 2017-03-10 14:41:14 -07:00
David Sparer
9e26ea1866 bumped assembly version 2017-03-10 14:26:35 -07:00
David Sparer
8152a87514 bumped patch version 2017-03-10 14:20:23 -07:00
David Sparer
b28775c2c6 made sqlbulkcopy column-position independant 2017-03-10 14:18:55 -07:00
David Sparer
3eb96ef765 set changelog and bumped patch version 2017-03-10 11:40:20 -07:00
David Sparer
8805584cbe updated sql code
- added upgrade script to bring db version up to 2.6
- refactored db upgrade code to a new class
- resolved an issue with db column naming for one of the new features
- updated new sql db creation script
2017-03-10 11:13:26 -07:00
David Sparer
be5c66bd93 Merge pull request #438 from mRemoteNG/1_75_hotfixes
1.75 hotfix 1
2017-03-06 10:33:04 -07:00
David Sparer
5347e5a3aa implemented new versioning scheme. resolves #437 2017-03-06 10:27:25 -07:00
David Sparer
9b22254b6c update changelog 2017-03-06 10:24:41 -07:00
David Sparer
6a67e0ea8b resolved issue with export filter not being respected. resolves #427 2017-03-02 16:42:00 -07:00
David Sparer
7b118995ea updated changelog 2017-03-02 13:26:40 -07:00
David Sparer
35b4564644 turned off a feature of ObjectListView that was stealing focus from keepass autotype events. resolves #312 2017-03-02 13:02:51 -07:00
David Sparer
30df947365 resolved issue when clicking in connection tree white space #422 2017-03-02 08:55:10 -07:00
David Sparer
b1ec975612 Merge pull request #425 from mRemoteNG/1_75_release
1 75 release
2017-03-02 08:51:19 -07:00
55 changed files with 912 additions and 200 deletions

View File

@@ -1,3 +1,37 @@
1.75.7003 (2017-03-24):
Fixes:
------
#464: Resolved issue when importing a connections file while using SQL server feature
1.75.7002 (2017-03-10):
Fixes:
------
#448: Resolved issue with SQL saving
1.75.7001 (2017-03-10):
Fixes:
------
#408: Update SQL scripts
1.75 hotfix 1 (2017-03-06):
General Changes:
----------------
#437: Modify version numbering scheme
Fixes:
------
#422: Uncaught exception when clicking in connection tree whitespace
#312: Resolved KeePass auto-type issue
#427: Export does not respect filtering user/password/domain
1.75 (2017-03-01):
Known Issue:

View File

@@ -114,22 +114,6 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Portable|x86' ">
<DefineConstants>HarvestPath=$(SolutionDir)mRemoteV1\bin\Release Portable;HelpFilesHarvestPath=$(SolutionDir)mRemoteV1\Resources\Help</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>set /p buildenv=&lt;buildenv.tmp
REM Sign MSI
IF EXIST C:\mRemoteNG_code_signing_cert.pfx (
IF %25buildenv: Portable=%25==Release (
powershell "&amp;""$(SolutionDir)Tools\signfiles.ps1""" %27%25cd%25%27
)
)
REM Rename MSI to include version number
powershell -ExecutionPolicy Bypass -File "$(SolutionDir)Tools\rename_installer_with_version.ps1" $(SolutionDir)
REM Copy MSI to Release folder
IF %25buildenv: Portable=%25==Release (powershell -ExecutionPolicy Bypass -File "$(SolutionDir)Tools\copy_release_installer.ps1" $(TargetDir) $(SolutionDir)Release)</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PreBuildEvent>REM Clean the TargetDir
rmdir /S /Q "$(TargetDir)"
@@ -142,4 +126,19 @@ call "$(WIX)bin\heat.exe" dir "$(SolutionDir)mRemoteV1\bin\$(Configuration)" -ag
REM Convert the license file "COPYING.TXT" to "License.rtf" to be shown in the installer GUI
call "$(ProjectDir)Resources\Pandoc\pandoc.exe" -s -t rtf -o "$(ProjectDir)\Resources\License.rtf" "$(SolutionDir)COPYING.TXT"</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>:: When passing paths to powershell scripts, check if the path ends with a backslash "\"
:: If it does, then the backslash may be interpreted as an escape character. Add another backslash to cancel the first one.
powershell -noprofile -command "sleep 2"
set /p buildenv=&lt;buildenv.tmp
set solutionDir=$(SolutionDir)\
set targetDir=%25cd%25
set psScriptsDir=$(SolutionDir)Tools
set certPath=$(CertPath)
set certPassword=$(CertPassword)
:: Call the post build powershell script
powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_installer.ps1" -SolutionDir "%25solutionDir%25" -TargetDir "%25targetDir%25" -TargetFileName "mRemoteNG.exe" -ConfigurationName "%25buildenv%25" -CertificatePath "%25certPath%25" -CertificatePassword "%25certPassword%25"</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,63 @@
node('windows') {
def jobDir = pwd()
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
def vsToolsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools"
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
def nunitTestAdapterPath = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\VisualStudio\\14.0\\Extensions"
stage ('Clean output dir') {
bat script: "rmdir /S /Q \"${jobDir}\\Release\" 2>nul", returnStatus: true
}
stage ('Checkout Branch') {
checkout([
$class: 'GitSCM',
branches: [[name: '*/${env.TargetBranch}']],
doGenerateSubmoduleConfigurations: false,
extensions: [],
submoduleCfg: [],
userRemoteConfigs: [[
credentialsId: '9c3fbff4-5b90-402f-a298-00e607fcec87',
url: 'https://github.com/mRemoteNG/mRemoteNG.git'
]]
])
}
stage ('Restore NuGet Packages') {
def nugetPath = "C:\\nuget.exe"
bat "${nugetPath} restore ${solutionFilePath}"
}
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\""
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\""
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
}
}
}
stage ('Run Unit Tests (Normal - MSI)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release\\mRemoteNGTests.dll\""
}
stage ('Run Unit Tests (Portable)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release Portable\\mRemoteNGTests.dll\""
}
stage ('Publish to GitHub') {
withCredentials([string(credentialsId: '5443a369-dbe8-42d3-b4e8-04d0b4e9039a', variable: 'GH_AUTH_TOKEN')]) {
def zipPath = "${jobDir}\\Release\\*.msi"
def msiPath = "${jobDir}\\Release\\*.zip"
// because batch files suck at handling newline characters, we have to convert to base64 in groovy and back to text in powershell
def base64Description = env.ReleaseDescription.bytes.encodeBase64().toString()
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\publish_to_github.ps1\" -Owner \"mRemoteNG\" -Repository \"mRemoteNG\" -ReleaseTitle \"${env.ReleaseTitle}\" -TagName \"${env.TagName}\" -TargetCommitish \"${env.TargetBranch}\" -Description \"${base64Description}\" -IsDraft ${env.IsDraft} -IsPrerelease ${env.IsPreRelease} -ZipFilePath \"${zipPath}\" -MsiFilePath \"${msiPath}\" -AuthToken \"${env.GH_AUTH_TOKEN}\" -DescriptionIsBase64Encoded"
}
}
}

15
Tools/copy_puttyng.ps1 Normal file
View File

@@ -0,0 +1,15 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
Write-Output "Copying PUTTYNG to correct directory"
Copy-Item -Path (Join-Path -Path $SolutionDir -ChildPath "mRemoteV1\Resources\PuTTYNG.exe") -Destination $TargetDir -Force
Write-Output ""

View File

@@ -1,16 +1,21 @@
$sourcePath = $args[0]
$destinationDir = $args[1]
param (
[string]
$SourcePath,
Write-Host $sourcePath
Write-Host $destinationDir
[string]
$DestinationDir
)
if (!(Test-Path -Path $destinationDir))
Write-Host $SourcePath
Write-Host $DestinationDir
if (!(Test-Path -Path $DestinationDir))
{
New-Item -Path $destinationDir -ItemType "directory"
New-Item -Path $DestinationDir -ItemType "directory"
}
$sourceFiles = Get-ChildItem -Path $sourcePath -Recurse | ?{$_.Extension -match "exe|msi"}
$sourceFiles = Get-ChildItem -Path $SourcePath -Recurse | ?{$_.Extension -match "exe|msi"}
foreach ($item in $sourceFiles)
{
Copy-Item -Path $item.FullName -Destination $destinationDir -Force
Copy-Item -Path $item.FullName -Destination $DestinationDir -Force
}

23
Tools/move_help_files.ps1 Normal file
View File

@@ -0,0 +1,23 @@
param (
[string]
[Parameter(Mandatory=$true)]
$TargetDir
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
$path_HelpFilesDir = Join-Path -Path $TargetDir -ChildPath "Help"
Write-Output "Moving Help files to correct directory"
# Remove stale Help files, if they exist
if (Test-Path -Path $path_HelpFilesDir) {
Remove-Item -Path $path_HelpFilesDir -Recurse -Force
}
# Move Help files
Move-Item -Path (Join-Path -Path $TargetDir -ChildPath "Resources\Help") -Destination $path_HelpFilesDir -Force
Start-Sleep -Seconds 2
Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "Resources") -Recurse -Force
Write-Output ""

View File

@@ -0,0 +1,43 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$TargetFileName,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName,
[string]
$CertificatePath,
[string]
$CertificatePassword,
[string[]]
$ExcludeFromSigning
)
Write-Output "+=================================================================+"
Write-Output "| Beginning mRemoteNG Installer Post Build |"
Write-Output "+=================================================================+"
Format-Table -AutoSize -Wrap -InputObject @{
"SolutionDir" = $SolutionDir
"TargetDir" = $TargetDir
"TargetFileName" = $TargetFileName
"ConfigurationName" = $ConfigurationName
"ExcludeFromSigning" = $ExcludeFromSigning
}
& "$PSScriptRoot\sign_binaries.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning
& "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
& "$PSScriptRoot\rename_installer_with_version.ps1" -SolutionDir $SolutionDir
& "$PSScriptRoot\copy_release_installer.ps1" -SourcePath $TargetDir -DestinationDir (Join-Path -Path $SolutionDir -ChildPath "Release")

View File

@@ -0,0 +1,47 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$TargetFileName,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName,
[string]
$CertificatePath,
[string]
$CertificatePassword,
[string[]]
$ExcludeFromSigning
)
Write-Output "+=================================================================+"
Write-Output "| Beginning mRemoteV1 Post Build |"
Write-Output "+=================================================================+"
Format-Table -AutoSize -Wrap -InputObject @{
"SolutionDir" = $SolutionDir
"TargetDir" = $TargetDir
"TargetFileName" = $TargetFileName
"ConfigurationName" = $ConfigurationName
"ExcludeFromSigning" = $ExcludeFromSigning
}
& "$PSScriptRoot\copy_puttyng.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir
& "$PSScriptRoot\move_help_files.ps1" -TargetDir $TargetDir
& "$PSScriptRoot\set_LargeAddressAware.ps1" -TargetDir $TargetDir -TargetFileName $TargetFileName
& "$PSScriptRoot\tidy_files_for_release.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
& "$PSScriptRoot\sign_binaries.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning
& "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
& "$PSScriptRoot\zip_portable_files.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName

168
Tools/publish_to_github.ps1 Normal file
View File

@@ -0,0 +1,168 @@
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,
[string]
[Parameter(Mandatory=$true)]
[ValidateSet("true","false")]
# true/false
$IsDraft,
[string]
[Parameter(Mandatory=$true)]
[ValidateSet("true","false")]
# true/false
$IsPrerelease,
[string]
[Parameter(Mandatory=$true)]
# Path to the zip file to upload with the release
$ZipFilePath,
[string]
[Parameter(Mandatory=$true)]
#Path to the msi file to upload with the release
$MsiFilePath,
[string]
[Parameter(Mandatory=$true)]
# The OAuth2 token to use for authentication.
$AuthToken,
[switch]
# Enable this switch to treat $Description as a Base64 encoded string. It will be decoded before being used elsewhere in the script.
$DescriptionIsBase64Encoded
)
$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
}
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 "binary/octetstream" -AuthToken $AuthToken
Write-Output $release

View File

@@ -1,11 +1,15 @@
$solutionDir = $args[0]
$renameTarget = $solutionDir + "InstallerProjects\Installer\bin\Release\en-US\mRemoteNG-Installer.msi"
param (
[string]
$SolutionDir
)
Write-Host $solutionDir
$renameTarget = $SolutionDir + "InstallerProjects\Installer\bin\Release\en-US\mRemoteNG-Installer.msi"
Write-Host $SolutionDir
Write-Host $renameTarget
$targetVersionedFile = "$solutionDir\mRemoteV1\bin\Release\mRemoteNG.exe"
$version = &"$solutionDir\Tools\sigcheck.exe" /accepteula -q -n $targetVersionedFile
$targetVersionedFile = "$SolutionDir\mRemoteV1\bin\Release\mRemoteNG.exe"
$version = &"$SolutionDir\Tools\sigcheck.exe" /accepteula -q -n $targetVersionedFile
$renameTargetFileObject = Get-Item -Path $renameTarget -ErrorAction SilentlyContinue

View File

@@ -0,0 +1,30 @@
param (
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$TargetFileName
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
# Find editbin.exe
$path_editBin = @((Resolve-Path -Path "C:\Program Files*\Microsoft Visual Studio*\VC\bin\editbin.exe").Path)[0]
# Verify editbin certificate
$microsoft_cert_thumbprint = "3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC"
$editbin_signature = Get-AuthenticodeSignature -FilePath $path_editBin
if (($editbin_signature.Status -ne "Valid") -or ($editbin_signature.SignerCertificate.Thumbprint -ne $microsoft_cert_thumbprint)) {
Write-Error "Could not validate the signature of editbin.exe - we can not set LargeAddressAware" -ErrorAction Stop
}
$path_outputExe = Join-Path -Path $TargetDir -ChildPath $TargetFileName
# Set LargeAddressAware
Write-Output "Setting LargeAddressAware on binary file `"$path_outputExe`""
& $path_editBin "/largeaddressaware" "$path_outputExe"
Write-Output ""

80
Tools/sign_binaries.ps1 Normal file
View File

@@ -0,0 +1,80 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName,
[string[]]
# File names to exclude from signing
$Exclude,
[string]
# The code signing certificate to use when signing the files.
$CertificatePath,
[string]
# Password to unlock the code signing certificate.
$CertificatePassword
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
$timeserver = "http://timestamp.verisign.com/scripts/timstamp.dll"
if ($ConfigurationName -notmatch "Release") {
Write-Output "This is not a release build - we won't sign files."
return
}
if ($CertificatePath -eq "" -or !(Test-Path -Path $CertificatePath -PathType Leaf)) {
Write-Output "Certificate is not present - we won't sign files."
return
}
if ($CertificatePassword -eq "") {
Write-Output "No certificate password was provided - we won't sign files."
return
}
try {
$certKeyStore = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath, $CertificatePassword, $certKeyStore) -ErrorAction Stop
} catch {
Write-Output "Error loading certificate file - we won't sign files."
Write-Output $Error[0]
return
}
# Sign MSI if we are building a release version and the certificate is available
Write-Output "Signing Binaries"
Write-Output "Getting files from path: $TargetDir"
$signableFiles = Get-ChildItem -Path $TargetDir -Recurse | ?{$_.Extension -match "dll|exe|msi"} | ?{$Exclude -notcontains $_.Name}
$excluded_files = Get-ChildItem -Path $TargetDir -Recurse | ?{$_.Extension -match "dll|exe|msi"} | ?{$Exclude -contains $_.Name}
$excluded_files | ForEach-Object `
-Begin { Write-Output "The following files were excluded from signing due to being on the exclusion list:" } `
-Process { Write-Output "-- $($_.FullName)" }
Write-Output "Signable files count: $($signableFiles.Count)"
foreach ($file in $signableFiles) {
Set-AuthenticodeSignature -Certificate $cert -TimestampServer $timeserver -IncludeChain all -FilePath $file.FullName
}
# Release certificate
if ($cert -ne $null) {
$cert.Dispose()
}
Write-Output ""

View File

@@ -1,13 +0,0 @@
$timeserver = "http://timestamp.verisign.com/scripts/timstamp.dll"
$certPath = "C:\mRemoteNG_code_signing_cert.pfx"
$certPassword = (Get-Credential -Message "Enter the password for the certificate" -UserName "USERNAME NOT NEEDED").Password
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath, $certPassword)
$targetPath = $args[0]
Write-Output "Getting files from path: $targetPath"
$signableFiles = Get-ChildItem -Path $targetPath -Recurse | ?{$_.Extension -match "dll|exe|msi"}
Write-Output "Signable files count: $($signableFiles.Count)"
foreach ($file in $signableFiles) {
Set-AuthenticodeSignature -Certificate $cert -TimestampServer $timeserver -IncludeChain all -FilePath $file.FullName
}

View File

@@ -0,0 +1,33 @@
param (
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
# Remove unnecessary files from Release versions
if ($ConfigurationName -match "Release") {
Write-Output "Removing unnecessary files from Release versions"
Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "app.publish") -Recurse -Force
$filesToDelete = Get-ChildItem -Path $TargetDir -Recurse -Include @(
"*.pdb",
"*.publish",
"*.xml",
"*.backup",
"*.log",
"*vshost*",
"*.tmp"
)
Remove-Item -Path $filesToDelete.FullName
Write-Output $filesToDelete.FullName
}
else {
Write-Output "We will not remove anything - this is not a release build."
}
Write-Output ""

View File

@@ -0,0 +1,36 @@
param (
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
# Sign MSI if we are building a release version and the certificate is available
if ($ConfigurationName -match "Release") {
Write-Output "Verifying signature of binaries"
Write-Output "Getting files from path: $TargetDir"
$signableFiles = Get-ChildItem -Path $TargetDir -Recurse | ?{$_.Extension -match "dll|exe|msi"}
Write-Output "Signable files count: $($signableFiles.Count)"
$badSignatureFound = $false
foreach ($file in $signableFiles) {
$signature = Get-AuthenticodeSignature -FilePath $file.FullName
if ($signature.Status -ne "Valid") {
Write-Warning "File $($file.FullName) does not have a valid signature."
$badSignatureFound = $true
}
}
if ($badSignatureFound) {
Write-Output "One or more files were improperly signed."
} else {
Write-Output "All files have valid signatures."
}
} else {
Write-Output "This is not a release build - we won't verify file signatures."
}
Write-Output ""

View File

@@ -0,0 +1,28 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
$path_packageZipScript = Join-Path -Path $SolutionDir -ChildPath "Tools\build-relport.cmd"
# Package Zip
if ($ConfigurationName -match "Release" -and $ConfigurationName -match "Portable") {
Write-Output "Packaging Release Portable ZIP"
& $path_packageZipScript
}
else {
Write-Output "We will not zip anything - this isnt a portable release build."
}
Write-Output ""

View File

@@ -12,13 +12,14 @@ namespace mRemoteNGTests.Config.Serializers
public class XmlConnectionNodeSerializerTests
{
private XmlConnectionNodeSerializer _connectionNodeSerializer;
private ICryptographyProvider _cryptographyProvider;
[SetUp]
public void Setup()
{
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
BlockCipherEngines.AES, BlockCipherModes.GCM);
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString());
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), new SaveFilter());
}
[Test]
@@ -48,8 +49,7 @@ namespace mRemoteNGTests.Config.Serializers
public void AttributesNotSerializedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
{
var saveFilter = new SaveFilter(true);
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
Assert.That(targetAttribute?.Value, Is.EqualTo(string.Empty));
@@ -59,8 +59,7 @@ namespace mRemoteNGTests.Config.Serializers
public void InheritanceNotSerialiedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
{
var saveFilter = new SaveFilter(true);
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
Assert.That(targetAttribute?.Value, Is.EqualTo(false.ToString()));

View File

@@ -28,7 +28,8 @@ namespace mRemoteNGTests.Config.Serializers
public void Setup()
{
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
var saveFilter = new SaveFilter();
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, saveFilter);
_connectionTreeModel = SetupConnectionTreeModel();
}

View File

@@ -20,7 +20,8 @@ namespace mRemoteNGTests.Config.Serializers
{
var connectionTreeModel = SetupConnectionTreeModel();
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider).CompileDocument(connectionTreeModel, false, false);
var saveFilter = new SaveFilter();
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, saveFilter).CompileDocument(connectionTreeModel, false, false);
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
}

View File

@@ -1,7 +1,9 @@
using System.Xml;
using System.Xml.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
@@ -45,6 +47,27 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(connectionNode, Is.Not.Null);
}
[TestCase("Username", "")]
[TestCase("Domain", "")]
[TestCase("Password", "")]
[TestCase("InheritAutomaticResize", "False")]
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
{
_serializer.SaveFilter = new SaveFilter(true);
var connectionInfo = new ConnectionInfo
{
Name = "myConnection",
Username = "somefilteredstuff",
Domain = "somefilteredstuff",
Password = "somefilteredstuff",
Inheritance = {AutomaticResize = true}
};
var serializedConnections = _serializer.Serialize(connectionInfo);
var xdoc = XDocument.Parse(serializedConnections);
var attributeValue = xdoc.Root?.Element("Node")?.Attribute(attributeName)?.Value;
Assert.That(attributeValue, Is.EqualTo(expectedValue));
}
private ConnectionTreeModel SetupConnectionTreeModel()
{
/*

View File

@@ -37,7 +37,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug Portable|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug Portable\</OutputPath>
<OutputPath>bin\Debug Portable\</OutputPath>
<DefineConstants>TRACE;DEBUG;PORTABLE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
@@ -45,7 +45,7 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release Portable|x86'">
<OutputPath>bin\x86\Release Portable\</OutputPath>
<OutputPath>bin\Release Portable\</OutputPath>
<DefineConstants>TRACE;PORTABLE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View File

@@ -20,6 +20,7 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Portable|x86 = Debug Portable|x86
Debug|x86 = Debug|x86
Release Installer|x86 = Release Installer|x86
Release Portable|x86 = Release Portable|x86
Release|x86 = Release|x86
EndGlobalSection
@@ -28,6 +29,8 @@ Global
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|x86.Build.0 = Debug Portable|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x86.ActiveCfg = Debug|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x86.Build.0 = Debug|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|x86.ActiveCfg = Release|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|x86.Build.0 = Release|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|x86.ActiveCfg = Release Portable|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|x86.Build.0 = Release Portable|x86
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x86.ActiveCfg = Release|x86
@@ -36,6 +39,8 @@ Global
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|x86.Build.0 = Debug Portable|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x86.ActiveCfg = Debug|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x86.Build.0 = Debug|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|x86.ActiveCfg = Release|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|x86.Build.0 = Release|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|x86.ActiveCfg = Release Portable|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|x86.Build.0 = Release Portable|x86
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|x86.ActiveCfg = Release|x86
@@ -43,11 +48,14 @@ Global
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|x86.ActiveCfg = Debug|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x86.ActiveCfg = Debug|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x86.Build.0 = Debug|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer|x86.ActiveCfg = Release|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer|x86.Build.0 = Release|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Portable|x86.ActiveCfg = Release|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|x86.ActiveCfg = Release|x86
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|x86.Build.0 = Release|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug Portable|x86.ActiveCfg = Debug Portable|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|x86.ActiveCfg = Debug|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|x86.ActiveCfg = Release|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|x86.Build.0 = Release|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Portable|x86.ActiveCfg = Release Portable|x86
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release|x86.ActiveCfg = Release|x86
EndGlobalSection

View File

@@ -23,7 +23,9 @@ namespace mRemoteNG.Config.Connections
{
var connector = new SqlDatabaseConnector();
var dataProvider = new SqlDataProvider(connector);
var dataTable = dataProvider.Load();
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
databaseVersionVerifier.VerifyDatabaseVersion();
var dataTable = dataProvider.Load();
deserializer = new DataTableDeserializer(dataTable);
}
else

View File

@@ -85,8 +85,9 @@ namespace mRemoteNG.Config.Connections
{
var sqlConnector = new SqlDatabaseConnector();
sqlConnector.Connect();
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
if (!VerifyDatabaseVersion(sqlConnector))
if (!databaseVersionVerifier.VerifyDatabaseVersion())
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
return;
@@ -102,83 +103,6 @@ namespace mRemoteNG.Config.Connections
sqlConnector.Dispose();
}
private bool VerifyDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
{
var isVerified = false;
try
{
var databaseVersion = GetDatabaseVersion(sqlDatabaseConnector);
SqlCommand sqlCommand;
if (databaseVersion.Equals(new Version()))
{
return true;
}
if (databaseVersion.CompareTo(new Version(2, 2)) == 0) // 2.2
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.3.");
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD EnableFontSmoothing bit NOT NULL DEFAULT 0, EnableDesktopComposition bit NOT NULL DEFAULT 0, InheritEnableFontSmoothing bit NOT NULL DEFAULT 0, InheritEnableDesktopComposition bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
databaseVersion = new Version(2, 3);
}
if (databaseVersion.CompareTo(new Version(2, 3)) == 0) // 2.3
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.4.");
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD UseCredSsp bit NOT NULL DEFAULT 1, InheritUseCredSsp bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
databaseVersion = new Version(2, 4);
}
if (databaseVersion.CompareTo(new Version(2, 4)) == 0) // 2.4
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Upgrading database from version {databaseVersion} to version 2.5.");
sqlCommand = new SqlCommand("ALTER TABLE tblCons ADD LoadBalanceInfo varchar (1024) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, AutomaticResize bit NOT NULL DEFAULT 1, InheritLoadBalanceInfo bit NOT NULL DEFAULT 0, InheritAutomaticResize bit NOT NULL DEFAULT 0;", sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
databaseVersion = new Version(2, 5);
}
if (databaseVersion.CompareTo(new Version(2, 5)) == 0) // 2.5
isVerified = true;
if (isVerified == false)
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, string.Format(Language.strErrorBadDatabaseVersion, databaseVersion, GeneralAppInfo.ProductName));
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.strErrorVerifyDatabaseVersionFailed, ex.Message));
}
return isVerified;
}
private Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
{
Version databaseVersion;
SqlDataReader sqlDataReader = null;
try
{
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
sqlDataReader = sqlCommand.ExecuteReader();
if (!sqlDataReader.HasRows)
return new Version(); // assume new empty database
else
sqlDataReader.Read();
databaseVersion = new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
throw;
}
finally
{
if (sqlDataReader != null && !sqlDataReader.IsClosed)
sqlDataReader.Close();
}
return databaseVersion;
}
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();

View File

@@ -33,9 +33,13 @@ namespace mRemoteNG.Config.DataProviders
{
if (!SqlDatabaseConnector.IsConnected)
OpenConnection();
var sqlBulkCopy = new SqlBulkCopy(SqlDatabaseConnector.SqlConnection) {DestinationTableName = "dbo.tblCons"};
sqlBulkCopy.WriteToServer(dataTable);
sqlBulkCopy.Close();
using (var sqlBulkCopy = new SqlBulkCopy(SqlDatabaseConnector.SqlConnection))
{
foreach (DataColumn col in dataTable.Columns)
sqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
sqlBulkCopy.DestinationTableName = "dbo.tblCons";
sqlBulkCopy.WriteToServer(dataTable);
}
}
public void OpenConnection()

View File

@@ -35,7 +35,7 @@ namespace mRemoteNG.Config.Import
var connectionTreeModel = xmlConnectionsDeserializer.Deserialize(true);
var rootImportContainer = new ContainerInfo { Name = Path.GetFileNameWithoutExtension(fileName) };
rootImportContainer.Children.AddRange(connectionTreeModel.RootNodes.First().Children);
rootImportContainer.AddChildRange(connectionTreeModel.RootNodes.First().Children.ToArray());
destinationContainer.AddChild(rootImportContainer);
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
@@ -33,6 +34,7 @@ namespace mRemoteNG.Config.Serializers
{
var connectionList = CreateNodesFromTable();
var connectionTreeModel = CreateNodeHierarchy(connectionList);
Runtime.IsConnectionsFileLoaded = true;
return connectionTreeModel;
}
@@ -155,8 +157,8 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Inheritance.Username = (bool)dataRow["InheritUsername"];
connectionInfo.Inheritance.ICAEncryptionStrength = (bool)dataRow["InheritICAEncryptionStrength"];
connectionInfo.Inheritance.RDPAuthenticationLevel = (bool)dataRow["InheritRDPAuthenticationLevel"];
connectionInfo.Inheritance.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = (bool)dataRow["RDPMinutesToIdleTimeout"];
connectionInfo.Inheritance.RDPAlertIdleTimeout = (bool)dataRow["InheritRDPAlertIdleTimeout"];
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = (bool)dataRow["InheritRDPMinutesToIdleTimeout"];
connectionInfo.Inheritance.LoadBalanceInfo = (bool)dataRow["InheritLoadBalanceInfo"];
connectionInfo.Inheritance.PreExtApp = (bool)dataRow["InheritPreExtApp"];
connectionInfo.Inheritance.PostExtApp = (bool)dataRow["InheritPostExtApp"];

View File

@@ -41,6 +41,7 @@ namespace mRemoteNG.Config.Serializers
private void CreateSchema()
{
// Note: these columns must be defined in the same order that they exist in the DB
_dataTable.Columns.Add("ID", typeof(int));
_dataTable.Columns[0].AutoIncrement = true;
_dataTable.Columns.Add("ConstantID", typeof(string));
@@ -65,8 +66,6 @@ namespace mRemoteNG.Config.Serializers
_dataTable.Columns.Add("RenderingEngine", typeof(string));
_dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
_dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
_dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
_dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
_dataTable.Columns.Add("Colors", typeof(string));
_dataTable.Columns.Add("Resolution", typeof(string));
_dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
@@ -123,15 +122,12 @@ namespace mRemoteNG.Config.Serializers
_dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
_dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
_dataTable.Columns.Add("InheritRedirectSound", typeof(bool));
_dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
_dataTable.Columns.Add("InheritResolution", typeof(bool));
_dataTable.Columns.Add("InheritUseConsoleSession", typeof(bool));
_dataTable.Columns.Add("InheritUseCredSsp", typeof(bool));
_dataTable.Columns.Add("InheritRenderingEngine", typeof(bool));
_dataTable.Columns.Add("InheritICAEncryptionStrength", typeof(bool));
_dataTable.Columns.Add("InheritRDPAuthenticationLevel", typeof(bool));
_dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
_dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
_dataTable.Columns.Add("InheritUsername", typeof(bool));
_dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
_dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
@@ -159,6 +155,12 @@ namespace mRemoteNG.Config.Serializers
_dataTable.Columns.Add("AutomaticResize", typeof(bool));
_dataTable.Columns.Add("InheritLoadBalanceInfo", typeof(bool));
_dataTable.Columns.Add("InheritAutomaticResize", typeof(bool));
_dataTable.Columns.Add("RDPMinutesToIdleTimeout", typeof(int));
_dataTable.Columns.Add("RDPAlertIdleTimeout", typeof(bool));
_dataTable.Columns.Add("SoundQuality", typeof(string));
_dataTable.Columns.Add("InheritRDPMinutesToIdleTimeout", typeof(bool));
_dataTable.Columns.Add("InheritRDPAlertIdleTimeout", typeof(bool));
_dataTable.Columns.Add("InheritSoundQuality", typeof(bool));
}
private void SetPrimaryKey()
@@ -204,8 +206,8 @@ namespace mRemoteNG.Config.Serializers
dataRow["RenderingEngine"] = connectionInfo.RenderingEngine;
dataRow["ICAEncryptionStrength"] = connectionInfo.ICAEncryptionStrength;
dataRow["RDPAuthenticationLevel"] = connectionInfo.RDPAuthenticationLevel;
//dataRow["RDPMinutesToIdleTimeout"] = connectionInfo.RDPMinutesToIdleTimeout;
//dataRow["RDPAlertIdleTimeout"] = connectionInfo.RDPAlertIdleTimeout;
dataRow["RDPMinutesToIdleTimeout"] = connectionInfo.RDPMinutesToIdleTimeout;
dataRow["RDPAlertIdleTimeout"] = connectionInfo.RDPAlertIdleTimeout;
dataRow["LoadBalanceInfo"] = connectionInfo.LoadBalanceInfo;
dataRow["Colors"] = connectionInfo.Colors;
dataRow["Resolution"] = connectionInfo.Resolution;
@@ -220,7 +222,7 @@ namespace mRemoteNG.Config.Serializers
dataRow["RedirectPrinters"] = connectionInfo.RedirectPrinters;
dataRow["RedirectSmartCards"] = connectionInfo.RedirectSmartCards;
dataRow["RedirectSound"] = connectionInfo.RedirectSound;
//dataRow["SoundQuality"] = connectionInfo.SoundQuality;
dataRow["SoundQuality"] = connectionInfo.SoundQuality;
dataRow["RedirectKeys"] = connectionInfo.RedirectKeys;
dataRow["Connected"] = connectionInfo.OpenConnections.Count > 0;
dataRow["PreExtApp"] = connectionInfo.PreExtApp;
@@ -267,7 +269,7 @@ namespace mRemoteNG.Config.Serializers
dataRow["InheritRedirectPrinters"] = connectionInfo.Inheritance.RedirectPrinters;
dataRow["InheritRedirectSmartCards"] = connectionInfo.Inheritance.RedirectSmartCards;
dataRow["InheritRedirectSound"] = connectionInfo.Inheritance.RedirectSound;
//dataRow["InheritSoundQuality"] = connectionInfo.Inheritance.SoundQuality;
dataRow["InheritSoundQuality"] = connectionInfo.Inheritance.SoundQuality;
dataRow["InheritResolution"] = connectionInfo.Inheritance.Resolution;
dataRow["InheritAutomaticResize"] = connectionInfo.Inheritance.AutomaticResize;
dataRow["InheritUseConsoleSession"] = connectionInfo.Inheritance.UseConsoleSession;
@@ -276,8 +278,8 @@ namespace mRemoteNG.Config.Serializers
dataRow["InheritUsername"] = connectionInfo.Inheritance.Username;
dataRow["InheritICAEncryptionStrength"] = connectionInfo.Inheritance.ICAEncryptionStrength;
dataRow["InheritRDPAuthenticationLevel"] = connectionInfo.Inheritance.RDPAuthenticationLevel;
//dataRow["InheritRDPMinutesToIdleTimeout"] = connectionInfo.Inheritance.RDPMinutesToIdleTimeout;
//dataRow["InheritRDPAlertIdleTimeout"] = connectionInfo.Inheritance.RDPAlertIdleTimeout;
dataRow["InheritRDPMinutesToIdleTimeout"] = connectionInfo.Inheritance.RDPMinutesToIdleTimeout;
dataRow["InheritRDPAlertIdleTimeout"] = connectionInfo.Inheritance.RDPAlertIdleTimeout;
dataRow["InheritLoadBalanceInfo"] = connectionInfo.Inheritance.LoadBalanceInfo;
dataRow["InheritPreExtApp"] = connectionInfo.Inheritance.PreExtApp;
dataRow["InheritPostExtApp"] = connectionInfo.Inheritance.PostExtApp;
@@ -324,7 +326,7 @@ namespace mRemoteNG.Config.Serializers
dataRow["InheritRedirectPrinters"] = false;
dataRow["InheritRedirectSmartCards"] = false;
dataRow["InheritRedirectSound"] = false;
//dataRow["InheritSoundQuality"] = false;
dataRow["InheritSoundQuality"] = false;
dataRow["InheritResolution"] = false;
dataRow["InheritAutomaticResize"] = false;
dataRow["InheritUseConsoleSession"] = false;
@@ -333,8 +335,8 @@ namespace mRemoteNG.Config.Serializers
dataRow["InheritUsername"] = false;
dataRow["InheritICAEncryptionStrength"] = false;
dataRow["InheritRDPAuthenticationLevel"] = false;
//dataRow["InheritRDPMinutesToIdleTimeout"] = false;
//dataRow["InheritRDPAlertIdleTimeout"] = false;
dataRow["InheritRDPMinutesToIdleTimeout"] = false;
dataRow["InheritRDPAlertIdleTimeout"] = false;
dataRow["InheritLoadBalanceInfo"] = false;
dataRow["InheritPreExtApp"] = false;
dataRow["InheritPostExtApp"] = false;

View File

@@ -0,0 +1,158 @@
using System;
using System.Data.SqlClient;
using System.Globalization;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
namespace mRemoteNG.Config.Serializers
{
public class SqlDatabaseVersionVerifier
{
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
public SqlDatabaseVersionVerifier(SqlDatabaseConnector sqlDatabaseConnector)
{
if (sqlDatabaseConnector == null)
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
_sqlDatabaseConnector = sqlDatabaseConnector;
}
public bool VerifyDatabaseVersion()
{
var isVerified = false;
try
{
var databaseVersion = GetDatabaseVersion(_sqlDatabaseConnector);
if (databaseVersion.Equals(new Version()))
{
return true;
}
if (databaseVersion.CompareTo(new Version(2, 2)) == 0) // 2.2
{
UpgradeFrom2_2();
databaseVersion = new Version(2, 3);
}
if (databaseVersion.CompareTo(new Version(2, 3)) == 0) // 2.3
{
UpgradeFrom2_3();
databaseVersion = new Version(2, 4);
}
if (databaseVersion.CompareTo(new Version(2, 4)) == 0) // 2.4
{
UpgradeFrom2_4();
databaseVersion = new Version(2, 5);
}
if (databaseVersion.CompareTo(new Version(2, 5)) == 0) // 2.5
{
UpgradeFrom2_5();
databaseVersion = new Version(2, 6);
}
if (databaseVersion.CompareTo(new Version(2, 6)) == 0) // 2.6
isVerified = true;
if (isVerified == false)
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg,
string.Format(Language.strErrorBadDatabaseVersion, databaseVersion, GeneralAppInfo.ProductName));
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg,
string.Format(Language.strErrorVerifyDatabaseVersionFailed, ex.Message));
}
return isVerified;
}
private Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
{
Version databaseVersion;
SqlDataReader sqlDataReader = null;
try
{
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
if (!sqlDatabaseConnector.IsConnected)
sqlDatabaseConnector.Connect();
sqlDataReader = sqlCommand.ExecuteReader();
if (!sqlDataReader.HasRows)
return new Version(); // assume new empty database
else
sqlDataReader.Read();
databaseVersion =
new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
throw;
}
finally
{
if (sqlDataReader != null && !sqlDataReader.IsClosed)
sqlDataReader.Close();
}
return databaseVersion;
}
private void UpgradeFrom2_2()
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.2 to version 2.3.");
const string sqlText = @"
ALTER TABLE tblCons
ADD EnableFontSmoothing bit NOT NULL DEFAULT 0,
EnableDesktopComposition bit NOT NULL DEFAULT 0,
InheritEnableFontSmoothing bit NOT NULL DEFAULT 0,
InheritEnableDesktopComposition bit NOT NULL DEFAULT 0;";
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
}
private void UpgradeFrom2_3()
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.3 to version 2.4.");
const string sqlText = @"
ALTER TABLE tblCons
ADD UseCredSsp bit NOT NULL DEFAULT 1,
InheritUseCredSsp bit NOT NULL DEFAULT 0;";
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
}
private void UpgradeFrom2_4()
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.4 to version 2.5.");
const string sqlText = @"
ALTER TABLE tblCons
ADD LoadBalanceInfo varchar (1024) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
AutomaticResize bit NOT NULL DEFAULT 1,
InheritLoadBalanceInfo bit NOT NULL DEFAULT 0,
InheritAutomaticResize bit NOT NULL DEFAULT 0;";
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
}
private void UpgradeFrom2_5()
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.5 to version 2.6.");
const string sqlText = @"
ALTER TABLE tblCons
ADD RDPMinutesToIdleTimeout int NOT NULL DEFAULT 0,
RDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
SoundQuality varchar (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL DEFAULT 'Dynamic',
InheritRDPMinutesToIdleTimeout bit NOT NULL DEFAULT 0,
InheritRDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
InheritSoundQuality bit NOT NULL DEFAULT 0;
UPDATE tblRoot
SET ConfVersion='2.6'";
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
sqlCommand.ExecuteNonQuery();
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Security;
using System;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Container;
@@ -13,14 +14,15 @@ namespace mRemoteNG.Config.Serializers
private readonly SecureString _encryptionKey;
private readonly SaveFilter _saveFilter = new SaveFilter();
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
{
_cryptographyProvider = cryptographyProvider;
_encryptionKey = encryptionKey;
}
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey, SaveFilter saveFilter)
{
if (cryptographyProvider == null)
throw new ArgumentNullException(nameof(cryptographyProvider));
if (encryptionKey == null)
throw new ArgumentNullException(nameof(encryptionKey));
if (saveFilter == null)
throw new ArgumentNullException(nameof(saveFilter));
_cryptographyProvider = cryptographyProvider;
_encryptionKey = encryptionKey;
_saveFilter = saveFilter;

View File

@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.Connection;
@@ -14,10 +15,17 @@ namespace mRemoteNG.Config.Serializers
{
private readonly ICryptographyProvider _cryptographyProvider;
private SecureString _encryptionKey;
private readonly SaveFilter _saveFilter;
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider)
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, SaveFilter saveFilter)
{
if (cryptographyProvider == null)
throw new ArgumentNullException(nameof(cryptographyProvider));
if (saveFilter == null)
throw new ArgumentNullException(nameof(saveFilter));
_cryptographyProvider = cryptographyProvider;
_saveFilter = saveFilter;
}
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
@@ -77,7 +85,7 @@ namespace mRemoteNG.Config.Serializers
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)
{
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey);
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey, _saveFilter);
return connectionSerializer.SerializeConnectionInfo(connectionInfo);
}
}

View File

@@ -41,7 +41,7 @@ namespace mRemoteNG.Config.Serializers
var xml = "";
try
{
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, SaveFilter);
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
xml = WriteXmlToString(xmlDocument);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.75.*")]
[assembly: AssemblyVersion("1.75.7003.*")]
[assembly:NeutralResourcesLanguageAttribute("en")]

View File

@@ -34,6 +34,8 @@ CREATE TABLE [dbo].[tblCons] (
[RenderingEngine] [varchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ICAEncryptionStrength] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[RDPAuthenticationLevel] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[RDPMinutesToIdleTimeout] [int] NOT NULL,
[RDPAlertIdleTimeout] [bit] NOT NULL,
[Colors] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Resolution] [varchar] (32) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[DisplayWallpaper] [bit] NOT NULL ,
@@ -46,6 +48,7 @@ CREATE TABLE [dbo].[tblCons] (
[RedirectPrinters] [bit] NOT NULL ,
[RedirectSmartCards] [bit] NOT NULL ,
[RedirectSound] [varchar] (64) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[SoundQuality] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[RedirectKeys] [bit] NOT NULL ,
[Connected] [bit] NOT NULL ,
[PreExtApp] [varchar] (256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
@@ -90,12 +93,15 @@ CREATE TABLE [dbo].[tblCons] (
[InheritRedirectPrinters] [bit] NOT NULL ,
[InheritRedirectSmartCards] [bit] NOT NULL ,
[InheritRedirectSound] [bit] NOT NULL ,
[InheritSoundQuality] [bit] NOT NULL,
[InheritResolution] [bit] NOT NULL ,
[InheritUseConsoleSession] [bit] NOT NULL ,
[InheritUseCredSsp] [bit] NOT NULL ,
[InheritRenderingEngine] [bit] NOT NULL ,
[InheritICAEncryptionStrength] [bit] NOT NULL ,
[InheritRDPAuthenticationLevel] [bit] NOT NULL ,
[InheritRDPMinutesToIdleTimeout] [bit] NOT NULL,
[InheritRDPAlertIdleTimeout] [bit] NOT NULL,
[InheritUsername] [bit] NOT NULL ,
[InheritPreExtApp] [bit] NOT NULL ,
[InheritPostExtApp] [bit] NOT NULL ,

Binary file not shown.

View File

@@ -48,6 +48,7 @@ namespace mRemoteNG.UI.Controls
{
InitializeComponent();
SetupConnectionTreeView();
UseOverlays = false;
}
#region ConnectionTree Setup
@@ -264,7 +265,7 @@ namespace mRemoteNG.UI.Controls
if (mouseEventArgs.Clicks > 1) return;
OLVColumn column;
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var clickedNode = listItem.RowObject as ConnectionInfo;
var clickedNode = listItem?.RowObject as ConnectionInfo;
if (clickedNode == null) return;
SingleClickHandler.Execute(clickedNode);
}

View File

@@ -213,6 +213,7 @@
<Compile Include="Tools\NotificationAreaIcon.cs" />
<Compile Include="Tools\ScanHost.cs" />
<Compile Include="Tools\SecureTransfer.cs" />
<Compile Include="Config\Serializers\SqlDatabaseVersionVerifier.cs" />
<Compile Include="Tree\AlwaysConfirmYes.cs" />
<Compile Include="Tree\SelectedConnectionDeletionConfirmer.cs" />
<Compile Include="Tree\ConnectionTreeDragAndDropHandler.cs" />
@@ -1247,44 +1248,19 @@
<Reference Include="mscorlib" />
</ItemGroup>
<PropertyGroup>
<PostBuildEvent>powershell -noprofile -command "sleep 2"
call "$(DevEnvDir)..\tools\vsvars32.bat"
set /p buildenv=&lt;buildenv.tmp
echo Copy PUTTYNG to correct directory
copy /Y "$(SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" .\
echo Move Help files to correct directory
IF EXIST Help (
del /s /q Help &gt;NUL
rmdir /s /q Help &gt;NUL
)
move /Y Resources\Help .\
<PostBuildEvent>:: When passing paths to powershell scripts, check if the path ends with a backslash "\"
:: If it does, then the backslash may be interpreted as an escape character. Add another backslash to cancel the first one.
powershell -noprofile -command "sleep 2"
rmdir /s /q Resources &gt;NUL
set /p buildenv=&lt;buildenv.tmp
set solutionDir=$(SolutionDir)\
set targetDir=%25cd%25
set psScriptsDir=$(SolutionDir)Tools
set certPath=$(CertPath)
set certPassword=$(CertPassword)
echo Set LargeAddressAware on binary
editbin /largeaddressaware mRemoteNG.exe
IF EXIST C:\mRemoteNG_code_signing_cert.pfx (
echo Signing binaries
IF %25buildenv: Portable=%25==Release (
powershell "&amp;""$(SolutionDir)Tools\signfiles.ps1""" '%25cd%25'
)
)
IF %25buildenv: Portable=%25==Release (
echo Remove unnecessary files from Release versions
rmdir /s /q app.publish
del /q *.pdb *.publish *.xml *.backup *.log *vshost* *.tmp
)
IF %25buildenv: =%25==ReleasePortable (
echo Package ZIP Release Portable
"$(SolutionDir)Tools\build-relport.cmd"
)</PostBuildEvent>
:: Call the post build powershell script
powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremotev1.ps1" -SolutionDir "%25solutionDir%25" -TargetDir "%25targetDir%25" -TargetFileName "mRemoteNG.exe" -ConfigurationName "%25buildenv%25" -CertificatePath "%25certPath%25" -CertificatePassword "%25certPassword%25" -ExcludeFromSigning "PuTTYNG.exe"</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>