Compare commits

..

98 Commits

Author SHA1 Message Date
Sean Kaim
81b0be0489 Merge pull request #588 from mRemoteNG/hotfix7
Hotfix7 changelog
2017-06-14 11:10:19 -04:00
Sean Kaim
3074a211f8 changelog 2017-06-14 11:08:55 -04:00
Sean Kaim
0659b140f5 Merge pull request #587 from mRemoteNG/hotfix7
Hotfix7
2017-06-14 10:59:06 -04:00
Sean Kaim
0b8160ae34 changelog 2017-06-14 10:57:49 -04:00
Sean Kaim
dbf2b7b4b6 increment version 2017-06-14 10:51:24 -04:00
Sean Kaim
1e8afc8ea4 update readme 2017-06-14 10:48:57 -04:00
Sean Kaim
70bd2e8a78 rebuilt & signed puttyng 0.69 2017-06-14 10:48:46 -04:00
Sean Kaim
8045544051 Merge pull request #581 from mRemoteNG/hotfix6
Hotfix6
2017-06-13 11:15:08 -04:00
Sean Kaim
0cef4dc9b3 changelog update 2017-06-13 10:49:05 -04:00
Sean Kaim
f1cfa4330a fix build/porting problem for about window 2017-06-13 10:42:31 -04:00
Sean Kaim
a50b370262 Use all space on about page
Fixed 377
9c5e4f7a7c
2017-06-13 10:24:40 -04:00
Sean Kaim
064fd217ba initial Hotfix 6 commit 2017-06-02 16:45:23 -04:00
David Sparer
692b26622c Merge pull request #534 from mRemoteNG/530_fix_tree_node_entry_creation_on_exttool_run
530 fix tree node entry creation on exttool run
2017-05-02 10:00:30 -06:00
David Sparer
72a56d33d0 updated changelog 2017-05-02 09:08:49 -06:00
David Sparer
ce4bfc55c1 ConnectionInfo.Clone no longer sets the Parent property
this resolves undesirable tree nodes from being created
2017-05-02 08:49:04 -06:00
David Sparer
f0faec9def Merge pull request #528 from mRemoteNG/hotfix5
1.75 Hotfix5
2017-04-27 15:36:16 -06:00
David Sparer
e6ef28050c set release date in changelog for 1.75.7005 2017-04-27 15:20:07 -06:00
David Sparer
547ec3cb3a updated msi installer requirements
Replaced KB2923545 with KB2830477 (which is the REAL rdp 8.1 update)
2017-04-25 21:06:25 -06:00
David Sparer
fc0f278962 signed putty v0.68 exe 2017-04-20 09:27:14 -06:00
David Sparer
1f3db15892 Merge branch '442_fix_importing_putty_session_with_spaces_in_name' into hotfix5 2017-04-20 09:17:22 -06:00
David Sparer
e3e4c49427 changelog update 2017-04-20 09:16:31 -06:00
David Sparer
1520b8bf73 fixed bug where any sessions with spaces in the name would be filtered out
this fixes the bug, but the entire putty sessions loading component should be refactored heavily
2017-04-20 09:07:21 -06:00
David Sparer
c9e7f82905 fixed minor bug with adding a duplicate default session in some situations 2017-04-20 08:53:57 -06:00
Sean Kaim
d2357fa779 changelog update 2017-04-19 12:38:54 -04:00
Sean Kaim
703178ddf1 Fix NPE when importing from the connection tree
Fixes #518
2017-04-19 12:37:56 -04:00
Sean Kaim
4e9c5de16c changelog 2017-04-17 17:34:09 -04:00
Sean Kaim
3d1fcc35df Update credits.txt 2017-04-17 17:30:14 -04:00
Sean Kaim
e20d7afb72 update changelog 2017-04-17 17:29:32 -04:00
Sean Kaim
07e2bc3858 update change log 2017-04-17 11:56:47 -04:00
Sean Kaim
f3b11d6f72 Fix for #434 - SysTray SafeHandle 2017-04-14 17:25:40 -04:00
Sean Kaim
69f310c02c PuTTYNG.exe 0.68 2017-04-14 17:00:22 -04:00
Sean Kaim
3308f1146c load expanded data properly
and minor optimization
2017-04-14 15:50:20 -04:00
Sean Kaim
8e8cf3df8d check for nulls 2017-04-14 15:34:55 -04:00
Sean Kaim
26fdd924ef Increment version number
And make it match the hotfix number - you have no idea how much that was
annoying me...
2017-04-14 14:44:26 -04:00
Sean Kaim
ea3494f6e7 Merge pull request #512 from mRemoteNG/483_make_datatable_serializer_safer
483 make datatable serializer safer
2017-04-14 14:37:33 -04:00
David Sparer
9f028d9104 added some safety checking for data table deserialization
added some tests for the data table deserializer
2017-04-09 17:36:56 -06:00
David Sparer
f40be696c7 made utility for creating test connection tree models 2017-04-09 17:35:52 -06:00
David Sparer
95a503a390 fix issue with setting up data table 2017-04-09 17:05:36 -06:00
David Sparer
88c51f4933 added some safety checks to the data table serialier 2017-04-09 16:57:56 -06:00
David Sparer
686005071e Merge branch 'resolve_sql_deserialization_issue' 2017-03-24 15:26:28 -06:00
David Sparer
e16d31d605 fixed stupid transposition typo 2017-03-24 15:14:57 -06:00
David Sparer
8b201d22cb added authkey requirement to get-githubrelease in order to show drafts 2017-03-24 15:07:31 -06:00
David Sparer
0f6f8d43bd added cmdlet for retrieving a github release 2017-03-24 14:28:18 -06:00
David Sparer
8f171cddd9 fix content type of msi upload to github 2017-03-24 14:23:38 -06:00
David Sparer
c77c323f73 fix jenkinsfile variable 2017-03-24 14:22:17 -06:00
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
65 changed files with 1129 additions and 298 deletions

View File

@@ -1,9 +1,57 @@
1.75.7007 (2017-06-14):
Fixes:
------
#583: SSH (PuTTYNG) Sessions are not properly integrated into the main mRemoteNG window (Sorry!)
1.75.7006 (2017-06-13):
Fixes:
------
#377: Use all space on About page
#527: Additional protections to avoid problems on update check in heavily firewalled environments
#530: Fixed issue where using External Tool on existing connection causes creation of 'New Connection' entry
#531: Update PuTTYNG to 0.69
#546: Quick Connect from notification area icon displays warning when clicking on a folder (see #334)
1.75.7005 (2017-04-27):
Fixes:
------
#410: Update PuTTYNG to 0.68
#434: Fix complier warnings CA1049 & CA2111
#442: Fixed issue loading PuTTY sessions that have spaces in the name
#502: Problems with ParentID for Duplicated Containers/Connections with SQL Connection Storage
#514: Expanded property not saved/loaded properly from SQL
#518: Exception when Importing File
General Changes:
----------------
Minor code cleanup/optimizations/null checks
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
#448: Resolved issue with SQL saving
1.75 hotfix 1 (2017-03-06):

View File

@@ -99,8 +99,8 @@ Copyright
Freely redistributable with attribution
http://www.dotnetmagic.com/magic_download.html
PuTTY 0.67
Copyright <20> 1997-2016 Simon Tatham
PuTTY 0.68
Copyright <20> 1997-2017 Simon Tatham
MIT License
http://www.chiark.greenend.org.uk/~sgtatham/putty/

View File

@@ -17,7 +17,7 @@
<?define RequiredDotNetFrameworkServicePackLevel = "" ?>
<?define RequiredDotNetFrameworkVersion = "$(var.RequiredDotNetFrameworkMajorVersion).$(var.RequiredDotNetFrameworkMinorVersion)" ?>
<?define Rdp80Kb = "KB2592687" ?>
<?define Rdp81Kb = "KB2923545" ?>
<?define Rdp81Kb = "KB2830477" ?>
<?define MinimumRdpKb = $(var.Rdp80Kb) ?>
<?define RdpDtlsKb = "KB2574819" ?>
<?define IGNOREPREREQUISITES = 0 ?>

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

@@ -6,7 +6,7 @@
<String Id="Install_NeedToBeAdminToInstall">You need to be an administrator to install this product.</String>
<String Id="Install_NeedDotNetFrameworkVersion">mRemoteNG requires Microsoft .NET Framework [REQUIREDDOTNETFRAMEWORKVERSION] or higher.</String>
<String Id="Install_OSVersionRequirement">mRemoteNG requires Windows 7 SP1 or higher to run. Please update your operating system and try again.</String>
<String Id="Install_RDP80Requirement">mRemoteNG requires RDP 8.0 or higher to run. Windows 7 users will need to install KB2592687</String>
<String Id="Install_RDP80Requirement">mRemoteNG requires RDP 8.0 or higher to run. Windows 7 users will need to install either KB2592687 (RDP 8.0) or KB2830477 (RDP 8.1)</String>
<String Id="Install_RDPDtlsRequirement">mRemoteNG requires KB2574819 in order to create RDP connections. Windows 7 users will need to install this KB.</String>
<String Id="Install_Win7RequiresSP1">For mRemoteNG to run on Windows 7, it requires Service Pack 1 to be installed. Please install Service Pack 1 and try again.</String>

View File

@@ -67,7 +67,7 @@
<Condition Message="!(loc.Install_RDPDtlsRequirement)">
<![CDATA[Installed OR (IGNOREPREREQUISITES = 1) OR (VersionNT >= 602 OR VersionNT64 >= 602) OR ((VersionNT = 601 OR VersionNT64 = 601) AND (RDP_DTLS_UPDATE_INSTALLED = 1))]]>
</Condition>
<!-- If Win7, require RDP 8.0 update (KB2592687) -->
<!-- If Win7, require RDP 8.0 (KB2592687) or 8.1 (KB2830477) update -->
<Condition Message="!(loc.Install_RDP80Requirement)">
<![CDATA[Installed OR (IGNOREPREREQUISITES = 1) OR (VersionNT >= 602 OR VersionNT64 >= 602) OR ((VersionNT = 601 OR VersionNT64 = 601) AND (MINIMUM_RDP_VERSION_INSTALLED = 1))]]>
</Condition>

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: '*/${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\\*.zip"
def msiPath = "${jobDir}\\Release\\*.msi"
// 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"
}
}
}

View File

@@ -10,8 +10,8 @@
| Update Channel | Build Status | Downloads |
| ---------------|--------------|-----------|
| Stable | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/master)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.74/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74) |
| Beta | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/beta_channel)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/beta_channel/) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.75Beta3/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Beta3) |
| Stable | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/master)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.75Hotfix7/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Hotfix7) |
| Beta | | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.75Hotfix7/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Hotfix7) |
| Development | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/develop)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/develop/) | - |
@@ -26,9 +26,9 @@ Currently these protocols are supported:
* VNC (Virtual Network Computing)
* ICA (Independent Computing Architecture)
* SSH (Secure Shell)
* Telnet (TELecommunication NETwork)
* HTTP/S (Hypertext Transfer Protocol)
* Rlogin (Rlogin)
* Telnet (Teletype Network)
* HTTP/S (Hypertext Transfer Protocol Secure)
* Rlogin (Remote Login)
* RAW
mRemoteNG can be installed on Windows 7 or later.

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

198
Tools/publish_to_github.ps1 Normal file
View File

@@ -0,0 +1,198 @@
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 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
Write-Output (Get-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $release.id -AuthToken $AuthToken)

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

@@ -0,0 +1,55 @@
using System.Data;
using System.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Connection;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNGTests.TestHelpers;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers
{
public class DataTableDeserializerTests
{
private DataTableDeserializer _deserializer;
[SetUp]
public void Setup()
{
}
[Test]
public void WeCanDeserializeATree()
{
var model = CreateConnectionTreeModel();
var dataTable = CreateDataTable(model.RootNodes[0]);
_deserializer = new DataTableDeserializer(dataTable);
var output = _deserializer.Deserialize();
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(model.GetRecursiveChildList().Count()));
}
[Test]
public void WeCanDeserializeASingleEntry()
{
var dataTable = CreateDataTable(new ConnectionInfo());
_deserializer = new DataTableDeserializer(dataTable);
var output = _deserializer.Deserialize();
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(1));
}
private DataTable CreateDataTable(ConnectionInfo tableContent)
{
var serializer = new DataTableSerializer(new SaveFilter());
return serializer.Serialize(tableContent);
}
private ConnectionTreeModel CreateConnectionTreeModel()
{
var builder = new ConnectionTreeModelBuilder();
return builder.Build();
}
}
}

View File

@@ -4,6 +4,7 @@ using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNGTests.TestHelpers;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers
@@ -20,13 +21,6 @@ namespace mRemoteNGTests.Config.Serializers
_dataTableSerializer = new DataTableSerializer(_saveFilter);
}
[TearDown]
public void Teardown()
{
_saveFilter = null;
_dataTableSerializer = null;
}
[Test]
public void AllItemsSerialized()
{
@@ -35,6 +29,14 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(dataTable.Rows.Count, Is.EqualTo(3));
}
[Test]
public void ReturnsEmptyDataTableWhenGivenEmptyConnectionTreeModel()
{
var model = new ConnectionTreeModel();
var dataTable = _dataTableSerializer.Serialize(model);
Assert.That(dataTable.Rows.Count, Is.EqualTo(0));
}
[Test]
public void UsernameSerializedWhenSaveSecurityAllowsIt()
{
@@ -109,20 +111,18 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(dataTable.Rows[0]["InheritUsername"], Is.False);
}
[Test]
public void CanSerializeEmptyConnectionInfo()
{
var dataTable = _dataTableSerializer.Serialize(new ConnectionInfo());
Assert.That(dataTable.Rows.Count, Is.EqualTo(1));
}
private ConnectionTreeModel CreateConnectionTreeModel()
{
var model = new ConnectionTreeModel();
var root = new RootNodeInfo(RootNodeType.Connection);
var folder1 = new ContainerInfo {Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1"};
var con1 = new ConnectionInfo {Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
var con2 = new ConnectionInfo {Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
root.AddChild(folder1);
root.AddChild(con2);
folder1.AddChild(con1);
model.AddRootNode(root);
return model;
var builder = new ConnectionTreeModelBuilder();
return builder.Build();
}
}
}

View File

@@ -48,6 +48,14 @@ namespace mRemoteNGTests.Connection
Assert.That(secondConnection.Domain, Is.EqualTo(_connectionInfo.Domain));
}
[Test]
public void CloneDoesNotSetParentOfNewConnectionInfo()
{
_connectionInfo.SetParent(new ContainerInfo());
var clonedConnection = _connectionInfo.Clone();
Assert.That(clonedConnection.Parent, Is.Null);
}
[Test]
public void CopyFromCopiesProperties()
{

View File

@@ -263,6 +263,14 @@ namespace mRemoteNGTests.Container
Assert.That(clone.ConstantID, Is.Not.EqualTo(_containerInfo.ConstantID));
}
[Test]
public void ClonedContainerDoesNotHaveParentSet()
{
_containerInfo.SetParent(new ContainerInfo());
var clone = _containerInfo.Clone();
Assert.That(clone.Parent, Is.Null);
}
[Test]
public void ClonedContainerContainsClonedChildren()
{

View File

@@ -0,0 +1,25 @@
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
namespace mRemoteNGTests.TestHelpers
{
public class ConnectionTreeModelBuilder
{
public ConnectionTreeModel Build()
{
var model = new ConnectionTreeModel();
var root = new RootNodeInfo(RootNodeType.Connection);
var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1" };
var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
root.AddChild(folder1);
root.AddChild(con2);
folder1.AddChild(con1);
model.AddRootNode(root);
return model;
}
}
}

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>
@@ -111,6 +111,7 @@
<Compile Include="App\LoggerTests.cs" />
<Compile Include="App\UpdaterTests.cs" />
<Compile Include="BinaryFileTests.cs" />
<Compile Include="Config\Serializers\DataTableDeserializerTests.cs" />
<Compile Include="Config\Serializers\DataTableSerializerTests.cs" />
<Compile Include="Config\Serializers\PortScanDeserializerTests.cs" />
<Compile Include="Config\Serializers\PuttyConnectionManagerDeserializerTests.cs" />
@@ -129,6 +130,7 @@
<Compile Include="Security\Authentication\PasswordAuthenticatorTests.cs" />
<Compile Include="Security\KeyDerivation\Pkcs5S2KeyGeneratorTests.cs" />
<Compile Include="Security\SecureStringExtensionsTests.cs" />
<Compile Include="TestHelpers\ConnectionTreeModelBuilder.cs" />
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />

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

@@ -1,6 +1,9 @@
using System;
using System.Drawing;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Text;
#pragma warning disable 169
namespace mRemoteNG.App
@@ -42,11 +45,17 @@ namespace mRemoteNG.App
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, System.Text.StringBuilder lParam);
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, string lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessage([In] IntPtr hWnd, [In] uint msg, [Out] StringBuilder wParam, [In] IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
@@ -76,6 +85,10 @@ namespace mRemoteNG.App
[DllImport("user32", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport("kernel32", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static extern bool CloseHandle(IntPtr handle);
#endregion
#region Structures
@@ -286,7 +299,10 @@ namespace mRemoteNG.App
public const int WA_ACTIVE = 0x1;
/// <summary>
///
/// Sent to both the window being activated and the window being deactivated.
/// If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the
/// top-level window being deactivated, then to the window procedure of the top-level window being activated. If the
/// windows use different input queues, the message is sent asynchronously, so the window is activated immediately.
/// </summary>
public const int WA_CLICKACTIVE = 0x2;
#endregion
@@ -455,6 +471,12 @@ namespace mRemoteNG.App
public const int VK_C = 0x67;
#endregion
#region EM
public const uint ECM_FIRST = 0x1500;
public const uint EM_SETCUEBANNER = ECM_FIRST + 1;
public const uint EM_GETCUEBANNER = ECM_FIRST + 2;
#endregion
#region LB
public const int LB_ERR = -1;
public const int LB_SELECTSTRING = 0x18C;

View File

@@ -27,6 +27,9 @@ namespace mRemoteNG.App.Update
char[] keyValueSeparators = { ':', '=' };
char[] commentCharacters = { '#', ';', '\'' };
// no separators means no valid update data...
if (content.Trim().IndexOfAny(keyValueSeparators) == -1) return;
using (var sr = new StringReader(content))
{
string line;
@@ -43,6 +46,10 @@ namespace mRemoteNG.App.Update
if (parts.Length != 2)
continue;
// make sure we have valid data in both parts before adding to the collection. If either part is empty, then it's not valid data.
if(string.IsNullOrEmpty(parts[0].Trim()) || string.IsNullOrEmpty(parts[1].Trim()))
continue;
Items.Add(parts[0].Trim(), parts[1].Trim());
}
}

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

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
using mRemoteNG.Connection;
using mRemoteNG.Tree.Root;
@@ -42,7 +43,8 @@ namespace mRemoteNG.Config.Putty
private IEnumerable<PuttySessionInfo> GetSessionToRemove(IEnumerable<string> sessionNamesFromProvider)
{
var currentlyKnownSessionNames = Sessions.Select(session => session.Name);
var sessionNamesToRemove = currentlyKnownSessionNames.Except(sessionNamesFromProvider);
var normalizedSessionNames = sessionNamesFromProvider.Select(HttpUtility.UrlDecode);
var sessionNamesToRemove = currentlyKnownSessionNames.Except(normalizedSessionNames);
return Sessions.Where(session => sessionNamesToRemove.Contains(session.Name));
}

View File

@@ -31,7 +31,7 @@ namespace mRemoteNG.Config.Putty
if (raw && !sessionNames.Contains("Default%20Settings"))
sessionNames.Insert(0, "Default%20Settings");
else if (!sessionNames.Contains("Default Settings"))
else if (!raw && !sessionNames.Contains("Default Settings"))
sessionNames.Insert(0, "Default Settings");
return sessionNames.ToArray();

View File

@@ -43,10 +43,16 @@ namespace mRemoteNG.Config.Serializers
var nodeList = new List<ConnectionInfo>();
foreach (DataRow row in _dataTable.Rows)
{
if ((string)row["Type"] == "Connection")
// ReSharper disable once SwitchStatementMissingSomeCases
switch ((string)row["Type"])
{
case "Connection":
nodeList.Add(DeserializeConnectionInfo(row));
else if ((string)row["Type"] == "Container")
break;
case "Container":
nodeList.Add(DeserializeContainerInfo(row));
break;
}
}
return nodeList;
}
@@ -69,8 +75,15 @@ namespace mRemoteNG.Config.Serializers
{
connectionInfo.Name = (string)dataRow["Name"];
connectionInfo.ConstantID = (string)dataRow["ConstantID"];
// This throws a NPE - Parent is a connectionInfo object which will be null at this point.
// The Parent object is linked properly later in CreateNodeHierarchy()
//connectionInfo.Parent.ConstantID = (string)dataRow["ParentID"];
//connectionInfo is ContainerInfo ? ((ContainerInfo)connectionInfo).IsExpanded.ToString() : "" = dataRow["Expanded"];
var info = connectionInfo as ContainerInfo;
if(info != null)
info.IsExpanded = (bool)dataRow["Expanded"];
connectionInfo.Description = (string)dataRow["Description"];
connectionInfo.Icon = (string)dataRow["Icon"];
connectionInfo.Panel = (string)dataRow["Panel"];
@@ -195,7 +208,7 @@ namespace mRemoteNG.Config.Serializers
var id = (string) row["ConstantID"];
var connectionInfo = connectionList.First(node => node.ConstantID == id);
var parentId = (string) row["ParentID"];
if (parentId == "0")
if (parentId == "0" || connectionList.All(node => node.ConstantID != parentId))
rootNode.AddChild(connectionInfo);
else
(connectionList.First(node => node.ConstantID == parentId) as ContainerInfo)?.AddChild(connectionInfo);

View File

@@ -25,147 +25,162 @@ namespace mRemoteNG.Config.Serializers
public DataTable Serialize(ConnectionTreeModel connectionTreeModel)
{
var rootNode = (RootNodeInfo)connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);
return Serialize(rootNode);
try
{
_dataTable = BuildTable();
_currentNodeIndex = 0;
var rootNode = connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);
return Serialize(rootNode);
}
catch
{
return _dataTable;
}
}
public DataTable Serialize(ConnectionInfo serializationTarget)
{
_dataTable = new DataTable(TableName);
CreateSchema();
SetPrimaryKey();
_dataTable = BuildTable();
_currentNodeIndex = 0;
SerializeNodesRecursive(serializationTarget);
return _dataTable;
}
private void CreateSchema()
private DataTable BuildTable()
{
// 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));
_dataTable.Columns.Add("PositionID", typeof(int));
_dataTable.Columns.Add("ParentID", typeof(string));
_dataTable.Columns.Add("LastChange", typeof(SqlDateTime));
_dataTable.Columns.Add("Name", typeof(string));
_dataTable.Columns.Add("Type", typeof(string));
_dataTable.Columns.Add("Expanded", typeof(bool));
_dataTable.Columns.Add("Description", typeof(string));
_dataTable.Columns.Add("Icon", typeof(string));
_dataTable.Columns.Add("Panel", typeof(string));
_dataTable.Columns.Add("Username", typeof(string));
_dataTable.Columns.Add("DomainName", typeof(string));
_dataTable.Columns.Add("Password", typeof(string));
_dataTable.Columns.Add("Hostname", typeof(string));
_dataTable.Columns.Add("Protocol", typeof(string));
_dataTable.Columns.Add("PuttySession", typeof(string));
_dataTable.Columns.Add("Port", typeof(int));
_dataTable.Columns.Add("ConnectToConsole", typeof(bool));
_dataTable.Columns.Add("UseCredSsp", typeof(bool));
_dataTable.Columns.Add("RenderingEngine", typeof(string));
_dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
_dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
_dataTable.Columns.Add("Colors", typeof(string));
_dataTable.Columns.Add("Resolution", typeof(string));
_dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
_dataTable.Columns.Add("DisplayThemes", typeof(bool));
_dataTable.Columns.Add("EnableFontSmoothing", typeof(bool));
_dataTable.Columns.Add("EnableDesktopComposition", typeof(bool));
_dataTable.Columns.Add("CacheBitmaps", typeof(bool));
_dataTable.Columns.Add("RedirectDiskDrives", typeof(bool));
_dataTable.Columns.Add("RedirectPorts", typeof(bool));
_dataTable.Columns.Add("RedirectPrinters", typeof(bool));
_dataTable.Columns.Add("RedirectSmartCards", typeof(bool));
_dataTable.Columns.Add("RedirectSound", typeof(string));
_dataTable.Columns.Add("RedirectKeys", typeof(bool));
_dataTable.Columns.Add("Connected", typeof(bool));
_dataTable.Columns.Add("PreExtApp", typeof(string));
_dataTable.Columns.Add("PostExtApp", typeof(string));
_dataTable.Columns.Add("MacAddress", typeof(string));
_dataTable.Columns.Add("UserField", typeof(string));
_dataTable.Columns.Add("ExtApp", typeof(string));
_dataTable.Columns.Add("VNCCompression", typeof(string));
_dataTable.Columns.Add("VNCEncoding", typeof(string));
_dataTable.Columns.Add("VNCAuthMode", typeof(string));
_dataTable.Columns.Add("VNCProxyType", typeof(string));
_dataTable.Columns.Add("VNCProxyIP", typeof(string));
_dataTable.Columns.Add("VNCProxyPort", typeof(int));
_dataTable.Columns.Add("VNCProxyUsername", typeof(string));
_dataTable.Columns.Add("VNCProxyPassword", typeof(string));
_dataTable.Columns.Add("VNCColors", typeof(string));
_dataTable.Columns.Add("VNCSmartSizeMode", typeof(string));
_dataTable.Columns.Add("VNCViewOnly", typeof(bool));
_dataTable.Columns.Add("RDGatewayUsageMethod", typeof(string));
_dataTable.Columns.Add("RDGatewayHostname", typeof(string));
_dataTable.Columns.Add("RDGatewayUseConnectionCredentials", typeof(string));
_dataTable.Columns.Add("RDGatewayUsername", typeof(string));
_dataTable.Columns.Add("RDGatewayPassword", typeof(string));
_dataTable.Columns.Add("RDGatewayDomain", typeof(string));
_dataTable.Columns.Add("InheritCacheBitmaps", typeof(bool));
_dataTable.Columns.Add("InheritColors", typeof(bool));
_dataTable.Columns.Add("InheritDescription", typeof(bool));
_dataTable.Columns.Add("InheritDisplayThemes", typeof(bool));
_dataTable.Columns.Add("InheritDisplayWallpaper", typeof(bool));
_dataTable.Columns.Add("InheritEnableFontSmoothing", typeof(bool));
_dataTable.Columns.Add("InheritEnableDesktopComposition", typeof(bool));
_dataTable.Columns.Add("InheritDomain", typeof(bool));
_dataTable.Columns.Add("InheritIcon", typeof(bool));
_dataTable.Columns.Add("InheritPanel", typeof(bool));
_dataTable.Columns.Add("InheritPassword", typeof(bool));
_dataTable.Columns.Add("InheritPort", typeof(bool));
_dataTable.Columns.Add("InheritProtocol", typeof(bool));
_dataTable.Columns.Add("InheritPuttySession", typeof(bool));
_dataTable.Columns.Add("InheritRedirectDiskDrives", typeof(bool));
_dataTable.Columns.Add("InheritRedirectKeys", typeof(bool));
_dataTable.Columns.Add("InheritRedirectPorts", typeof(bool));
_dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
_dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
_dataTable.Columns.Add("InheritRedirectSound", 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("InheritUsername", typeof(bool));
_dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
_dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
_dataTable.Columns.Add("InheritMacAddress", typeof(bool));
_dataTable.Columns.Add("InheritUserField", typeof(bool));
_dataTable.Columns.Add("InheritExtApp", typeof(bool));
_dataTable.Columns.Add("InheritVNCCompression", typeof(bool));
_dataTable.Columns.Add("InheritVNCEncoding", typeof(bool));
_dataTable.Columns.Add("InheritVNCAuthMode", typeof(bool));
_dataTable.Columns.Add("InheritVNCProxyType", typeof(bool));
_dataTable.Columns.Add("InheritVNCProxyIP", typeof(bool));
_dataTable.Columns.Add("InheritVNCProxyPort", typeof(bool));
_dataTable.Columns.Add("InheritVNCProxyUsername", typeof(bool));
_dataTable.Columns.Add("InheritVNCProxyPassword", typeof(bool));
_dataTable.Columns.Add("InheritVNCColors", typeof(bool));
_dataTable.Columns.Add("InheritVNCSmartSizeMode", typeof(bool));
_dataTable.Columns.Add("InheritVNCViewOnly", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayUsageMethod", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayHostname", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayUseConnectionCredentials", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayUsername", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayPassword", typeof(bool));
_dataTable.Columns.Add("InheritRDGatewayDomain", typeof(bool));
_dataTable.Columns.Add("LoadBalanceInfo", typeof(string));
_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));
var dataTable = new DataTable(TableName);
CreateSchema(dataTable);
SetPrimaryKey(dataTable);
return dataTable;
}
private void SetPrimaryKey()
private void CreateSchema(DataTable dataTable)
{
_dataTable.PrimaryKey = new[] { _dataTable.Columns["ConstantID"] };
// 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));
dataTable.Columns.Add("PositionID", typeof(int));
dataTable.Columns.Add("ParentID", typeof(string));
dataTable.Columns.Add("LastChange", typeof(SqlDateTime));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Type", typeof(string));
dataTable.Columns.Add("Expanded", typeof(bool));
dataTable.Columns.Add("Description", typeof(string));
dataTable.Columns.Add("Icon", typeof(string));
dataTable.Columns.Add("Panel", typeof(string));
dataTable.Columns.Add("Username", typeof(string));
dataTable.Columns.Add("DomainName", typeof(string));
dataTable.Columns.Add("Password", typeof(string));
dataTable.Columns.Add("Hostname", typeof(string));
dataTable.Columns.Add("Protocol", typeof(string));
dataTable.Columns.Add("PuttySession", typeof(string));
dataTable.Columns.Add("Port", typeof(int));
dataTable.Columns.Add("ConnectToConsole", typeof(bool));
dataTable.Columns.Add("UseCredSsp", typeof(bool));
dataTable.Columns.Add("RenderingEngine", typeof(string));
dataTable.Columns.Add("ICAEncryptionStrength", typeof(string));
dataTable.Columns.Add("RDPAuthenticationLevel", typeof(string));
dataTable.Columns.Add("Colors", typeof(string));
dataTable.Columns.Add("Resolution", typeof(string));
dataTable.Columns.Add("DisplayWallpaper", typeof(bool));
dataTable.Columns.Add("DisplayThemes", typeof(bool));
dataTable.Columns.Add("EnableFontSmoothing", typeof(bool));
dataTable.Columns.Add("EnableDesktopComposition", typeof(bool));
dataTable.Columns.Add("CacheBitmaps", typeof(bool));
dataTable.Columns.Add("RedirectDiskDrives", typeof(bool));
dataTable.Columns.Add("RedirectPorts", typeof(bool));
dataTable.Columns.Add("RedirectPrinters", typeof(bool));
dataTable.Columns.Add("RedirectSmartCards", typeof(bool));
dataTable.Columns.Add("RedirectSound", typeof(string));
dataTable.Columns.Add("RedirectKeys", typeof(bool));
dataTable.Columns.Add("Connected", typeof(bool));
dataTable.Columns.Add("PreExtApp", typeof(string));
dataTable.Columns.Add("PostExtApp", typeof(string));
dataTable.Columns.Add("MacAddress", typeof(string));
dataTable.Columns.Add("UserField", typeof(string));
dataTable.Columns.Add("ExtApp", typeof(string));
dataTable.Columns.Add("VNCCompression", typeof(string));
dataTable.Columns.Add("VNCEncoding", typeof(string));
dataTable.Columns.Add("VNCAuthMode", typeof(string));
dataTable.Columns.Add("VNCProxyType", typeof(string));
dataTable.Columns.Add("VNCProxyIP", typeof(string));
dataTable.Columns.Add("VNCProxyPort", typeof(int));
dataTable.Columns.Add("VNCProxyUsername", typeof(string));
dataTable.Columns.Add("VNCProxyPassword", typeof(string));
dataTable.Columns.Add("VNCColors", typeof(string));
dataTable.Columns.Add("VNCSmartSizeMode", typeof(string));
dataTable.Columns.Add("VNCViewOnly", typeof(bool));
dataTable.Columns.Add("RDGatewayUsageMethod", typeof(string));
dataTable.Columns.Add("RDGatewayHostname", typeof(string));
dataTable.Columns.Add("RDGatewayUseConnectionCredentials", typeof(string));
dataTable.Columns.Add("RDGatewayUsername", typeof(string));
dataTable.Columns.Add("RDGatewayPassword", typeof(string));
dataTable.Columns.Add("RDGatewayDomain", typeof(string));
dataTable.Columns.Add("InheritCacheBitmaps", typeof(bool));
dataTable.Columns.Add("InheritColors", typeof(bool));
dataTable.Columns.Add("InheritDescription", typeof(bool));
dataTable.Columns.Add("InheritDisplayThemes", typeof(bool));
dataTable.Columns.Add("InheritDisplayWallpaper", typeof(bool));
dataTable.Columns.Add("InheritEnableFontSmoothing", typeof(bool));
dataTable.Columns.Add("InheritEnableDesktopComposition", typeof(bool));
dataTable.Columns.Add("InheritDomain", typeof(bool));
dataTable.Columns.Add("InheritIcon", typeof(bool));
dataTable.Columns.Add("InheritPanel", typeof(bool));
dataTable.Columns.Add("InheritPassword", typeof(bool));
dataTable.Columns.Add("InheritPort", typeof(bool));
dataTable.Columns.Add("InheritProtocol", typeof(bool));
dataTable.Columns.Add("InheritPuttySession", typeof(bool));
dataTable.Columns.Add("InheritRedirectDiskDrives", typeof(bool));
dataTable.Columns.Add("InheritRedirectKeys", typeof(bool));
dataTable.Columns.Add("InheritRedirectPorts", typeof(bool));
dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
dataTable.Columns.Add("InheritRedirectSound", 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("InheritUsername", typeof(bool));
dataTable.Columns.Add("InheritPreExtApp", typeof(bool));
dataTable.Columns.Add("InheritPostExtApp", typeof(bool));
dataTable.Columns.Add("InheritMacAddress", typeof(bool));
dataTable.Columns.Add("InheritUserField", typeof(bool));
dataTable.Columns.Add("InheritExtApp", typeof(bool));
dataTable.Columns.Add("InheritVNCCompression", typeof(bool));
dataTable.Columns.Add("InheritVNCEncoding", typeof(bool));
dataTable.Columns.Add("InheritVNCAuthMode", typeof(bool));
dataTable.Columns.Add("InheritVNCProxyType", typeof(bool));
dataTable.Columns.Add("InheritVNCProxyIP", typeof(bool));
dataTable.Columns.Add("InheritVNCProxyPort", typeof(bool));
dataTable.Columns.Add("InheritVNCProxyUsername", typeof(bool));
dataTable.Columns.Add("InheritVNCProxyPassword", typeof(bool));
dataTable.Columns.Add("InheritVNCColors", typeof(bool));
dataTable.Columns.Add("InheritVNCSmartSizeMode", typeof(bool));
dataTable.Columns.Add("InheritVNCViewOnly", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayUsageMethod", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayHostname", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayUseConnectionCredentials", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayUsername", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayPassword", typeof(bool));
dataTable.Columns.Add("InheritRDGatewayDomain", typeof(bool));
dataTable.Columns.Add("LoadBalanceInfo", typeof(string));
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(DataTable dataTable)
{
dataTable.PrimaryKey = new[] { dataTable.Columns["ConstantID"] };
}
private void SerializeNodesRecursive(ConnectionInfo connectionInfo)
@@ -186,7 +201,7 @@ namespace mRemoteNG.Config.Serializers
dataRow["Name"] = connectionInfo.Name;
dataRow["Type"] = connectionInfo.GetTreeNodeType().ToString();
dataRow["ConstantID"] = connectionInfo.ConstantID;
dataRow["ParentID"] = connectionInfo.Parent.ConstantID;
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
dataRow["PositionID"] = _currentNodeIndex;
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
var info = connectionInfo as ContainerInfo;

View File

@@ -78,7 +78,6 @@ namespace mRemoteNG.Connection
var newConnectionInfo = new ConnectionInfo();
newConnectionInfo.CopyFrom(this);
newConnectionInfo.ConstantID = MiscTools.CreateConstantID();
newConnectionInfo.SetParent(Parent);
newConnectionInfo.Inheritance = Inheritance.Clone();
return newConnectionInfo;
}
@@ -172,7 +171,7 @@ namespace mRemoteNG.Connection
{
var inheritType = Inheritance.GetType();
var inheritPropertyInfo = inheritType.GetProperty(propertyName);
var inheritPropertyValue = Convert.ToBoolean(inheritPropertyInfo.GetValue(Inheritance, null));
var inheritPropertyValue = inheritPropertyInfo != null && Convert.ToBoolean(inheritPropertyInfo.GetValue(Inheritance, null));
return inheritPropertyValue;
}
@@ -180,15 +179,20 @@ namespace mRemoteNG.Connection
{
var connectionInfoType = Parent.GetType();
var parentPropertyInfo = connectionInfoType.GetProperty(propertyName);
if (parentPropertyInfo == null)
return default(TPropertyType); // shouldn't get here...
var parentPropertyValue = (TPropertyType)parentPropertyInfo.GetValue(Parent, null);
return parentPropertyValue;
}
private static int GetDefaultPort(ProtocolType protocol)
{
try
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch (protocol)
{
case ProtocolType.RDP:

View File

@@ -179,7 +179,6 @@ namespace mRemoteNG.Container
var newContainer = new ContainerInfo();
newContainer.CopyFrom(this);
newContainer.ConstantID = MiscTools.CreateConstantID();
newContainer.SetParent(Parent);
newContainer.OpenConnections = new ProtocolList();
newContainer.Inheritance = Inheritance.Clone();
foreach (var child in Children.ToArray())

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.7001.*")]
[assembly: AssemblyVersion("1.75.7007.*")]
[assembly:NeutralResourcesLanguageAttribute("en")]

Binary file not shown.

View File

@@ -3,6 +3,7 @@ using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.UI.Forms;
@@ -114,7 +115,7 @@ namespace mRemoteNG.Tools
private void ConMenItem_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
if (!(((ToolStripMenuItem) sender).Tag is ConnectionInfo)) return;
if (((ToolStripMenuItem)sender).Tag is ContainerInfo) return;
if (frmMain.Default.Visible == false)
ShowForm();
_connectionInitiator.OpenConnection((ConnectionInfo) ((ToolStripMenuItem) sender).Tag);

View File

@@ -1,54 +1,92 @@
using System;
using System.Drawing;
using mRemoteNG.App;
using Microsoft.Win32.SafeHandles;
// ReSharper disable MemberCanBeMadeStatic.Global
namespace mRemoteNG.Tools
{
public class SystemMenu
{
public sealed class SystemMenu : SafeHandleZeroOrMinusOneIsInvalid, IDisposable
{
[Flags]
public enum Flags
{
MF_STRING = App.NativeMethods.MF_STRING,
MF_SEPARATOR = App.NativeMethods.MF_SEPARATOR,
MF_BYCOMMAND = App.NativeMethods.MF_BYCOMMAND,
MF_BYPOSITION = App.NativeMethods.MF_BYPOSITION,
MF_POPUP = App.NativeMethods.MF_POPUP,
WM_SYSCOMMAND = App.NativeMethods.WM_SYSCOMMAND
MF_STRING = NativeMethods.MF_STRING,
MF_SEPARATOR = NativeMethods.MF_SEPARATOR,
MF_BYCOMMAND = NativeMethods.MF_BYCOMMAND,
MF_BYPOSITION = NativeMethods.MF_BYPOSITION,
MF_POPUP = NativeMethods.MF_POPUP,
WM_SYSCOMMAND = NativeMethods.WM_SYSCOMMAND
}
public IntPtr SystemMenuHandle;
public IntPtr FormHandle;
public SystemMenu(IntPtr Handle)
private bool disposed;
internal IntPtr SystemMenuHandle;
private readonly IntPtr FormHandle;
public SystemMenu(IntPtr Handle) :base(true)
{
FormHandle = Handle;
SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, false);
}
SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, false);
SetHandle(SystemMenuHandle);
}
public void Reset()
{
SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, true);
SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, true);
}
public void AppendMenuItem(IntPtr ParentMenu, Flags Flags, IntPtr ID, string Text)
{
App.NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
}
public IntPtr CreatePopupMenuItem()
{
return App.NativeMethods.CreatePopupMenu();
return NativeMethods.CreatePopupMenu();
}
public bool InsertMenuItem(IntPtr SysMenu, int Position, Flags Flags, IntPtr SubMenu, string Text)
{
return App.NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
return NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
}
public IntPtr SetBitmap(IntPtr Menu, int Position, Flags Flags, Bitmap Bitmap)
{
return new IntPtr(Convert.ToInt32(App.NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
return new IntPtr(Convert.ToInt32(NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
}
}
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(SystemMenuHandle);
}
/* If we don't have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms182329.aspx (CA2216: Disposable types should declare finalizer)
* If we DO have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms244737.aspx (CA1063: Implement IDisposable correctly)
*
* Since the handle is likely going to be in use for the entierty of the process, the finalizer isn't very important since when we're calling it
* the process is likely exiting. Leaks would be moot once it exits. CA2216 is the lesser of 2 evils as far as I can tell. Suppress.
~SystemMenu()
{
Dispose(false);
}
*/
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2216:DisposableTypesShouldDeclareFinalizer")]
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if (disposed) return;
if (!disposing) return;
ReleaseHandle();
disposed = true;
}
}
}

View File

@@ -63,11 +63,6 @@ namespace mRemoteNG.Tree
connectionInfo?.RemoveParent();
}
public void CloneNode(ConnectionInfo connectionInfo)
{
connectionInfo.Clone();
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void RaiseCollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs args)
{

View File

@@ -717,7 +717,11 @@ namespace mRemoteNG.UI.Controls
private void OnImportFileClicked(object sender, EventArgs e)
{
var selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo ?? _connectionTree.SelectedNode.Parent;
ContainerInfo selectedNodeAsContainer;
if (_connectionTree.SelectedNode == null)
selectedNodeAsContainer = Runtime.ConnectionTreeModel.RootNodes.First();
else
selectedNodeAsContainer = _connectionTree.SelectedNode as ContainerInfo ?? _connectionTree.SelectedNode.Parent;
Import.ImportFromFile(selectedNodeAsContainer);
}

View File

@@ -215,6 +215,7 @@ namespace mRemoteNG.UI.Controls
public void DuplicateSelectedNode()
{
var newNode = SelectedNode.Clone();
SelectedNode.Parent.AddChildBelow(newNode, SelectedNode);
newNode.Parent.SetChildBelow(newNode, SelectedNode);
Runtime.SaveConnectionsAsync();
}

View File

@@ -33,6 +33,7 @@ namespace mRemoteNG.UI.Window
this.lblEdition = new System.Windows.Forms.Label();
this.pbLogo = new System.Windows.Forms.PictureBox();
this.pnlBottom = new System.Windows.Forms.Panel();
this.verText = new System.Windows.Forms.TextBox();
this.lblCredits = new System.Windows.Forms.Label();
this.txtCredits = new System.Windows.Forms.TextBox();
this.txtChangeLog = new System.Windows.Forms.TextBox();
@@ -41,7 +42,6 @@ namespace mRemoteNG.UI.Window
this.lblChangeLog = new System.Windows.Forms.Label();
this.lblLicense = new System.Windows.Forms.Label();
this.lblCopyright = new System.Windows.Forms.Label();
this.verText = new System.Windows.Forms.TextBox();
this.pnlTop.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbLogo)).BeginInit();
this.pnlBottom.SuspendLayout();
@@ -105,6 +105,18 @@ namespace mRemoteNG.UI.Window
this.pnlBottom.Size = new System.Drawing.Size(1121, 559);
this.pnlBottom.TabIndex = 1;
//
// verText
//
this.verText.BackColor = System.Drawing.SystemColors.Control;
this.verText.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.verText.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.verText.Location = new System.Drawing.Point(69, 51);
this.verText.Name = "verText";
this.verText.Size = new System.Drawing.Size(147, 20);
this.verText.TabIndex = 12;
this.verText.TabStop = false;
this.verText.Text = "w.x.y.z";
//
// lblCredits
//
this.lblCredits.AutoSize = true;
@@ -119,6 +131,8 @@ namespace mRemoteNG.UI.Window
//
// txtCredits
//
this.txtCredits.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.txtCredits.BackColor = System.Drawing.SystemColors.Control;
this.txtCredits.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txtCredits.Cursor = System.Windows.Forms.Cursors.Default;
@@ -136,6 +150,9 @@ namespace mRemoteNG.UI.Window
//
// txtChangeLog
//
this.txtChangeLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtChangeLog.BackColor = System.Drawing.SystemColors.Control;
this.txtChangeLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txtChangeLog.Cursor = System.Windows.Forms.Cursors.Default;
@@ -211,18 +228,6 @@ namespace mRemoteNG.UI.Window
this.lblCopyright.Text = "Copyright";
this.lblCopyright.UseCompatibleTextRendering = true;
//
// verText
//
this.verText.BackColor = System.Drawing.SystemColors.Control;
this.verText.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.verText.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.verText.Location = new System.Drawing.Point(69, 51);
this.verText.Name = "verText";
this.verText.Size = new System.Drawing.Size(147, 20);
this.verText.TabIndex = 12;
this.verText.TabStop = false;
this.verText.Text = "w.x.y.z";
//
// AboutWindow
//
this.BackColor = System.Drawing.SystemColors.Control;
@@ -251,7 +256,8 @@ namespace mRemoteNG.UI.Window
public AboutWindow(DockContent Panel)
{
WindowType = WindowType.About;
DockPnl = Panel;
DockPnl = Panel;
DockPnl = new DockContent();
InitializeComponent();
Runtime.FontOverride(this);
}

View File

@@ -1248,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>