mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Compare commits
182 Commits
v1.75Hotfi
...
v1.75.7011
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce8171f12 | ||
|
|
e3121cb043 | ||
|
|
99e52ab0b5 | ||
|
|
2b672dc4fc | ||
|
|
6db7adf900 | ||
|
|
65782285a3 | ||
|
|
64bd5a93ad | ||
|
|
68f052efcb | ||
|
|
4a8baf79fb | ||
|
|
499ac0295e | ||
|
|
29c422501a | ||
|
|
8efe74f614 | ||
|
|
4e0f12f4b9 | ||
|
|
cbd3a61259 | ||
|
|
2406a7be49 | ||
|
|
dd40b56047 | ||
|
|
f14a0d5ee3 | ||
|
|
e0383d6c59 | ||
|
|
eeabcd94ed | ||
|
|
8a3e37041a | ||
|
|
a1e9aefeb2 | ||
|
|
670cb51352 | ||
|
|
a43dff88c5 | ||
|
|
fb3c87359f | ||
|
|
a49dec7e6d | ||
|
|
a7156235c3 | ||
|
|
3cb52ba3f1 | ||
|
|
024f1a7047 | ||
|
|
b77c7e922f | ||
|
|
9335c4706b | ||
|
|
e09a9dabd6 | ||
|
|
e4e2f50015 | ||
|
|
61865050c7 | ||
|
|
05d90c26ff | ||
|
|
43cdb29eb6 | ||
|
|
87ff1cb2b2 | ||
|
|
f73c9c9d02 | ||
|
|
d15e444cb7 | ||
|
|
2eff6c3dc4 | ||
|
|
41fe211aec | ||
|
|
2acfa6d88d | ||
|
|
348b0c728c | ||
|
|
875e1573a4 | ||
|
|
926dc868ef | ||
|
|
86ecb38ae2 | ||
|
|
f3ca58111c | ||
|
|
3124d3ca1c | ||
|
|
9012506209 | ||
|
|
adb874ca74 | ||
|
|
6aaf2f031b | ||
|
|
1669377938 | ||
|
|
198c235765 | ||
|
|
66f2c55343 | ||
|
|
0f3fa86bed | ||
|
|
e5c2cfd243 | ||
|
|
ef1c397f11 | ||
|
|
12e0cc3d7b | ||
|
|
ff6bb6ebb0 | ||
|
|
6b78215b2e | ||
|
|
5d9a02657f | ||
|
|
14d670a9a2 | ||
|
|
67801506e0 | ||
|
|
48eb6dbbe0 | ||
|
|
d520c6a816 | ||
|
|
664799c01b | ||
|
|
d88c5b9db2 | ||
|
|
0fe7a693f8 | ||
|
|
9a2efd9686 | ||
|
|
88961fbdb5 | ||
|
|
a11ceced09 | ||
|
|
ca35662ca2 | ||
|
|
e7c4bbe1e8 | ||
|
|
1bc56b5c9e | ||
|
|
25a0630bcb | ||
|
|
1f7d122bee | ||
|
|
d9cb32ca53 | ||
|
|
760587ee2e | ||
|
|
d2fe8a2ddb | ||
|
|
81b0be0489 | ||
|
|
3074a211f8 | ||
|
|
0659b140f5 | ||
|
|
0b8160ae34 | ||
|
|
dbf2b7b4b6 | ||
|
|
1e8afc8ea4 | ||
|
|
70bd2e8a78 | ||
|
|
8045544051 | ||
|
|
0cef4dc9b3 | ||
|
|
f1cfa4330a | ||
|
|
a50b370262 | ||
|
|
064fd217ba | ||
|
|
692b26622c | ||
|
|
72a56d33d0 | ||
|
|
ce4bfc55c1 | ||
|
|
f0faec9def | ||
|
|
e6ef28050c | ||
|
|
547ec3cb3a | ||
|
|
fc0f278962 | ||
|
|
1f3db15892 | ||
|
|
e3e4c49427 | ||
|
|
1520b8bf73 | ||
|
|
c9e7f82905 | ||
|
|
d2357fa779 | ||
|
|
703178ddf1 | ||
|
|
4e9c5de16c | ||
|
|
3d1fcc35df | ||
|
|
e20d7afb72 | ||
|
|
07e2bc3858 | ||
|
|
f3b11d6f72 | ||
|
|
69f310c02c | ||
|
|
3308f1146c | ||
|
|
8e8cf3df8d | ||
|
|
26fdd924ef | ||
|
|
ea3494f6e7 | ||
|
|
9f028d9104 | ||
|
|
f40be696c7 | ||
|
|
95a503a390 | ||
|
|
88c51f4933 | ||
|
|
9e20f1dd33 | ||
|
|
16be19b5d3 | ||
|
|
80ac0259b8 | ||
|
|
9f7911923c | ||
|
|
686005071e | ||
|
|
e16d31d605 | ||
|
|
8b201d22cb | ||
|
|
0f6f8d43bd | ||
|
|
8f171cddd9 | ||
|
|
c77c323f73 | ||
|
|
9e358309e4 | ||
|
|
485438f38d | ||
|
|
fe26a60337 | ||
|
|
d2c2de4dd7 | ||
|
|
d49d58f7f8 | ||
|
|
164d4fff8b | ||
|
|
7726406674 | ||
|
|
ed38b39fec | ||
|
|
9188d4316e | ||
|
|
cf374c6b8b | ||
|
|
82388dcbc3 | ||
|
|
7a6a99e2b6 | ||
|
|
c383736834 | ||
|
|
6e5e78df3b | ||
|
|
311bf1b641 | ||
|
|
5c9933791c | ||
|
|
039d4d11aa | ||
|
|
c0f2d2aa84 | ||
|
|
45099bfa07 | ||
|
|
695ae9d970 | ||
|
|
21eb0064b1 | ||
|
|
513fe402af | ||
|
|
b27e5754e8 | ||
|
|
fa7231d77b | ||
|
|
f5a30ecb33 | ||
|
|
7f22289889 | ||
|
|
f80c39077a | ||
|
|
75c60a1cc4 | ||
|
|
2cf38d6b7c | ||
|
|
482c9c1574 | ||
|
|
882e59a260 | ||
|
|
7a036956b7 | ||
|
|
7520b20cf9 | ||
|
|
d47ccd75d5 | ||
|
|
56ff81a0ed | ||
|
|
8db76f5324 | ||
|
|
a9442ea06e | ||
|
|
92bd0d3ea0 | ||
|
|
512d7322b2 | ||
|
|
45645c439f | ||
|
|
84ebb82cae | ||
|
|
576f6a3bd6 | ||
|
|
96df821eca | ||
|
|
8589778e92 | ||
|
|
a8a7de9ee6 | ||
|
|
1d99340425 | ||
|
|
a8cdfb56f3 | ||
|
|
0958cdaa2d | ||
|
|
ebfb3dd31e | ||
|
|
3943b8753f | ||
|
|
9e26ea1866 | ||
|
|
8152a87514 | ||
|
|
b28775c2c6 | ||
|
|
3eb96ef765 | ||
|
|
8805584cbe |
110
CHANGELOG.TXT
110
CHANGELOG.TXT
@@ -1,3 +1,113 @@
|
||||
1.75.7011 (2017-xx-xx):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#761: Connections using external tools do not start (introduced in v1.75.7009)
|
||||
Minor changes to how the connection tree column widths are calculated
|
||||
|
||||
|
||||
1.75.7010 (2017-10-29):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#756: CustomConsPath always null
|
||||
|
||||
|
||||
1.75.7009 (2017-10-28):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#676: Portable version ignores /cons param on first run
|
||||
#675: Attempting to add new connection/folder does not work in some situations
|
||||
#665: Can not add new connection or new folder in some situations
|
||||
#658: Keep Port Scan tab open after import
|
||||
#646: Exception after click on import port scan
|
||||
#635: Updated PuTTYNG to 0.70
|
||||
#610: mRemoteNG cannot start /crashes for some users on Windows server 2012 R2 server
|
||||
#600: Missing horizontal scrollbar on Connections Panel
|
||||
#596: Exception when launching external tool without a connection selected
|
||||
#550: Sometimes double-clicking connection tree node began rename instead of connecting
|
||||
#536: Prevented log file creation when writeLogFile option is not set
|
||||
#529: Erratic Tree Selection when using SQL Database
|
||||
#482: Default connection password not decrypted when loaded
|
||||
#335: The Quick Connect Toolbar > Connection view does not show open connections with the play icon
|
||||
#176: Unable to enter text in Quick Connect when SSH connection active
|
||||
Minor error message correction
|
||||
Minor code refactoring
|
||||
|
||||
|
||||
NO.RELEASE (2017-06-15):
|
||||
|
||||
Fixed in previous releases:
|
||||
---------------------------
|
||||
#466: Installer still failing on Win7 for updates - v1.75.7005 (Hotifx 5)
|
||||
#462: Remove no longer used files from portable version - v1.75.7003 (Hotfix 4)
|
||||
|
||||
|
||||
1.75.7008 (2017-06-15):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#589: MSI doesn't update with newer PuTTYNG version that fixes #583 (Again, Sorry!)
|
||||
Minor updates to the installer build
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
1.75 hotfix 1 (2017-03-06):
|
||||
|
||||
General Changes:
|
||||
|
||||
@@ -11,7 +11,9 @@ Bennett Blodinger (github.com/benwa)
|
||||
Joe Cefoli (github.com/jcefoli)
|
||||
countchappy (github.com/countchappy)
|
||||
Tony Lambert
|
||||
|
||||
Brandon Wulf (github.com/mrwulf)
|
||||
Pedro Rodrigues (github.com/pedro2555)
|
||||
github.com/dekelMP
|
||||
|
||||
|
||||
Past Contributors
|
||||
@@ -99,8 +101,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/
|
||||
|
||||
|
||||
@@ -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 ?>
|
||||
|
||||
@@ -39,9 +39,6 @@
|
||||
<Compile Include="mRemoteNGV1.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Dependencies\PuTTYNG.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Filters\Harvest_Filter.xslt" />
|
||||
<Content Include="Includes\Config.wxi" />
|
||||
<Content Include="Resources\header.bmp" />
|
||||
@@ -57,7 +54,6 @@
|
||||
<Folder Include="Localizations" />
|
||||
<Folder Include="Filters" />
|
||||
<Folder Include="bin" />
|
||||
<Folder Include="Dependencies" />
|
||||
<Folder Include="Resources" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -115,20 +111,19 @@
|
||||
<DefineConstants>HarvestPath=$(SolutionDir)mRemoteV1\bin\Release Portable;HelpFilesHarvestPath=$(SolutionDir)mRemoteV1\Resources\Help</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>set /p buildenv=<buildenv.tmp
|
||||
<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.
|
||||
|
||||
REM Sign MSI
|
||||
IF EXIST C:\mRemoteNG_code_signing_cert.pfx (
|
||||
IF %25buildenv: Portable=%25==Release (
|
||||
powershell "&""$(SolutionDir)Tools\signfiles.ps1""" %27%25cd%25%27
|
||||
)
|
||||
)
|
||||
powershell -noprofile -command "sleep 2"
|
||||
set /p buildenv=<buildenv.tmp
|
||||
set solutionDir=$(SolutionDir)\
|
||||
set targetDir=%25cd%25
|
||||
set psScriptsDir=$(SolutionDir)Tools
|
||||
set certPath=$(CertPath)
|
||||
set certPassword=$(CertPassword)
|
||||
|
||||
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>
|
||||
:: 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>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>REM Clean the TargetDir
|
||||
@@ -137,9 +132,9 @@ rmdir /S /Q "$(TargetDir)"
|
||||
echo $(ConfigurationName) > buildenv.tmp
|
||||
|
||||
REM Harvest bin directory of the mRemoteV1 project
|
||||
call "$(WIX)bin\heat.exe" dir "$(SolutionDir)mRemoteV1\bin\$(Configuration)" -ag -dr INSTALLDIR -var var.HarvestPath -srd -cg MandatoryComponents -template fragment -out "$(ProjectDir)Fragments\FilesFragment.wxs" -t "$(ProjectDir)Filters\Harvest_Filter.xslt" -v
|
||||
"$(WIX)bin\heat.exe" dir "$(SolutionDir)mRemoteV1\bin\$(Configuration)" -ag -nologo -dr INSTALLDIR -var var.HarvestPath -srd -cg MandatoryComponents -template fragment -out "$(ProjectDir)Fragments\FilesFragment.wxs" -t "$(ProjectDir)Filters\Harvest_Filter.xslt"
|
||||
|
||||
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>
|
||||
"$(ProjectDir)Resources\Pandoc\pandoc.exe" -s -t rtf -o "$(ProjectDir)\Resources\License.rtf" "$(SolutionDir)COPYING.TXT"</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<MajorUpgrade DowngradeErrorMessage="!(loc.Upgrade_NewerVersionInstalled)" Schedule="afterInstallExecute" />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
<Binary Id="CustomActions.CA.dll" SourceFile="$(var.SolutionDir)InstallerProjects\CustomActions\bin\$(var.Configuration)\CustomActions.CA.dll" />
|
||||
<Property Id="MsiLogging" Value="v" />
|
||||
<Property Id="ARPPRODUCTICON" Value="mRemoteNG.ico" />
|
||||
<Property Id="ARPHELPLINK" Value="http://www.mremoteng.org" />
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize" />
|
||||
@@ -67,7 +68,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>
|
||||
|
||||
68
Jenkinsfile_publish.groovy
Normal file
68
Jenkinsfile_publish.groovy
Normal file
@@ -0,0 +1,68 @@
|
||||
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 /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
||||
archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
||||
}
|
||||
|
||||
stage ('Build mRemoteNG (Portable)') {
|
||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
||||
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 ('Generate UpdateCheck Files') {
|
||||
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\create_upg_chk_files.ps1\" -TagName \"${env.TagName}\" -UpdateChannel \"${env.UpdateChannel}\""
|
||||
archiveArtifacts artifacts: "Release\\*.txt", caseSensitive: false, onlyIfSuccessful: true
|
||||
}
|
||||
|
||||
stage ('Publish to GitHub') {
|
||||
withCredentials([string(credentialsId: '5443a369-dbe8-42d3-b4e8-04d0b4e9039a', variable: 'GH_AUTH_TOKEN')]) {
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
README.MD
10
README.MD
@@ -10,8 +10,8 @@
|
||||
|
||||
| Update Channel | Build Status | Downloads |
|
||||
| ---------------|--------------|-----------|
|
||||
| Stable | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74) |
|
||||
| Beta | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/beta_channel/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Beta3) |
|
||||
| Stable | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Hotfix7) |
|
||||
| Beta | | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Hotfix7) |
|
||||
| Development | [](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
15
Tools/copy_puttyng.ps1
Normal 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 ""
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,42 +1,109 @@
|
||||
#Requires -Version 4.0
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TagName,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet("Stable","Beta","Development")]
|
||||
$UpdateChannel
|
||||
)
|
||||
|
||||
|
||||
|
||||
function New-MsiUpdateFileContent {
|
||||
param (
|
||||
[System.IO.FileInfo]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$MsiFile,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TagName
|
||||
)
|
||||
|
||||
$version = $MsiFile.BaseName -replace "[a-zA-Z-]*"
|
||||
$certThumbprint = (Get-AuthenticodeSignature -FilePath $MsiFile).SignerCertificate.Thumbprint
|
||||
$hash = Get-FileHash -Algorithm SHA512 $MsiFile | % { $_.Hash }
|
||||
|
||||
$fileContents = `
|
||||
"Version: $version
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$TagName/$($MsiFile.Name)
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$TagName/CHANGELOG.TXT
|
||||
CertificateThumbprint: $certThumbprint
|
||||
Checksum: $hash"
|
||||
Write-Output $fileContents
|
||||
}
|
||||
|
||||
|
||||
function New-ZipUpdateFileContent {
|
||||
param (
|
||||
[System.IO.FileInfo]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$ZipFile,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TagName
|
||||
)
|
||||
|
||||
$version = $ZipFile.BaseName -replace "[a-zA-Z-]*"
|
||||
$hash = Get-FileHash -Algorithm SHA512 $ZipFile | % { $_.Hash }
|
||||
|
||||
$fileContents = `
|
||||
"Version: $version
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$TagName/$($ZipFile.Name)
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$TagName/CHANGELOG.TXT
|
||||
Checksum: $hash"
|
||||
Write-Output $fileContents
|
||||
}
|
||||
|
||||
|
||||
function Resolve-UpdateCheckFileName {
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet("Stable","Beta","Development")]
|
||||
$UpdateChannel,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet("Normal","Portable")]
|
||||
$Type
|
||||
)
|
||||
|
||||
$fileName = ""
|
||||
|
||||
if ($UpdateChannel -eq "Beta") { $fileName += "beta-" }
|
||||
elseif ($UpdateChannel -eq "Development") { $fileName += "dev-" }
|
||||
|
||||
$fileName += "update"
|
||||
|
||||
if ($Type -eq "Portable") { $fileName += "-portable" }
|
||||
|
||||
$fileName += ".txt"
|
||||
|
||||
Write-Output $fileName
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$releaseFolder = Join-Path -Path $PSScriptRoot -ChildPath "..\Release" -Resolve
|
||||
$tag = Read-Host -Prompt 'Tag name'
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
# build msi update file
|
||||
$msiFile = Get-ChildItem -Path "$releaseFolder\*.msi" | sort LastWriteTime | select -last 1
|
||||
$msiUpdateContents = New-MsiUpdateFileContent -MsiFile $msiFile -TagName $TagName
|
||||
$msiUpdateFileName = Resolve-UpdateCheckFileName -UpdateChannel $UpdateChannel -Type Normal
|
||||
Write-Output "`n`nMSI Update Check File Contents ($msiUpdateFileName)`n------------------------------"
|
||||
Tee-Object -InputObject $msiUpdateContents -FilePath "$releaseFolder\$msiUpdateFileName"
|
||||
|
||||
Write-Host PORTABLE
|
||||
Write-Host --------
|
||||
$file = Get-ChildItem -Path "$releaseFolder\*.zip" | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".zip")
|
||||
Write-Host Version: $version
|
||||
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
|
||||
Write-Host MSI
|
||||
Write-Host ---
|
||||
$file = Get-ChildItem -Path "$releaseFolder\*.msi" | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".msi")
|
||||
Write-Host Version: $version
|
||||
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
|
||||
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
# build zip update file
|
||||
$zipFile = Get-ChildItem -Path "$releaseFolder\*.zip" | sort LastWriteTime | select -last 1
|
||||
$zipUpdateContents = New-ZipUpdateFileContent -ZipFile $zipFile -TagName $TagName
|
||||
$zipUpdateFileName = Resolve-UpdateCheckFileName -UpdateChannel $UpdateChannel -Type Portable
|
||||
Write-Output "`n`nZip Update Check File Contents ($zipUpdateFileName)`n------------------------------"
|
||||
Tee-Object -InputObject $zipUpdateContents -FilePath "$releaseFolder\$zipUpdateFileName"
|
||||
220
Tools/github_functions.ps1
Normal file
220
Tools/github_functions.ps1
Normal file
@@ -0,0 +1,220 @@
|
||||
$githubUrl = 'https://api.github.com'
|
||||
|
||||
|
||||
function Publish-GitHubRelease {
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Owner,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Repository,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$ReleaseTitle,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$TagName,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# Either the SHA of the commit to target or the branch name.
|
||||
$TargetCommitish,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Description,
|
||||
|
||||
[bool]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$IsDraft,
|
||||
|
||||
[bool]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$IsPrerelease,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# The OAuth2 token to use for authentication.
|
||||
$AuthToken
|
||||
)
|
||||
|
||||
$body = New-GitHubReleaseRequestBody -TagName $TagName -TargetCommitish $TargetCommitish -ReleaseTitle $ReleaseTitle -Description $Description -IsDraft $IsDraft -IsPrerelease $IsPrerelease
|
||||
$req_publishRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases" -Method Post -Headers @{"Authorization"="token $AuthToken"} -Body $body -ErrorAction Stop
|
||||
$response_publishRelease = ConvertFrom-Json -InputObject $req_publishRelease.Content
|
||||
|
||||
Write-Output $response_publishRelease
|
||||
}
|
||||
|
||||
|
||||
function Edit-GitHubRelease {
|
||||
param (
|
||||
[string]
|
||||
#[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Owner,
|
||||
|
||||
[string]
|
||||
#[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Repository,
|
||||
|
||||
[string]
|
||||
#[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$ReleaseId,
|
||||
|
||||
[string]
|
||||
#
|
||||
$ReleaseTitle,
|
||||
|
||||
[string]
|
||||
#
|
||||
$TagName,
|
||||
|
||||
[string]
|
||||
# Either the SHA of the commit to target or the branch name.
|
||||
$TargetCommitish,
|
||||
|
||||
[string]
|
||||
#
|
||||
$Description,
|
||||
|
||||
[bool]
|
||||
#
|
||||
$IsDraft,
|
||||
|
||||
[bool]
|
||||
#
|
||||
$IsPrerelease,
|
||||
|
||||
[string]
|
||||
#[Parameter(Mandatory=$true)]
|
||||
# The OAuth2 token to use for authentication.
|
||||
$AuthToken
|
||||
)
|
||||
|
||||
$body_params = @{
|
||||
"TagName" = $TagName
|
||||
"TargetCommitish" = $TargetCommitish
|
||||
"ReleaseTitle" = $ReleaseTitle
|
||||
"Description" = $Description
|
||||
}
|
||||
if ($PSBoundParameters.ContainsKey("IsDraft")) { $body_params.Add("IsDraft", $IsDraft) }
|
||||
if ($PSBoundParameters.ContainsKey("IsPrerelease")) { $body_params.Add("IsPrerelease", $IsPrerelease) }
|
||||
|
||||
$body = New-GitHubReleaseRequestBody @body_params
|
||||
$req_editRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases/$ReleaseId" -Method Post -Headers @{"Authorization"="token $AuthToken"} -Body $body -ErrorAction Stop
|
||||
$response_editRelease = ConvertFrom-Json -InputObject $req_editRelease.Content
|
||||
|
||||
Write-Output $response_editRelease
|
||||
}
|
||||
|
||||
|
||||
function Get-GitHubRelease {
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Owner,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Repository,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$ReleaseId,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# The OAuth2 token to use for authentication.
|
||||
$AuthToken
|
||||
)
|
||||
|
||||
$req_getRelease = Invoke-WebRequest -Uri "$githubUrl/repos/$Owner/$Repository/releases/$ReleaseId" -Method Get -Headers @{"Authorization"="token $AuthToken"} -ErrorAction Stop
|
||||
$response_getRelease = ConvertFrom-Json -InputObject $req_getRelease.Content
|
||||
|
||||
Write-Output $response_getRelease
|
||||
}
|
||||
|
||||
|
||||
function Upload-GitHubReleaseAsset {
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$UploadUri,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# Path to the file to upload with the release
|
||||
$FilePath,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# Content type of the file
|
||||
$ContentType,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# The OAuth2 token to use for authentication.
|
||||
$AuthToken
|
||||
)
|
||||
|
||||
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
|
||||
$file = Get-Item -Path $FilePath
|
||||
|
||||
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
|
||||
}
|
||||
|
||||
|
||||
function New-GitHubReleaseRequestBody {
|
||||
param (
|
||||
[string]
|
||||
#
|
||||
$TagName,
|
||||
|
||||
[string]
|
||||
# Either the SHA of the commit to target or the branch name.
|
||||
$TargetCommitish,
|
||||
|
||||
[string]
|
||||
# Title of the release
|
||||
$ReleaseTitle,
|
||||
|
||||
[string]
|
||||
# Description of the release
|
||||
$Description,
|
||||
|
||||
[bool]
|
||||
# Is this a draft?
|
||||
$IsDraft,
|
||||
|
||||
[bool]
|
||||
# Is this a pre-release?
|
||||
$IsPrerelease
|
||||
)
|
||||
|
||||
$body_params = [ordered]@{}
|
||||
if ($TagName -ne "") { $body_params.Add("tag_name", $TagName) }
|
||||
if ($TargetCommitish -ne "") { $body_params.Add("target_commitish", $TargetCommitish) }
|
||||
if ($ReleaseTitle -ne "") { $body_params.Add("name", $ReleaseTitle) }
|
||||
if ($Description -ne "") { $body_params.Add("body", $Description) }
|
||||
if ($PSBoundParameters.ContainsKey("IsDraft")) { $body_params.Add("draft", $IsDraft) }
|
||||
if ($PSBoundParameters.ContainsKey("IsPrerelease")) { $body_params.Add("prerelease", $IsPrerelease) }
|
||||
|
||||
$json_body = ConvertTo-Json -InputObject $body_params -Compress
|
||||
Write-Output $json_body
|
||||
}
|
||||
23
Tools/move_help_files.ps1
Normal file
23
Tools/move_help_files.ps1
Normal 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 ""
|
||||
43
Tools/postbuild_installer.ps1
Normal file
43
Tools/postbuild_installer.ps1
Normal 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 -CertificatePath $CertificatePath
|
||||
& "$PSScriptRoot\rename_installer_with_version.ps1" -SolutionDir $SolutionDir
|
||||
& "$PSScriptRoot\copy_release_installer.ps1" -SourcePath $TargetDir -DestinationDir (Join-Path -Path $SolutionDir -ChildPath "Release")
|
||||
47
Tools/postbuild_mremotev1.ps1
Normal file
47
Tools/postbuild_mremotev1.ps1
Normal 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
|
||||
25
Tools/publish_draft_github_release.ps1
Normal file
25
Tools/publish_draft_github_release.ps1
Normal file
@@ -0,0 +1,25 @@
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Owner,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$Repository,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
#
|
||||
$ReleaseId,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
# The OAuth2 token to use for authentication.
|
||||
$AuthToken
|
||||
)
|
||||
|
||||
. "$PSScriptRoot\github_functions.ps1"
|
||||
|
||||
Edit-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $ReleaseId -AuthToken $AuthToken -IsDraft $false
|
||||
76
Tools/publish_to_github.ps1
Normal file
76
Tools/publish_to_github.ps1
Normal file
@@ -0,0 +1,76 @@
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
if ($DescriptionIsBase64Encoded) {
|
||||
$Description = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Description)))
|
||||
}
|
||||
|
||||
|
||||
. "$PSScriptRoot\github_functions.ps1"
|
||||
|
||||
|
||||
$release = Publish-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseTitle $ReleaseTitle -TagName $TagName -TargetCommitish $TargetCommitish -Description $Description -IsDraft ([bool]::Parse($IsDraft)) -IsPrerelease ([bool]::Parse($IsPrerelease)) -AuthToken $AuthToken
|
||||
$zipUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $ZipFilePath -ContentType "application/zip" -AuthToken $AuthToken
|
||||
$msiUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $MsiFilePath -ContentType "application/octet-stream" -AuthToken $AuthToken
|
||||
Write-Output (Get-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $release.id -AuthToken $AuthToken)
|
||||
@@ -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
|
||||
|
||||
43
Tools/set_LargeAddressAware.ps1
Normal file
43
Tools/set_LargeAddressAware.ps1
Normal file
@@ -0,0 +1,43 @@
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TargetDir,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TargetFileName
|
||||
)
|
||||
|
||||
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
|
||||
|
||||
# Find editbin.exe
|
||||
#Resolve-Path tends to be faster, but since editbin's are all over the place it's not 100% effective
|
||||
$editBinPath = @((Resolve-Path -Path "C:\Program Files*\Microsoft Visual Studio*\VC\bin\editbin.exe").Path)
|
||||
|
||||
if(!$editBinPath)
|
||||
{
|
||||
# This should work on all VS versions, but doesn't on our Jenkin's build for some reason...
|
||||
# This is needed VC Community
|
||||
$editBinPath = @((gci -Path "C:\Program*\Microsoft Visual Studio\" -Filter editbin.exe -Recurse)[0].FullName)
|
||||
}
|
||||
|
||||
# if we STILL can't find it, just return. Same end result NUnit test will fail.
|
||||
if(!$editBinPath)
|
||||
{
|
||||
echo "Could not find editbin.exe - Can't set LargeAddressAware"
|
||||
return
|
||||
}
|
||||
|
||||
echo "editBinPath value:"
|
||||
echo $editBinPath
|
||||
# Verify editbin certificate
|
||||
& "$PSScriptRoot\validate_microsoft_tool.ps1" -FullPath "$editBinPath"
|
||||
|
||||
|
||||
$outputExe = Join-Path -Path $TargetDir -ChildPath $TargetFileName
|
||||
|
||||
# Set LargeAddressAware
|
||||
Write-Output "Setting LargeAddressAware on binary file `"$outputExe`""
|
||||
& $editBinPath "/largeaddressaware" "$outputExe"
|
||||
|
||||
Write-Output ""
|
||||
80
Tools/sign_binaries.ps1
Normal file
80
Tools/sign_binaries.ps1
Normal 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 ""
|
||||
@@ -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
|
||||
}
|
||||
33
Tools/tidy_files_for_release.ps1
Normal file
33
Tools/tidy_files_for_release.ps1
Normal 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 ""
|
||||
17
Tools/validate_microsoft_tool.ps1
Normal file
17
Tools/validate_microsoft_tool.ps1
Normal file
@@ -0,0 +1,17 @@
|
||||
# $FullPath Full path to the Microsoft executable to validate
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$FullPath
|
||||
)
|
||||
|
||||
$validMSCertThumbprints = @("3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC", "108E2BA23632620C427C570B6D9DB51AC31387FE", "98ED99A67886D020C564923B7DF25E9AC019DF26", "5EAD300DC7E4D637948ECB0ED829A072BD152E17")
|
||||
$exeSignature = Get-AuthenticodeSignature -FilePath $FullPath
|
||||
$baseErrorMsg = "Could not validate the certificate of $FullPath. "
|
||||
|
||||
if ($exeSignature.Status -ne "Valid") {
|
||||
Write-Error -Message ($baseErrorMsg+"The signature was invalid.") -ErrorAction Stop
|
||||
}
|
||||
elseif ($validMSCertThumbprints -notcontains $exeSignature.SignerCertificate.Thumbprint) {
|
||||
Write-Error -Message ($baseErrorMsg+"The certificate thumbprint ($($exeSignature.SignerCertificate.Thumbprint)) is not trusted.") -ErrorAction Stop
|
||||
}
|
||||
47
Tools/verify_binary_signatures.ps1
Normal file
47
Tools/verify_binary_signatures.ps1
Normal file
@@ -0,0 +1,47 @@
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TargetDir,
|
||||
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$ConfigurationName,
|
||||
|
||||
[string]
|
||||
# The code signing certificate to use when signing the files.
|
||||
$CertificatePath
|
||||
)
|
||||
|
||||
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
|
||||
|
||||
# validate release versions and if the certificate is available
|
||||
if ($ConfigurationName -match "Release") {
|
||||
|
||||
if ($CertificatePath -eq "" -or !(Test-Path -Path $CertificatePath -PathType Leaf))
|
||||
{
|
||||
Write-Output "Certificate is not present - files likely not signed - we won't verify file signatures."
|
||||
return
|
||||
}
|
||||
|
||||
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 ""
|
||||
28
Tools/zip_portable_files.ps1
Normal file
28
Tools/zip_portable_files.ps1
Normal 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 ""
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
57
mRemoteNGTests/Connection/Protocol/IntegratedProgramTests.cs
Normal file
57
mRemoteNGTests/Connection/Protocol/IntegratedProgramTests.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System.Collections;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Window;
|
||||
using NUnit.Framework;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace mRemoteNGTests.Connection.Protocol
|
||||
{
|
||||
public class IntegratedProgramTests
|
||||
{
|
||||
private readonly ExternalTool _extTool = new ExternalTool
|
||||
{
|
||||
DisplayName = "notepad",
|
||||
FileName = @"%windir%\system32\notepad.exe",
|
||||
Arguments = "",
|
||||
TryIntegrate = true
|
||||
};
|
||||
|
||||
|
||||
[Test]
|
||||
public void CanStartExternalApp()
|
||||
{
|
||||
SetExternalToolList(_extTool);
|
||||
var sut = new IntegratedProgram();
|
||||
sut.InterfaceControl = BuildInterfaceControl("notepad", sut);
|
||||
sut.Initialize();
|
||||
var appStarted = sut.Connect();
|
||||
sut.Disconnect();
|
||||
Assert.That(appStarted);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConnectingToExternalAppThatDoesntExistDoesNothing()
|
||||
{
|
||||
SetExternalToolList(_extTool);
|
||||
var sut = new IntegratedProgram();
|
||||
sut.InterfaceControl = BuildInterfaceControl("doesntExist", sut);
|
||||
var appInitialized = sut.Initialize();
|
||||
Assert.That(appInitialized, Is.False);
|
||||
}
|
||||
|
||||
private void SetExternalToolList(ExternalTool externalTool)
|
||||
{
|
||||
Runtime.ExternalTools = new ArrayList {externalTool};
|
||||
}
|
||||
|
||||
private InterfaceControl BuildInterfaceControl(string extAppName, ProtocolBase sut)
|
||||
{
|
||||
var connectionWindow = new ConnectionWindow(new DockContent());
|
||||
var connectionInfo = new ConnectionInfo {ExtApp = extAppName};
|
||||
return new InterfaceControl(connectionWindow, sut, connectionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
25
mRemoteNGTests/TestHelpers/ConnectionTreeModelBuilder.cs
Normal file
25
mRemoteNGTests/TestHelpers/ConnectionTreeModelBuilder.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -62,13 +62,11 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\mRemoteV1\References\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NSubstitute, Version=1.10.0.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NSubstitute.1.10.0.0\lib\net45\NSubstitute.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="NSubstitute, Version=2.0.3.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NSubstitute.2.0.3\lib\net45\NSubstitute.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NUnitForms">
|
||||
<HintPath>nUnitForms\bin\NUnitForms.dll</HintPath>
|
||||
@@ -111,6 +109,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" />
|
||||
@@ -124,11 +123,13 @@
|
||||
<Compile Include="Config\Serializers\XmlRootNodeSerializerTests.cs" />
|
||||
<Compile Include="Connection\AbstractConnectionInfoDataTests.cs" />
|
||||
<Compile Include="Connection\ConnectionInfoComparerTests.cs" />
|
||||
<Compile Include="Connection\Protocol\IntegratedProgramTests.cs" />
|
||||
<Compile Include="Connection\Protocol\ProtocolListTests.cs" />
|
||||
<Compile Include="IntegrationTests\XmlSerializationLifeCycleTests.cs" />
|
||||
<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" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="BouncyCastle" version="1.8.1" targetFramework="net45" />
|
||||
<package id="DockPanelSuite" version="2.10.0" targetFramework="net45" />
|
||||
<package id="DockPanelSuite.ThemeVS2012Light" version="2.10.0" targetFramework="net45" />
|
||||
<package id="NSubstitute" version="1.10.0.0" targetFramework="net45" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net45" />
|
||||
<package id="NSubstitute" version="2.0.3" targetFramework="net45" />
|
||||
<package id="NUnit" version="3.8.1" targetFramework="net45" />
|
||||
<package id="ObjectListView.Official" version="2.9.1" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using log4net;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using log4net.Config;
|
||||
#if !PORTABLE
|
||||
@@ -45,14 +46,23 @@ namespace mRemoteNG.App
|
||||
|
||||
private static string BuildLogFilePath()
|
||||
{
|
||||
if (!Settings.Default.WriteLogFile)
|
||||
return "";
|
||||
|
||||
#if !PORTABLE
|
||||
var logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.ProductName);
|
||||
#else
|
||||
var logFilePath = Application.StartupPath;
|
||||
#endif
|
||||
var logFileName = Path.ChangeExtension(Application.ProductName, ".log");
|
||||
var logFile = Path.Combine(logFilePath, logFileName);
|
||||
return logFile;
|
||||
if (logFileName != null)
|
||||
{
|
||||
var logFile = Path.Combine(logFilePath, logFileName);
|
||||
return logFile;
|
||||
}
|
||||
|
||||
Debug.Print("Error: Could not determine log file path.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace mRemoteNG.App
|
||||
public static bool IsConnectionsFileLoaded { get; set; }
|
||||
public static RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; }
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
||||
private static DateTime LastSqlUpdate { get; set; }
|
||||
public static DateTime LastSqlUpdate { get; set; }
|
||||
public static ArrayList ExternalTools { get; set; } = new ArrayList();
|
||||
public static SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
|
||||
public static ConnectionTreeModel ConnectionTreeModel
|
||||
@@ -283,7 +283,7 @@ namespace mRemoteNG.App
|
||||
connectionsLoader.ConnectionFileName = GetStartupConnectionFileName();
|
||||
}
|
||||
|
||||
CreateBackupFile(Convert.ToString(connectionsLoader.ConnectionFileName));
|
||||
CreateBackupFile(connectionsLoader.ConnectionFileName);
|
||||
}
|
||||
|
||||
connectionsLoader.UseDatabase = Settings.Default.UseSQLServer;
|
||||
@@ -334,7 +334,7 @@ namespace mRemoteNG.App
|
||||
if (ex is FileNotFoundException && !withDialog)
|
||||
{
|
||||
MessageCollector.AddExceptionMessage(string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionsLoader.ConnectionFileName), ex, MessageClass.InformationMsg);
|
||||
NewConnections(Convert.ToString(connectionsLoader.ConnectionFileName));
|
||||
NewConnections(connectionsLoader.ConnectionFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -465,11 +465,11 @@ namespace mRemoteNG.App
|
||||
if (Settings.Default.UseSQLServer)
|
||||
{
|
||||
connectionsSaver.SaveFormat = ConnectionsSaver.Format.SQL;
|
||||
connectionsSaver.SQLHost = Convert.ToString(Settings.Default.SQLHost);
|
||||
connectionsSaver.SQLDatabaseName = Convert.ToString(Settings.Default.SQLDatabaseName);
|
||||
connectionsSaver.SQLUsername = Convert.ToString(Settings.Default.SQLUser);
|
||||
connectionsSaver.SQLHost = Settings.Default.SQLHost;
|
||||
connectionsSaver.SQLDatabaseName = Settings.Default.SQLDatabaseName;
|
||||
connectionsSaver.SQLUsername = Settings.Default.SQLUser;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
connectionsSaver.SQLPassword = cryptographyProvider.Decrypt(Convert.ToString(Settings.Default.SQLPass), EncryptionKey);
|
||||
connectionsSaver.SQLPassword = cryptographyProvider.Decrypt(Settings.Default.SQLUser, EncryptionKey);
|
||||
}
|
||||
|
||||
connectionsSaver.SaveConnections();
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace mRemoteNG.App
|
||||
ParseCommandLineArgs();
|
||||
IeBrowserEmulation.Register();
|
||||
GetConnectionIcons();
|
||||
DefaultConnectionInfo.Instance.LoadFrom(Settings.Default, a=>"ConDefault"+a);
|
||||
DefaultConnectionInheritance.Instance.LoadFrom(Settings.Default, a=>"InhDefault"+a);
|
||||
}
|
||||
|
||||
private static void GetConnectionIcons()
|
||||
@@ -76,7 +74,7 @@ namespace mRemoteNG.App
|
||||
{
|
||||
var osData = GetOperatingSystemData();
|
||||
var architecture = GetArchitectureData();
|
||||
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(Convert.ToString(s)))));
|
||||
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(s))));
|
||||
}
|
||||
|
||||
private static string GetOperatingSystemData()
|
||||
@@ -214,10 +212,37 @@ namespace mRemoteNG.App
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("GetUpdateInfoCompleted() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector.AddExceptionMessage("GetUpdateInfoCompleted() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a path to a file connections XML file for a given absolute or relative path
|
||||
/// </summary>
|
||||
/// <param name="ConsParam">The absolute or relative path to the connection XML file</param>
|
||||
/// <returns>string or null</returns>
|
||||
private static string GetCustomConsPath(string ConsParam)
|
||||
{
|
||||
// early exit condition
|
||||
if (string.IsNullOrEmpty(ConsParam))
|
||||
return null;
|
||||
|
||||
// trim invalid characters for the Combine method (see: https://msdn.microsoft.com/en-us/library/fyy7a5kt.aspx#Anchor_2)
|
||||
ConsParam = ConsParam.Trim().TrimStart('\\').Trim();
|
||||
|
||||
// fallback paths
|
||||
if (File.Exists(ConsParam))
|
||||
return ConsParam;
|
||||
|
||||
if (File.Exists(Path.Combine(GeneralAppInfo.HomePath, ConsParam)))
|
||||
return GeneralAppInfo.HomePath + Path.DirectorySeparatorChar + ConsParam;
|
||||
|
||||
if (File.Exists(Path.Combine(ConnectionsFileInfo.DefaultConnectionsPath, ConsParam)))
|
||||
return ConnectionsFileInfo.DefaultConnectionsPath + Path.DirectorySeparatorChar + ConsParam;
|
||||
|
||||
// default case
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void ParseCommandLineArgs()
|
||||
{
|
||||
@@ -282,29 +307,12 @@ namespace mRemoteNG.App
|
||||
NoReconnectParam = "norc";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ConsParam))
|
||||
// Handle custom connection file location
|
||||
var consPathFromParam = GetCustomConsPath(ConsParam);
|
||||
if (consPathFromParam != null)
|
||||
{
|
||||
if (File.Exists(cmd[ConsParam]) == false)
|
||||
{
|
||||
if (File.Exists(GeneralAppInfo.HomePath + "\\" + cmd[ConsParam]))
|
||||
{
|
||||
Settings.Default.LoadConsFromCustomLocation = true;
|
||||
Settings.Default.CustomConsPath = GeneralAppInfo.HomePath + "\\" + cmd[ConsParam];
|
||||
return;
|
||||
}
|
||||
if (File.Exists(ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam]))
|
||||
{
|
||||
Settings.Default.LoadConsFromCustomLocation = true;
|
||||
Settings.Default.CustomConsPath = ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings.Default.LoadConsFromCustomLocation = true;
|
||||
Settings.Default.CustomConsPath = cmd[ConsParam];
|
||||
return;
|
||||
}
|
||||
Settings.Default.CustomConsPath = consPathFromParam;
|
||||
Settings.Default.LoadConsFromCustomLocation = true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ResetPosParam))
|
||||
@@ -329,6 +337,8 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Settings.Default.ResetToolbars = true;
|
||||
}
|
||||
|
||||
Settings.Default.Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -57,7 +57,15 @@ namespace mRemoteNG.Config.Connections
|
||||
|
||||
private bool DatabaseIsMoreUpToDateThanUs()
|
||||
{
|
||||
return GetLastUpdateTimeFromDbResponse() > _lastUpdateTime;
|
||||
var lastUpdateInDb = GetLastUpdateTimeFromDbResponse();
|
||||
var IAmTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
|
||||
return (lastUpdateInDb > _lastUpdateTime && !IAmTheLastoneUpdated);
|
||||
}
|
||||
|
||||
private bool CheckIfIAmTheLastOneUpdated(DateTime lastUpdateInDb)
|
||||
{
|
||||
DateTime LastSqlUpdateWithoutMilliseconds = new DateTime(Runtime.LastSqlUpdate.Ticks - (Runtime.LastSqlUpdate.Ticks % TimeSpan.TicksPerSecond), Runtime.LastSqlUpdate.Kind);
|
||||
return lastUpdateInDb == LastSqlUpdateWithoutMilliseconds;
|
||||
}
|
||||
|
||||
private DateTime GetLastUpdateTimeFromDbResponse()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -41,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;
|
||||
}
|
||||
@@ -67,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"];
|
||||
@@ -155,8 +170,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"];
|
||||
@@ -193,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);
|
||||
|
||||
@@ -25,145 +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()
|
||||
{
|
||||
_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("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));
|
||||
_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("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));
|
||||
_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));
|
||||
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)
|
||||
@@ -184,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;
|
||||
@@ -204,8 +221,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 +237,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 +284,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 +293,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 +341,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 +350,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;
|
||||
|
||||
158
mRemoteV1/Config/Serializers/SqlDatabaseVersionVerifier.cs
Normal file
158
mRemoteV1/Config/Serializers/SqlDatabaseVersionVerifier.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -18,11 +18,17 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public void LoadFrom<TSource>(TSource sourceInstance, Func<string, string> propertyNameMutator = null)
|
||||
{
|
||||
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
|
||||
if (propertyNameMutator == null) propertyNameMutator = a => a;
|
||||
var connectionProperties = GetProperties(_excludedProperties);
|
||||
foreach (var property in connectionProperties)
|
||||
{
|
||||
var propertyFromSource = typeof(TSource).GetProperty(propertyNameMutator(property.Name));
|
||||
if (propertyFromSource == null)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg,
|
||||
$"DefaultConInfo-LoadFrom: Could not load {property.Name}", true);
|
||||
continue;
|
||||
}
|
||||
var valueFromSource = propertyFromSource.GetValue(sourceInstance, null);
|
||||
|
||||
var descriptor = TypeDescriptor.GetProperties(Instance)[property.Name];
|
||||
@@ -36,7 +42,7 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public void SaveTo<TDestination>(TDestination destinationInstance, Func<string, string> propertyNameMutator = null)
|
||||
{
|
||||
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
|
||||
if (propertyNameMutator == null) propertyNameMutator = a => a;
|
||||
var inheritanceProperties = GetProperties(_excludedProperties);
|
||||
foreach (var property in inheritanceProperties)
|
||||
{
|
||||
@@ -44,6 +50,12 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
var propertyFromDestination = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
|
||||
var localValue = property.GetValue(Instance, null);
|
||||
if (propertyFromDestination == null)
|
||||
{
|
||||
Runtime.MessageCollector?.AddMessage(Messages.MessageClass.ErrorMsg,
|
||||
$"DefaultConInfo-SaveTo: Could not load {property.Name}", true);
|
||||
continue;
|
||||
}
|
||||
var convertedValue = Convert.ChangeType(localValue, propertyFromDestination.PropertyType);
|
||||
propertyFromDestination.SetValue(destinationInstance, convertedValue, null);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using mRemoteNG.App;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
@@ -17,11 +18,17 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public void LoadFrom<TSource>(TSource sourceInstance, Func<string,string> propertyNameMutator = null)
|
||||
{
|
||||
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
|
||||
if (propertyNameMutator == null) propertyNameMutator = a => a;
|
||||
var inheritanceProperties = GetProperties();
|
||||
foreach (var property in inheritanceProperties)
|
||||
{
|
||||
var propertyFromSettings = typeof(TSource).GetProperty(propertyNameMutator(property.Name));
|
||||
if (propertyFromSettings == null)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg,
|
||||
$"DefaultConInherit-LoadFrom: Could not load {property.Name}", true);
|
||||
continue;
|
||||
}
|
||||
var valueFromSettings = propertyFromSettings.GetValue(sourceInstance, null);
|
||||
property.SetValue(Instance, valueFromSettings, null);
|
||||
}
|
||||
@@ -29,12 +36,18 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public void SaveTo<TDestination>(TDestination destinationInstance, Func<string, string> propertyNameMutator = null)
|
||||
{
|
||||
if (propertyNameMutator == null) propertyNameMutator = (a) => a;
|
||||
if (propertyNameMutator == null) propertyNameMutator = a => a;
|
||||
var inheritanceProperties = GetProperties();
|
||||
foreach (var property in inheritanceProperties)
|
||||
{
|
||||
var propertyFromSettings = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
|
||||
var localValue = property.GetValue(Instance, null);
|
||||
if (propertyFromSettings == null)
|
||||
{
|
||||
Runtime.MessageCollector?.AddMessage(Messages.MessageClass.ErrorMsg,
|
||||
$"DefaultConInherit-SaveTo: Could not load {property.Name}", true);
|
||||
continue;
|
||||
}
|
||||
propertyFromSettings.SetValue(destinationInstance, localValue, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Tools;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
@@ -21,9 +21,15 @@ namespace mRemoteNG.Connection.Protocol
|
||||
#region Public Methods
|
||||
public override bool Initialize()
|
||||
{
|
||||
if (InterfaceControl.Info == null) return base.Initialize();
|
||||
if (InterfaceControl.Info == null)
|
||||
return base.Initialize();
|
||||
|
||||
_externalTool = Runtime.GetExtAppByName(InterfaceControl.Info.ExtApp);
|
||||
if (_externalTool == null)
|
||||
{
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.ErrorMsg, string.Format(Language.CouldNotFindExternalTool, InterfaceControl.Info.ExtApp));
|
||||
return false;
|
||||
}
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
|
||||
return base.Initialize();
|
||||
@@ -33,7 +39,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
try
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Attempting to start: {_externalTool.DisplayName}", true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, $"Attempting to start: {_externalTool.DisplayName}", true);
|
||||
|
||||
if (_externalTool.TryIntegrate == false)
|
||||
{
|
||||
@@ -43,7 +49,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
* will be called - which is just going to call IntegratedProgram.Close() again anyway...
|
||||
* Close();
|
||||
*/
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Assuming no other errors/exceptions occurred immediately before this message regarding {_externalTool.DisplayName}, the next \"closed by user\" message can be ignored", true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, $"Assuming no other errors/exceptions occurred immediately before this message regarding {_externalTool.DisplayName}, the next \"closed by user\" message can be ignored", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,9 +69,9 @@ namespace mRemoteNG.Connection.Protocol
|
||||
_process.Exited += ProcessExited;
|
||||
|
||||
_process.Start();
|
||||
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
|
||||
|
||||
var startTicks = Environment.TickCount;
|
||||
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
|
||||
|
||||
var startTicks = Environment.TickCount;
|
||||
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + Settings.Default.MaxPuttyWaitTime * 1000)
|
||||
{
|
||||
_process.Refresh();
|
||||
@@ -80,10 +86,10 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
|
||||
NativeMethods.SetParent(_handle, InterfaceControl.Handle);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppHandle, _handle), true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppTitle, _process.MainWindowTitle), true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppParentHandle, InterfaceControl.Parent.Handle), true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppHandle, _handle), true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppTitle, _process.MainWindowTitle), true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, string.Format(Language.strIntAppParentHandle, InterfaceControl.Parent.Handle), true);
|
||||
|
||||
Resize(this, new EventArgs());
|
||||
base.Connect();
|
||||
@@ -91,7 +97,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppConnectionFailed, ex);
|
||||
Runtime.MessageCollector?.AddExceptionMessage(Language.strIntAppConnectionFailed, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't dispose control, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
Runtime.MessageCollector?.AddExceptionStackTrace("Couldn't dispose control, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,12 +172,12 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't set InterfaceControl.Parent.Tag or Dispose Interface, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
Runtime.MessageCollector?.AddExceptionStackTrace("Couldn't set InterfaceControl.Parent.Tag or Dispose Interface, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't Close InterfaceControl BG (Connection.Protocol.Base)", ex);
|
||||
Runtime.MessageCollector?.AddExceptionStackTrace("Couldn't Close InterfaceControl BG (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
else if (Settings.Default.EmptyCredentials == "custom")
|
||||
{
|
||||
username = Convert.ToString(Settings.Default.DefaultUsername);
|
||||
username = Settings.Default.DefaultUsername;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
if (Settings.Default.EmptyCredentials == "custom")
|
||||
{
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
password = cryptographyProvider.Decrypt(Convert.ToString(Settings.Default.DefaultPassword), Runtime.EncryptionKey);
|
||||
password = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
}
|
||||
else if (Settings.Default.EmptyCredentials == "custom")
|
||||
{
|
||||
_rdpClient.UserName = Convert.ToString(Settings.Default.DefaultUsername);
|
||||
_rdpClient.UserName = Settings.Default.DefaultUsername;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -443,7 +443,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
if (Settings.Default.DefaultPassword != "")
|
||||
{
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Convert.ToString(Settings.Default.DefaultPassword), Runtime.EncryptionKey);
|
||||
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,7 +460,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
|
||||
}
|
||||
else if (Settings.Default.EmptyCredentials == "custom")
|
||||
{
|
||||
_rdpClient.Domain = Convert.ToString(Settings.Default.DefaultDomain);
|
||||
_rdpClient.Domain = Settings.Default.DefaultDomain;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -34,28 +34,27 @@ namespace mRemoteNG.Messages
|
||||
|
||||
var EnableTimer = true; // used to control if we SWITCH to the notifiation panel. Message will still be added regardless.
|
||||
|
||||
if (nMsg.MsgClass == MessageClass.InformationMsg)
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (nMsg.MsgClass)
|
||||
{
|
||||
AddInfoMessage(nMsg);
|
||||
case MessageClass.InformationMsg:
|
||||
AddInfoMessage(nMsg);
|
||||
|
||||
if (!Settings.Default.SwitchToMCOnInformation)
|
||||
EnableTimer = false;
|
||||
}
|
||||
if (!Settings.Default.SwitchToMCOnInformation)
|
||||
EnableTimer = false;
|
||||
break;
|
||||
case MessageClass.WarningMsg:
|
||||
AddWarningMessage(nMsg);
|
||||
|
||||
if (nMsg.MsgClass == MessageClass.WarningMsg)
|
||||
{
|
||||
AddWarningMessage(nMsg);
|
||||
if (!Settings.Default.SwitchToMCOnWarning)
|
||||
EnableTimer = false;
|
||||
break;
|
||||
case MessageClass.ErrorMsg:
|
||||
AddErrorMessage(nMsg);
|
||||
|
||||
if (!Settings.Default.SwitchToMCOnWarning)
|
||||
EnableTimer = false;
|
||||
}
|
||||
|
||||
if (nMsg.MsgClass == MessageClass.ErrorMsg)
|
||||
{
|
||||
AddErrorMessage(nMsg);
|
||||
|
||||
if (!Settings.Default.SwitchToMCOnError)
|
||||
EnableTimer = false;
|
||||
if (!Settings.Default.SwitchToMCOnError)
|
||||
EnableTimer = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (OnlyLog)
|
||||
@@ -95,7 +94,8 @@ namespace mRemoteNG.Messages
|
||||
private static void AddErrorMessage(Message nMsg)
|
||||
{
|
||||
Debug.Print("Error: " + nMsg.MsgText);
|
||||
Logger.Instance.Error(nMsg.MsgText);
|
||||
if (Settings.Default.WriteLogFile)
|
||||
Logger.Instance.Error(nMsg.MsgText);
|
||||
}
|
||||
|
||||
private static void AddReportMessage(Message nMsg)
|
||||
|
||||
@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
|
||||
// by using the '*' as shown below:
|
||||
// <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
[assembly: AssemblyVersion("1.75.7000.*")]
|
||||
[assembly: AssemblyVersion("1.75.7011.*")]
|
||||
|
||||
[assembly:NeutralResourcesLanguageAttribute("en")]
|
||||
|
||||
|
||||
@@ -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 ,
|
||||
|
||||
11
mRemoteV1/Resources/Language/Language.Designer.cs
generated
11
mRemoteV1/Resources/Language/Language.Designer.cs
generated
@@ -60,6 +60,15 @@ namespace mRemoteNG {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not find external tool with name "{0}".
|
||||
/// </summary>
|
||||
internal static string CouldNotFindExternalTool {
|
||||
get {
|
||||
return ResourceManager.GetString("CouldNotFindExternalTool", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to About.
|
||||
/// </summary>
|
||||
@@ -440,7 +449,7 @@ namespace mRemoteNG {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You cannot import a normal connection file.
|
||||
///Please use File - Load Connections for normal connection files!.
|
||||
///Please use File - Open Connection File for normal connection files!.
|
||||
/// </summary>
|
||||
internal static string strCannotImportNormalSessionFile {
|
||||
get {
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
</data>
|
||||
<data name="strCannotImportNormalSessionFile" xml:space="preserve">
|
||||
<value>You cannot import a normal connection file.
|
||||
Please use File - Load Connections for normal connection files!</value>
|
||||
Please use File - Open Connection File for normal connection files!</value>
|
||||
</data>
|
||||
<data name="strCannotStartPortScan" xml:space="preserve">
|
||||
<value>IPアドレスのフォーマットが正しくないのでポートスキャンの開始に失敗しました</value>
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
</data>
|
||||
<data name="strCannotImportNormalSessionFile" xml:space="preserve">
|
||||
<value>You cannot import a normal connection file.
|
||||
Please use File - Load Connections for normal connection files!</value>
|
||||
Please use File - Open Connection File for normal connection files!</value>
|
||||
</data>
|
||||
<data name="strCannotStartPortScan" xml:space="preserve">
|
||||
<value>Cannot start Port Scan, incorrect IP format!</value>
|
||||
@@ -2433,4 +2433,7 @@ mRemoteNG will now quit and begin with the installation.</value>
|
||||
<data name="strPropertyNameRDPAlertIdleTimeout" xml:space="preserve">
|
||||
<value>Alert on Idle Disconnect</value>
|
||||
</data>
|
||||
<data name="CouldNotFindExternalTool" xml:space="preserve">
|
||||
<value>Could not find external tool with name "{0}"</value>
|
||||
</data>
|
||||
</root>
|
||||
Binary file not shown.
@@ -5,7 +5,6 @@ using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tree;
|
||||
|
||||
|
||||
@@ -31,7 +30,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("frmMain.AddNodeToMenu() failed", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector.AddExceptionMessage("frmMain.AddNodeToMenu() failed", ex);
|
||||
}
|
||||
return dropDownList;
|
||||
}
|
||||
@@ -67,7 +66,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
else if (node.GetTreeNodeType() == TreeNodeType.Connection)
|
||||
{
|
||||
menuItem.Image = Resources.Pause;
|
||||
menuItem.Image = node.OpenConnections.Count > 0 ? Resources.Play : Resources.Pause;
|
||||
menuItem.Tag = node;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.App;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
@@ -169,12 +171,26 @@ namespace mRemoteNG.Tools
|
||||
break;
|
||||
case "username":
|
||||
replacement = _connectionInfo.Username;
|
||||
if (string.IsNullOrEmpty(replacement))
|
||||
if (Settings.Default.EmptyCredentials == "windows")
|
||||
replacement = Environment.UserName;
|
||||
else if (Settings.Default.EmptyCredentials == "custom")
|
||||
replacement = Settings.Default.DefaultUsername;
|
||||
break;
|
||||
case "password":
|
||||
replacement = _connectionInfo.Password;
|
||||
if (string.IsNullOrEmpty(replacement) && Settings.Default.EmptyCredentials == "custom")
|
||||
replacement = new LegacyRijndaelCryptographyProvider()
|
||||
.Decrypt(Convert.ToString(Settings.Default.DefaultPassword),
|
||||
Runtime.EncryptionKey);
|
||||
break;
|
||||
case "domain":
|
||||
replacement = _connectionInfo.Domain;
|
||||
if (string.IsNullOrEmpty(replacement))
|
||||
if (Settings.Default.EmptyCredentials == "windows")
|
||||
replacement = Environment.UserDomainName;
|
||||
else if (Settings.Default.EmptyCredentials == "custom")
|
||||
replacement = Settings.Default.DefaultDomain;
|
||||
break;
|
||||
case "description":
|
||||
replacement = _connectionInfo.Description;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Microsoft.Win32;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.AccessControl;
|
||||
using Microsoft.Win32;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
@@ -202,7 +202,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("IeBrowserEmulation.Register() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector?.AddExceptionMessage("IeBrowserEmulation.Register() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("IeBrowserEmulation.Unregister() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
Runtime.MessageCollector?.AddExceptionMessage("IeBrowserEmulation.Unregister() failed.", ex, MessageClass.ErrorMsg, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace mRemoteNG.Tools
|
||||
|
||||
public PortScanner(IPAddress ipAddress1, IPAddress ipAddress2, int port1, int port2)
|
||||
{
|
||||
IPAddress ipAddressStart = IpAddressMin(ipAddress1, ipAddress2);
|
||||
IPAddress ipAddressEnd = IpAddressMax(ipAddress1, ipAddress2);
|
||||
var ipAddressStart = IpAddressMin(ipAddress1, ipAddress2);
|
||||
var ipAddressEnd = IpAddressMax(ipAddress1, ipAddress2);
|
||||
|
||||
int portStart = Math.Min(port1, port2);
|
||||
int portEnd = Math.Max(port1, port2);
|
||||
var portStart = Math.Min(port1, port2);
|
||||
var portEnd = Math.Max(port1, port2);
|
||||
|
||||
_ports.Clear();
|
||||
for (int port = portStart; port <= portEnd; port++)
|
||||
for (var port = portStart; port <= portEnd; port++)
|
||||
{
|
||||
_ports.Add(port);
|
||||
}
|
||||
@@ -59,8 +59,8 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Net.Sockets.TcpClient tcpClient = new System.Net.Sockets.TcpClient(hostname, Convert.ToInt32(port));
|
||||
tcpClient.Close();
|
||||
var tcpClient = new System.Net.Sockets.TcpClient(hostname, Convert.ToInt32(port));
|
||||
tcpClient.Close();
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -79,16 +79,21 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
hostCount = 0;
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Tools.PortScan: Starting scan of {_ipAddresses.Count} hosts...", true);
|
||||
foreach (IPAddress ipAddress in _ipAddresses)
|
||||
foreach (var ipAddress in _ipAddresses)
|
||||
{
|
||||
BeginHostScanEvent?.Invoke(ipAddress.ToString());
|
||||
|
||||
Ping pingSender = new Ping();
|
||||
var pingSender = new Ping();
|
||||
|
||||
try
|
||||
{
|
||||
pingSender.PingCompleted += PingSender_PingCompleted;
|
||||
pingSender.SendAsync(ipAddress, ipAddress);
|
||||
|
||||
/* https://msdn.microsoft.com/en-us/library/0e6kc029(v=vs.110).aspx
|
||||
* Default timeout is 5 seconds... That's a bit long...
|
||||
*/
|
||||
//TODO Make timeout configurable...
|
||||
pingSender.SendAsync(ipAddress, /*userToken:*/ ipAddress);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -109,7 +114,7 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
// UserState is the IP Address
|
||||
var ip = e.UserState.ToString();
|
||||
ScanHost scanHost = new ScanHost(ip);
|
||||
var scanHost = new ScanHost(ip);
|
||||
hostCount++;
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Tools.PortScan: Scanning {hostCount} of {_ipAddresses.Count} hosts: {scanHost.HostIp}", true);
|
||||
@@ -129,9 +134,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
catch (Exception dnsex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg,
|
||||
$"Tools.PortScan: Could not resolve {scanHost.HostIp} {Environment.NewLine} {dnsex.Message}",
|
||||
true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Tools.PortScan: Could not resolve {scanHost.HostIp} {Environment.NewLine} {dnsex.Message}", true);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(scanHost.HostName))
|
||||
@@ -139,12 +142,12 @@ namespace mRemoteNG.Tools
|
||||
scanHost.HostName = scanHost.HostIp;
|
||||
}
|
||||
|
||||
foreach (int port in _ports)
|
||||
foreach (var port in _ports)
|
||||
{
|
||||
bool isPortOpen;
|
||||
try
|
||||
{
|
||||
System.Net.Sockets.TcpClient tcpClient = new System.Net.Sockets.TcpClient(ip, port);
|
||||
var tcpClient = new System.Net.Sockets.TcpClient(ip, port);
|
||||
isPortOpen = true;
|
||||
scanHost.OpenPorts.Add(port);
|
||||
tcpClient.Close();
|
||||
@@ -209,16 +212,16 @@ namespace mRemoteNG.Tools
|
||||
|
||||
private static IPAddress[] IpAddressArrayFromRange(IPAddress ipAddress1, IPAddress ipAddress2)
|
||||
{
|
||||
IPAddress startIpAddress = IpAddressMin(ipAddress1, ipAddress2);
|
||||
IPAddress endIpAddress = IpAddressMax(ipAddress1, ipAddress2);
|
||||
var startIpAddress = IpAddressMin(ipAddress1, ipAddress2);
|
||||
var endIpAddress = IpAddressMax(ipAddress1, ipAddress2);
|
||||
|
||||
int startAddress = IpAddressToInt32(startIpAddress);
|
||||
int endAddress = IpAddressToInt32(endIpAddress);
|
||||
int addressCount = endAddress - startAddress;
|
||||
var startAddress = IpAddressToInt32(startIpAddress);
|
||||
var endAddress = IpAddressToInt32(endIpAddress);
|
||||
var addressCount = endAddress - startAddress;
|
||||
|
||||
IPAddress[] addressArray = new IPAddress[addressCount + 1];
|
||||
int index = 0;
|
||||
for (int address = startAddress; address <= endAddress; address++)
|
||||
var addressArray = new IPAddress[addressCount + 1];
|
||||
var index = 0;
|
||||
for (var address = startAddress; address <= endAddress; address++)
|
||||
{
|
||||
addressArray[index] = IpAddressFromInt32(address);
|
||||
index++;
|
||||
@@ -229,26 +232,14 @@ namespace mRemoteNG.Tools
|
||||
|
||||
private static IPAddress IpAddressMin(IPAddress ipAddress1, IPAddress ipAddress2)
|
||||
{
|
||||
if (IpAddressCompare(ipAddress1, ipAddress2) < 0) // ipAddress1 < ipAddress2
|
||||
{
|
||||
return ipAddress1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ipAddress2;
|
||||
}
|
||||
// ipAddress1 < ipAddress2
|
||||
return IpAddressCompare(ipAddress1, ipAddress2) < 0 ? ipAddress1 : ipAddress2;
|
||||
}
|
||||
|
||||
private static IPAddress IpAddressMax(IPAddress ipAddress1, IPAddress ipAddress2)
|
||||
{
|
||||
if (IpAddressCompare(ipAddress1, ipAddress2) > 0) // ipAddress1 > ipAddress2
|
||||
{
|
||||
return ipAddress1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ipAddress2;
|
||||
}
|
||||
// ipAddress1 > ipAddress2
|
||||
return IpAddressCompare(ipAddress1, ipAddress2) > 0 ? ipAddress1 : ipAddress2;
|
||||
}
|
||||
|
||||
private static int IpAddressCompare(IPAddress ipAddress1, IPAddress ipAddress2)
|
||||
@@ -260,10 +251,10 @@ namespace mRemoteNG.Tools
|
||||
{
|
||||
if (ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
|
||||
{
|
||||
throw (new ArgumentException("ipAddress"));
|
||||
throw new ArgumentException("ipAddress");
|
||||
}
|
||||
|
||||
byte[] addressBytes = ipAddress.GetAddressBytes(); // in network order (big-endian)
|
||||
var addressBytes = ipAddress.GetAddressBytes(); // in network order (big-endian)
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(addressBytes); // to host order (little-endian)
|
||||
@@ -275,7 +266,7 @@ namespace mRemoteNG.Tools
|
||||
|
||||
private static IPAddress IpAddressFromInt32(int ipAddress)
|
||||
{
|
||||
byte[] addressBytes = BitConverter.GetBytes(ipAddress); // in host order
|
||||
var addressBytes = BitConverter.GetBytes(ipAddress); // in host order
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(addressBytes); // to network order (big-endian)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,12 @@ using mRemoteNG.Tree.Root;
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public partial class ConnectionTree : TreeListView, IConnectionTree
|
||||
public partial class ConnectionTree : TreeListView, IConnectionTree
|
||||
{
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
|
||||
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
|
||||
private bool _allowEdit;
|
||||
|
||||
public ConnectionInfo SelectedNode => (ConnectionInfo) SelectedObject;
|
||||
|
||||
@@ -90,23 +91,49 @@ namespace mRemoteNG.UI.Controls
|
||||
Collapsed += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = false;
|
||||
};
|
||||
if (container == null) return;
|
||||
container.IsExpanded = false;
|
||||
AutoResizeColumn(Columns[0]);
|
||||
};
|
||||
Expanded += (sender, args) =>
|
||||
{
|
||||
var container = args.Model as ContainerInfo;
|
||||
if (container != null)
|
||||
container.IsExpanded = true;
|
||||
};
|
||||
if (container == null) return;
|
||||
container.IsExpanded = true;
|
||||
AutoResizeColumn(Columns[0]);
|
||||
};
|
||||
SelectionChanged += tvConnections_AfterSelect;
|
||||
MouseDoubleClick += OnMouse_DoubleClick;
|
||||
MouseClick += OnMouse_SingleClick;
|
||||
CellToolTipShowing += tvConnections_CellToolTipShowing;
|
||||
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
|
||||
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
|
||||
BeforeLabelEdit += HandleCheckForValidEdit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes the given column to ensure that all content is shown
|
||||
/// </summary>
|
||||
private void AutoResizeColumn(ColumnHeader column)
|
||||
{
|
||||
var longestIndentationAndTextWidth = int.MinValue;
|
||||
var horizontalScrollOffset = LowLevelScrollPosition.X;
|
||||
const int padding = 10;
|
||||
|
||||
for (var i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var rowIndentation = Items[i].Position.X;
|
||||
var rowTextWidth = TextRenderer.MeasureText(Items[i].Text, Font).Width;
|
||||
|
||||
longestIndentationAndTextWidth = Math.Max(rowIndentation + rowTextWidth, longestIndentationAndTextWidth);
|
||||
}
|
||||
|
||||
column.Width = longestIndentationAndTextWidth +
|
||||
SmallImageSize.Width +
|
||||
horizontalScrollOffset +
|
||||
padding;
|
||||
}
|
||||
|
||||
private void PopulateTreeView()
|
||||
{
|
||||
UnregisterModelUpdateHandlers();
|
||||
@@ -114,7 +141,8 @@ namespace mRemoteNG.UI.Controls
|
||||
RegisterModelUpdateHandlers();
|
||||
NodeSearcher = new NodeSearcher(ConnectionTreeModel);
|
||||
ExecutePostSetupActions();
|
||||
}
|
||||
AutoResizeColumn(Columns[0]);
|
||||
}
|
||||
|
||||
private void RegisterModelUpdateHandlers()
|
||||
{
|
||||
@@ -137,13 +165,17 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void HandleCollectionPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
|
||||
// for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
|
||||
// Removed "TO DO" from above comment. Per #142 it apperas that this no longer occurs with ObjectListView 2.9.1
|
||||
var property = propertyChangedEventArgs.PropertyName;
|
||||
if (property != "Name" && property != "OpenConnections") return;
|
||||
var senderAsConnectionInfo = sender as ConnectionInfo;
|
||||
if (senderAsConnectionInfo != null)
|
||||
RefreshObject(senderAsConnectionInfo);
|
||||
}
|
||||
if (senderAsConnectionInfo == null)
|
||||
return;
|
||||
|
||||
RefreshObject(senderAsConnectionInfo);
|
||||
AutoResizeColumn(Columns[0]);
|
||||
}
|
||||
|
||||
private void ExecutePostSetupActions()
|
||||
{
|
||||
@@ -201,11 +233,12 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
// use root node if no node is selected
|
||||
ConnectionInfo parentNode = SelectedNode ?? GetRootConnectionNode();
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
var selectedContainer = parentNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? parentNode.Parent;
|
||||
newNode.SetParent(parent);
|
||||
Expand(parent);
|
||||
SelectObject(newNode, true);
|
||||
@@ -215,16 +248,31 @@ namespace mRemoteNG.UI.Controls
|
||||
public void DuplicateSelectedNode()
|
||||
{
|
||||
var newNode = SelectedNode.Clone();
|
||||
SelectedNode.Parent.AddChildBelow(newNode, SelectedNode);
|
||||
newNode.Parent.SetChildBelow(newNode, SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void RenameSelectedNode()
|
||||
{
|
||||
_allowEdit = true;
|
||||
SelectedItem.BeginEdit();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void HandleCheckForValidEdit(object sender, LabelEditEventArgs e)
|
||||
{
|
||||
if (!(sender is ConnectionTree)) return;
|
||||
if (_allowEdit)
|
||||
{
|
||||
_allowEdit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.CancelEdit = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteSelectedNode()
|
||||
{
|
||||
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
|
||||
@@ -236,7 +284,8 @@ namespace mRemoteNG.UI.Controls
|
||||
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshObject(sender);
|
||||
}
|
||||
AutoResizeColumn(Columns[0]);
|
||||
}
|
||||
|
||||
private void tvConnections_AfterSelect(object sender, EventArgs e)
|
||||
{
|
||||
@@ -255,7 +304,7 @@ namespace mRemoteNG.UI.Controls
|
||||
if (mouseEventArgs.Clicks < 2) 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;
|
||||
DoubleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace mRemoteNG.UI.Controls
|
||||
public NameColumn(ImageGetterDelegate imageGetterDelegate)
|
||||
{
|
||||
AspectName = "Name";
|
||||
FillsFreeSpace = true;
|
||||
IsButton = true;
|
||||
FillsFreeSpace = false;
|
||||
AspectGetter = item => ((ConnectionInfo) item).Name;
|
||||
ImageGetter = imageGetterDelegate;
|
||||
}
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
radCredentialsCustom.Checked = true;
|
||||
}
|
||||
|
||||
txtCredentialsUsername.Text = Convert.ToString(Settings.Default.DefaultUsername);
|
||||
txtCredentialsUsername.Text = Settings.Default.DefaultUsername;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
txtCredentialsPassword.Text = cryptographyProvider.Decrypt(Convert.ToString(Settings.Default.DefaultPassword), Runtime.EncryptionKey);
|
||||
txtCredentialsDomain.Text = Convert.ToString(Settings.Default.DefaultDomain);
|
||||
txtCredentialsPassword.Text = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
|
||||
txtCredentialsDomain.Text = Settings.Default.DefaultDomain;
|
||||
|
||||
if (Settings.Default.ConfirmCloseConnection == (int) ConfirmCloseEnum.Never)
|
||||
{
|
||||
|
||||
@@ -46,9 +46,6 @@ namespace mRemoteNG.UI.Forms
|
||||
private ConnectionTreeWindow ConnectionTreeWindow { get; set; }
|
||||
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
|
||||
|
||||
|
||||
|
||||
|
||||
private frmMain()
|
||||
{
|
||||
_showFullPathInTitle = Settings.Default.ShowCompleteConsPathInTitle;
|
||||
@@ -190,8 +187,9 @@ namespace mRemoteNG.UI.Forms
|
||||
// Create gui config load and save objects
|
||||
var settingsLoader = new SettingsLoader(this);
|
||||
settingsLoader.LoadSettings();
|
||||
|
||||
ApplyLanguage();
|
||||
LoadDefaultConnectionInfo();
|
||||
|
||||
ApplyLanguage();
|
||||
PopulateQuickConnectProtocolMenu();
|
||||
ThemeManager.ThemeChanged += ApplyThemes;
|
||||
ApplyThemes();
|
||||
@@ -224,6 +222,12 @@ namespace mRemoteNG.UI.Forms
|
||||
ConnectionTreeWindow = Windows.TreeForm;
|
||||
}
|
||||
|
||||
private void LoadDefaultConnectionInfo()
|
||||
{
|
||||
DefaultConnectionInfo.Instance.LoadFrom(Settings.Default, a => "ConDefault" + a);
|
||||
DefaultConnectionInheritance.Instance.LoadFrom(Settings.Default, a => "InhDefault" + a);
|
||||
}
|
||||
|
||||
private void ApplyLanguage()
|
||||
{
|
||||
mMenFile.Text = Language.strMenuFile;
|
||||
@@ -453,13 +457,14 @@ namespace mRemoteNG.UI.Forms
|
||||
var extA = (ExternalTool)((ToolStripButton)sender).Tag;
|
||||
|
||||
var selectedTreeNode = Windows.TreeForm.SelectedNode;
|
||||
if (selectedTreeNode.GetTreeNodeType() == TreeNodeType.Connection | selectedTreeNode.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
if (selectedTreeNode != null && selectedTreeNode.GetTreeNodeType() == TreeNodeType.Connection | selectedTreeNode.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
{
|
||||
extA.Start(selectedTreeNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
extA.Start();
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "No connection was selected, external tool may return errors.", true);
|
||||
extA.Start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1071,30 +1076,37 @@ namespace mRemoteNG.UI.Forms
|
||||
var control = FromChildHandle(NativeMethods.WindowFromPoint(MousePosition));
|
||||
if (control != null)
|
||||
{
|
||||
// Let TreeViews and ComboBoxes get focus but don't simulate a mouse event
|
||||
if (control is TreeView || control is ComboBox)
|
||||
{ }
|
||||
else
|
||||
{
|
||||
if (control.CanSelect || control is MenuStrip || control is ToolStrip || control is Crownwood.Magic.Controls.TabControl || control is Crownwood.Magic.Controls.InertButton)
|
||||
{
|
||||
// Simulate a mouse event since one wasn't generated by Windows
|
||||
var clientMousePosition = control.PointToClient(MousePosition);
|
||||
var temp_wLow = clientMousePosition.X;
|
||||
var temp_wHigh = clientMousePosition.Y;
|
||||
NativeMethods.SendMessage(control.Handle, NativeMethods.WM_LBUTTONDOWN, (IntPtr)NativeMethods.MK_LBUTTON, (IntPtr)NativeMethods.MAKELPARAM(ref temp_wLow, ref temp_wHigh));
|
||||
clientMousePosition.X = temp_wLow;
|
||||
clientMousePosition.Y = temp_wHigh;
|
||||
control.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This handles activations from clicks that did not start a size/move operation
|
||||
ActivateConnection();
|
||||
}
|
||||
break;
|
||||
case NativeMethods.WM_WINDOWPOSCHANGED:
|
||||
// Let TreeViews get focus but don't simulate a mouse event
|
||||
if (control is TreeView ||
|
||||
control is ComboBox ||
|
||||
control is TextBox)
|
||||
{
|
||||
control.Focus();
|
||||
}
|
||||
else if (control.CanSelect ||
|
||||
control is MenuStrip ||
|
||||
control is ToolStrip ||
|
||||
control is Crownwood.Magic.Controls.TabControl ||
|
||||
control is Crownwood.Magic.Controls.InertButton)
|
||||
{
|
||||
// Simulate a mouse event since one wasn't generated by Windows
|
||||
var clientMousePosition = control.PointToClient(MousePosition);
|
||||
var temp_wLow = clientMousePosition.X;
|
||||
var temp_wHigh = clientMousePosition.Y;
|
||||
NativeMethods.SendMessage(control.Handle, NativeMethods.WM_LBUTTONDOWN, (IntPtr)NativeMethods.MK_LBUTTON, (IntPtr)NativeMethods.MAKELPARAM(ref temp_wLow, ref temp_wHigh));
|
||||
clientMousePosition.X = temp_wLow;
|
||||
clientMousePosition.Y = temp_wHigh;
|
||||
control.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This handles activations from clicks that did not start a size/move operation
|
||||
ActivateConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NativeMethods.WM_WINDOWPOSCHANGED:
|
||||
// Ignore this message if the window wasn't activated
|
||||
var windowPos = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(NativeMethods.WINDOWPOS));
|
||||
if ((windowPos.flags & NativeMethods.SWP_NOACTIVATE) != 0)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
14
mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
generated
14
mRemoteV1/UI/Window/ConnectionTreeWindow.Designer.cs
generated
@@ -1,5 +1,7 @@
|
||||
|
||||
|
||||
using mRemoteNG.Tree;
|
||||
|
||||
namespace mRemoteNG.UI.Window
|
||||
{
|
||||
public partial class ConnectionTreeWindow : BaseWindow
|
||||
@@ -19,6 +21,9 @@ namespace mRemoteNG.UI.Window
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
mRemoteNG.Tree.TreeNodeCompositeClickHandler treeNodeCompositeClickHandler1 = new mRemoteNG.Tree.TreeNodeCompositeClickHandler();
|
||||
mRemoteNG.Tree.AlwaysConfirmYes alwaysConfirmYes1 = new mRemoteNG.Tree.AlwaysConfirmYes();
|
||||
mRemoteNG.Tree.TreeNodeCompositeClickHandler treeNodeCompositeClickHandler2 = new mRemoteNG.Tree.TreeNodeCompositeClickHandler();
|
||||
this.olvConnections = new mRemoteNG.UI.Controls.ConnectionTree();
|
||||
this.pnlConnections = new System.Windows.Forms.Panel();
|
||||
this.PictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
@@ -44,22 +49,31 @@ namespace mRemoteNG.UI.Window
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.olvConnections.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.olvConnections.CellEditUseWholeCell = false;
|
||||
this.olvConnections.ConnectionTreeModel = new ConnectionTreeModel();
|
||||
this.olvConnections.Cursor = System.Windows.Forms.Cursors.Default;
|
||||
treeNodeCompositeClickHandler1.ClickHandlers = new mRemoteNG.Tree.ITreeNodeClickHandler[0];
|
||||
this.olvConnections.DoubleClickHandler = treeNodeCompositeClickHandler1;
|
||||
this.olvConnections.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||
this.olvConnections.HideSelection = false;
|
||||
this.olvConnections.IsSimpleDragSource = true;
|
||||
this.olvConnections.IsSimpleDropSink = true;
|
||||
this.olvConnections.LabelEdit = true;
|
||||
this.olvConnections.Location = new System.Drawing.Point(0, 0);
|
||||
this.olvConnections.MultiSelect = false;
|
||||
this.olvConnections.Name = "olvConnections";
|
||||
this.olvConnections.NodeDeletionConfirmer = alwaysConfirmYes1;
|
||||
this.olvConnections.PostSetupActions = new mRemoteNG.UI.Controls.IConnectionTreeDelegate[0];
|
||||
this.olvConnections.SelectedBackColor = System.Drawing.SystemColors.Highlight;
|
||||
this.olvConnections.SelectedForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.olvConnections.ShowGroups = false;
|
||||
treeNodeCompositeClickHandler2.ClickHandlers = new mRemoteNG.Tree.ITreeNodeClickHandler[0];
|
||||
this.olvConnections.SingleClickHandler = treeNodeCompositeClickHandler2;
|
||||
this.olvConnections.Size = new System.Drawing.Size(192, 410);
|
||||
this.olvConnections.TabIndex = 20;
|
||||
this.olvConnections.UnfocusedSelectedBackColor = System.Drawing.SystemColors.Highlight;
|
||||
this.olvConnections.UnfocusedSelectedForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.olvConnections.UseCompatibleStateImageBehavior = false;
|
||||
this.olvConnections.UseOverlays = false;
|
||||
this.olvConnections.View = System.Windows.Forms.View.Details;
|
||||
this.olvConnections.VirtualMode = true;
|
||||
//
|
||||
|
||||
@@ -123,10 +123,9 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
private void btnImport_Click(object sender, EventArgs e)
|
||||
{
|
||||
ProtocolType protocol = (ProtocolType)StringToEnum(typeof(ProtocolType), Convert.ToString(cbProtocol.SelectedItem));
|
||||
var protocol = (ProtocolType)StringToEnum(typeof(ProtocolType), Convert.ToString(cbProtocol.SelectedItem));
|
||||
importSelectedHosts(protocol);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -168,8 +167,8 @@ namespace mRemoteNG.UI.Window
|
||||
SwitchButtonText();
|
||||
lvHosts.Items.Clear();
|
||||
|
||||
System.Net.IPAddress ipAddressStart = System.Net.IPAddress.Parse(ipStart.Text);
|
||||
System.Net.IPAddress ipAddressEnd = System.Net.IPAddress.Parse(ipEnd.Text);
|
||||
var ipAddressStart = System.Net.IPAddress.Parse(ipStart.Text);
|
||||
var ipAddressEnd = System.Net.IPAddress.Parse(ipEnd.Text);
|
||||
|
||||
_portScanner = new PortScanner(ipAddressStart, ipAddressEnd, (int) portStart.Value, (int) portEnd.Value);
|
||||
|
||||
@@ -198,9 +197,14 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
prgBar.Maximum = 100;
|
||||
prgBar.Value = 0;
|
||||
|
||||
/* If there are still hosts timing out, we might call PortScannerHostScannedDelegate after the import which will throw exceptions...
|
||||
* Disable the import button until after the scan is complete
|
||||
*/
|
||||
btnImport.Enabled = !_scanning;
|
||||
}
|
||||
|
||||
private static void PortScanner_BeginHostScan(string host)
|
||||
|
||||
private static void PortScanner_BeginHostScan(string host)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Scanning " + host, true);
|
||||
}
|
||||
@@ -210,13 +214,13 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new PortScannerHostScannedDelegate(PortScanner_HostScanned), new object[] {host, scannedCount, totalCount});
|
||||
Invoke(new PortScannerHostScannedDelegate(PortScanner_HostScanned), host, scannedCount, totalCount);
|
||||
return;
|
||||
}
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Host scanned " + host.HostIp, true);
|
||||
|
||||
ListViewItem listViewItem = host.ToListViewItem();
|
||||
var listViewItem = host.ToListViewItem();
|
||||
if (listViewItem != null)
|
||||
{
|
||||
lvHosts.Items.Add(listViewItem);
|
||||
@@ -232,7 +236,7 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new PortScannerScanComplete(PortScanner_ScanComplete), new object[] {hosts});
|
||||
Invoke(new PortScannerScanComplete(PortScanner_ScanComplete), hosts);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -245,6 +249,13 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
private void importSelectedHosts(ProtocolType protocol)
|
||||
{
|
||||
|
||||
if (lvHosts.SelectedItems.Count < 1)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, "importSelectedHosts: Could not import host(s) from port scan context menu. No hosts selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
var hosts = new List<ScanHost>();
|
||||
foreach (ListViewItem item in lvHosts.SelectedItems)
|
||||
{
|
||||
@@ -257,11 +268,21 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
if (hosts.Count < 1)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, "Could not import host(s) from port scan context menu");
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, "importSelectedHosts: Could not import host(s) from port scan context menu", true);
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedTreeNodeAsContainer = Windows.TreeForm.SelectedNode as ContainerInfo ?? Windows.TreeForm.SelectedNode.Parent;
|
||||
ContainerInfo selectedTreeNodeAsContainer;
|
||||
if (Windows.TreeForm.SelectedNode == null)
|
||||
{
|
||||
selectedTreeNodeAsContainer = Windows.TreeForm.ConnectionTree.GetRootConnectionNode();
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "importSelectedHosts: No node selected. Using Root Node.", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedTreeNodeAsContainer = Windows.TreeForm.SelectedNode as ContainerInfo ?? Windows.TreeForm.SelectedNode.Parent;
|
||||
}
|
||||
|
||||
Import.ImportFromPortScan(hosts, protocol, selectedTreeNodeAsContainer);
|
||||
}
|
||||
|
||||
|
||||
@@ -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=<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 >NUL
|
||||
rmdir /s /q Help >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 >NUL
|
||||
set /p buildenv=<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 "&""$(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>
|
||||
|
||||
199
packages/NSubstitute.1.10.0.0/BreakingChanges.txt
vendored
199
packages/NSubstitute.1.10.0.0/BreakingChanges.txt
vendored
@@ -1,199 +0,0 @@
|
||||
================================================================================================
|
||||
1.10.0 Release
|
||||
================================================================================================
|
||||
|
||||
Substitutes will now automatically return an empty `IQueryable<T>` for
|
||||
members that return that type. Tests previously relying on a
|
||||
substitute `IQueryable<T>` will no longer work properly.
|
||||
|
||||
Reason:
|
||||
Code that uses an `IQueryable<T>` can now run using the auto-subbed
|
||||
value without causing null pointer exceptions (see issue #67).
|
||||
|
||||
Fix:
|
||||
Avoid mocking `IQueryable<T>` where possible -- configure members
|
||||
to return a real `IQueryable<T>` instead.
|
||||
If a substitute is required, explicitly configure the call to return
|
||||
a substitute:
|
||||
|
||||
sub.MyQueryable().Returns(Substitute.For<IQueryable<int>>());
|
||||
|
||||
|
||||
================================================================================================
|
||||
1.9.1 Release
|
||||
================================================================================================
|
||||
|
||||
Substitutes set up to throw exception for methods with return type Task<T>
|
||||
cause compilation to fail due to the call being ambiguous (CS0121).
|
||||
"The call is ambiguous between the following methods or properties:
|
||||
.Returns<Task<T>> and .Returns<T>"
|
||||
|
||||
Reason:
|
||||
To make it easier to stub async methods. See issue #189.
|
||||
|
||||
Fix:
|
||||
Specify generic type argument explicitly. If Method() returns string:
|
||||
Old: sub.Method().Returns(x => { throw new Exception() });
|
||||
New: sub.Method().Returns<string>(x => { throw new Exception() });
|
||||
|
||||
================================================================================================
|
||||
1.8.0 Release
|
||||
================================================================================================
|
||||
|
||||
Incorrect use of argument matchers outside of a member call, particularly within a
|
||||
Returns(), will now throw an exception (instead of causing unexpected behaviour
|
||||
in other tests: see https://github.com/nsubstitute/NSubstitute/issues/149).
|
||||
|
||||
Reason:
|
||||
Prevent accidental incorrect use from causing hard-to-find errors in unrelated tests.
|
||||
|
||||
Fix:
|
||||
Do not use argument matchers in Returns() or outside of where an argument is normally used.
|
||||
Correct use: sub.Method(Arg.Any<string>()).Returns("hi")
|
||||
Incorrect use: sub.Method().Returns(Arg.Any<string>())
|
||||
|
||||
================================================================================================
|
||||
1.7.0 Release
|
||||
================================================================================================
|
||||
|
||||
Auto-substitute for pure virtual classes with at least one public static method, which
|
||||
means some methods and properties on substitutes that used to return null by default will now
|
||||
return a new substitute of that type.
|
||||
|
||||
Reason:
|
||||
Keep consistency with the behaviour of other pure virtual classes.
|
||||
|
||||
Fix:
|
||||
Explicitly return null from methods and property getters when required for a test.
|
||||
e.g. sub.Method().Returns(x => null);
|
||||
|
||||
------------------------------------------------------------------------------------------------
|
||||
|
||||
Moved `Received.InOrder` feature from `NSubstitute.Experimental` to main `NSubstitute` namespace.
|
||||
Obsoleted original `NSubstitute.Experimental.Received`.
|
||||
|
||||
This can result in ambiguous reference compiler errors and obsolete member compiler earnings.
|
||||
|
||||
Reason:
|
||||
Promoted experimental Received feature to core library.
|
||||
|
||||
Fix:
|
||||
Import `NSubstitute` namespace instead of `NSubstitute.Experimental`.
|
||||
(If `NSubstitute` is already imported just delete the `using NSubstitute.Experimental;` line from your fixtures.)
|
||||
|
||||
================================================================================================
|
||||
1.5.0 Release
|
||||
================================================================================================
|
||||
|
||||
The base object methods (Equals, GetHashCode and ToString) for substitute objects of classes that
|
||||
extend those methods now return the result of calling the actual implementation of those methods
|
||||
rather than the default value for the return type. This means that places where you relied on
|
||||
.Equals returning false, .ToString returning null and .GetHashCode returning 0 because the actual
|
||||
methods weren't called will now call the actual implementation.
|
||||
|
||||
Reason:
|
||||
Substitute objects of classes that overrode those methods that were used as parameters for
|
||||
setting up return values or checking received calls weren't able to be directly used within the
|
||||
call, e.g. instead of:
|
||||
|
||||
someObject.SomeCall(aSubstitute).Returns(1);
|
||||
|
||||
You previously needed to have:
|
||||
|
||||
someObject.SomeCall(Arg.Is<TypeBeingSubstituted>(a => a == aSubstitute)).Returns(1);
|
||||
|
||||
However, now you can use the former, which is much more terse and consistent with the way other
|
||||
Returns or Received calls work.
|
||||
|
||||
This means that substitute objects will now always work like .NET objects rather than being
|
||||
inconsistent when the class being substituted overrode any of those base object methods.
|
||||
|
||||
Fix:
|
||||
There is no workaround to change the behaviour of .Equals, .GetHashCode or .ToString. If you have
|
||||
a use case to change the behaviour of these methods please lodge an issue at the NSubstitute
|
||||
Github site.
|
||||
|
||||
------------------------------------------------------------------------------------------------
|
||||
|
||||
In rare cases the new `Returns()` and `ReturnsForAnyArgs()` overloads can cause compilation to fail due to the call being ambiguous (CS0121).
|
||||
|
||||
Reason:
|
||||
The new overloads allow a sequence of callbacks to be used for return values. A common example is return several values, then throwing an exception.
|
||||
|
||||
Fix:
|
||||
Remove the ambiguity by explicitly casting the arguments types or by using lambda syntax.
|
||||
e.g. sub.Call().Returns(x => null, x => null);
|
||||
|
||||
================================================================================================
|
||||
1.4.0 Release
|
||||
================================================================================================
|
||||
|
||||
Auto-substitute from substitutes of `Func` delegates (following the same rules as auto-subbing
|
||||
for methods and properties). So the delegate returned from `Substitute.For<Func<IFoo>>()` will
|
||||
return a substitute of `IFoo`. This means some substitutes for delegates that used to return
|
||||
null will now return a new substitute.
|
||||
|
||||
Reason:
|
||||
Reduced setup when substituting for `Func` delegates, and consistency with behaviour for
|
||||
properties and methods.
|
||||
|
||||
Fix:
|
||||
Explicitly return null from substitute delegates when required for a test.
|
||||
e.g. subFunc().Returns(x => null);
|
||||
|
||||
|
||||
================================================================================================
|
||||
1.2.0 Release
|
||||
================================================================================================
|
||||
|
||||
Auto-substitute for pure virtual classes (in addition to interfaces and delegate types), which
|
||||
means some methods and properties on substitutes that used to return null by default will now
|
||||
return a new substitute of that type.
|
||||
|
||||
Reason:
|
||||
Cut down the code required to configure substitute members that return interface-like types
|
||||
(e.g. ASP.NET web abstractions like HttpContextBase) which are safe to create and proxy.
|
||||
|
||||
Safe classes are those with all their public methods and properties defined as virtual or
|
||||
abstract, and containing a default, parameterless constructor defined as public or protected.
|
||||
|
||||
Fix:
|
||||
Explicitly return null from methods and property getters when required for a test.
|
||||
e.g. sub.Method().Returns(x => null);
|
||||
|
||||
|
||||
================================================================================================
|
||||
0.9.5 Release
|
||||
================================================================================================
|
||||
|
||||
Raise.Event<TEventArgs>(...) methods renamed to Raise.EventWith<TEventArgs()
|
||||
|
||||
Reason:
|
||||
The Raise.Event<TEventArgs>() signature would often conflict with the
|
||||
Raise.Event<THandler>() method which is used to raise all types of events.
|
||||
|
||||
Raise.Event<THandler>() will now always work for any event type, while
|
||||
Raise.EventWith<TEventArgs>() can be used as a shortcut to raise
|
||||
EventHandler-style events with a particular argument.
|
||||
|
||||
Fix:
|
||||
Replace Raise.Event<TEventArgs>() calls with equivalent Raise.EventWith<TEventArgs>() call.
|
||||
|
||||
------------------------------------------------------------------------------------------------
|
||||
Raise.Action() methods removed
|
||||
|
||||
Reason:
|
||||
The Raise.Event<THandler>() method can be used to raise all delegate events, including Actions.
|
||||
Raise.Action() was removed so there is a consistent way of raising all delegate events.
|
||||
|
||||
Fix:
|
||||
- Replace Raise.Action() calls with Raise.Event<Action>().
|
||||
- Replace Raise.Action<T>(T arg) calls with Raise.Event<Action<T>>(arg).
|
||||
- Replace Raise.Action<T1,T2>(T1 x, T2 y) calls with Raise.Event<Action<T1,T2>>(x, y).
|
||||
|
||||
|
||||
================================================================================================
|
||||
0.9.0 Release
|
||||
================================================================================================
|
||||
|
||||
No breaking changes.
|
||||
151
packages/NSubstitute.1.10.0.0/CHANGELOG.txt
vendored
151
packages/NSubstitute.1.10.0.0/CHANGELOG.txt
vendored
@@ -1,151 +0,0 @@
|
||||
### 1.10.0 (March 2016)
|
||||
* [NEW] Callbacks builder for more control over When..Do callbacks. Thanks to bartoszgolek. (#202, #200)
|
||||
* [NEW] Auto-substitute for IQueryable<T>. Thanks to emragins. (#67)
|
||||
* [FIX] Fix bug when showing params arguments for value types (#214)
|
||||
* [FIX] Fix bug when showing params arguments for Received.InOrder calls (#211)
|
||||
|
||||
### 1.9.2 (October 2015)
|
||||
* [UPDATE] Mark Exceptions as [Serializable]. Thanks to David Mann. (#201)
|
||||
* [FIX] Fix bug with concurrently creating delegate substitutes. Thanks to Alexandr Nikitin. (#205)
|
||||
|
||||
### 1.9.1 (October 2015)
|
||||
* [FIX] Fix bug introduced in 1.9.0 that made checking a call was Received() clear previously stubbed values for that call.
|
||||
|
||||
### 1.9.0 (October 2015)
|
||||
* [NEW] Allow awaiting of async methods with Received()/DidNotReceive(). Thanks to Marcio Rinaldi for this contribution. (#190, #191)
|
||||
* [NEW] Task-specific Returns methods to make it easier to stub async methods. Thanks to Antony Koch for implementing this, and thanks to Marius Gundersen and Alexandr Nikitin for the suggestion and discussion regarding the change. (#189) (Also thanks to Jake Ginnivan who tried adding this back in #91, but I didn't merge that part of the PR in. Sorry!)
|
||||
* [NEW] ReturnsForAll<T> extension method. Thanks to Mike Hanson for this contribution. (#198, #196)
|
||||
|
||||
### 1.8.2 (May 2015)
|
||||
* [NEW] Convenience .ReturnsNull() extensions in NSubstitute.ReturnsExtensions. Thanks to Michal Wereda for this contribution. (#181)
|
||||
* [NEW] CallInfo.ArgAt<T>(int) added to match argument at a given position and cast to the required type. Thanks to @jotabe-net for this contribution. (#175)
|
||||
* [NEW] Convenience Throws() extensions in NSubstitute.ExceptionExtensions (sub.MyCall().Throws(ex)). Thanks to Michal Wereda for this contribution. Thanks also to Geir Sagberg for helpful suggestions relating to this feature. (#172)
|
||||
|
||||
### 1.8.1 (December 2014)
|
||||
* [FIX] Fix for methods returning multidimensional arrays. Thanks to Alexandr Nikitin. (#170)
|
||||
|
||||
### 1.8.0 (November 2014)
|
||||
* [NEW] Convenience methods for throwing exceptions with When-Do. Thanks to Geir Sagberg for this contribution.
|
||||
* [FIX] Throw exception when arg matcher used within Returns. (#149)
|
||||
|
||||
### 1.7.2 (March 2014)
|
||||
* [FIX] Basic support for types that return dynamic. Thanks to Alexandr Nikitin. (#75)
|
||||
* [NEW] Auto-subbing for observables. Thanks to Paul Betts.
|
||||
|
||||
### 1.7.1 (January 2014)
|
||||
* [FIX] Ambiguous arg exception with out/ref parameters. Thanks to Alexandr Nikitin. (#129)
|
||||
|
||||
### 1.7.0 (January 2014)
|
||||
* [NEW] Partial subs (Substitute.ForPartsOf<T>()). Thanks to Alexandr Nikitin for tonnes of hard work on this feature (and for putting up with a vacillating project owner :)).
|
||||
* [UPDATE] Received.InOrder moved out of Experimental namespace.
|
||||
* [FIX] Argument matching with optional parameters. Thanks to Peter Wiles. (#111)
|
||||
* [FIX] Argument matching with out/ref. Thanks to Kevin Bosman. (#111)
|
||||
* [FIX] The default return value for any call that returns a concrete type that is purely virtual, but also has at least one public static method in it will be a substitute rather than null. Thanks to Robert Moore (@robdmoore) for this contribution. (#118)
|
||||
|
||||
### 1.6.1 (June 2013)
|
||||
* [FIX] Detect and throw on type mismatches in Returns() caused by Returns(ConfigureOtherSub()).
|
||||
* [FIX] Support raising exceptions that do not implement a serialisation constructor (#110). Thanks to Alexandr Nikitin for this contribution.
|
||||
|
||||
### 1.6.0 (April 2013)
|
||||
* [NEW] .AndDoes() method for chaining a callback after a Returns(). (#98)
|
||||
* [FIX] Handling calls with params argument of value types, thanks to Eric Winkler.
|
||||
* [FIX] Can now substitute for interfaces implementing System.Windows.IDataObject, thanks to Johan Appelgren.
|
||||
* [UPDATE] Improved XML doc comments, thanks to David Gardiner.
|
||||
|
||||
### 1.5.0 (January 2013)
|
||||
* [EXPERIMENTAL] Asserting ordered call sequences
|
||||
* [FIX] Arg.Invoke with four arguments now passes fourth arg correctly (#88). Thanks to Ville Salonen (@VilleSalonen) for finding and patching this.
|
||||
* [FIX] Substitute objects now use actual implementation for base object methods (Equals, GetHashCode, ToString). Thanks to Robert Moore (@robdmoore) for this contribution. (#77)
|
||||
* [NEW] Auto-substitute for Task/Task<T>. Task<T> will use substitute rules that T would use. Thanks to Jake Ginnivan (@JakeGinnivan) for this contribution.
|
||||
* [NEW] Match derived types for generic calls (#97). Thanks to Iain Ballard for this contribution.
|
||||
* [NEW] Returns now supports passing multiple callbacks, which makes it easier to combine stubbing multiple return values followed by throwing an exception (#99). Thanks to Alexandr Nikitin for this contribution.
|
||||
|
||||
### 1.4.3 (August 2012)
|
||||
* [FIX] Updated to Castle.Core 3.1.0 to fix an issue proxying generic methods with a struct constraint (#83).
|
||||
|
||||
### 1.4.2 (July 2012)
|
||||
* [FIX] Issue using NET40 build on Mono (due to NET45 build tools incompatibility)
|
||||
|
||||
### 1.4.1 (June 2012)
|
||||
* [FIX] Fix matching Nullable<T> arguments when arg value is null. Thanks to Magnus Olstad Hansen (@maggedotno) for this contribution. (#78)
|
||||
* [UPDATE] Updated to Castle.Core 3.0.0.
|
||||
|
||||
### 1.4.0 (May 2012)
|
||||
* [NEW] [BREAKING] Auto-substitute for types returned from substitutes of delegates/Funcs (follows same auto-substitute rules as for methods and properties). Thanks to Sauli T<>hk<68>p<EFBFBD><70> for implementing this feature. (#52)
|
||||
* [NEW] Show details of params arguments when displaying received calls. Thanks to Sauli T<>hk<68>p<EFBFBD><70> for implementing this feature. (#65)
|
||||
* [FIX] Race condition between checking received calls and building the exception could cause nonsensical exception messages like "Expected 5, actually received 5" when called concurrently. (#64)
|
||||
|
||||
### 1.3.0 (Nov 2011)
|
||||
* [NEW] Support for Received(times) to assert a call was received a certain number of times. Thanks to Abi Bellamkonda for this contribution. (#63)
|
||||
* [FIX] Improved support for calling substitutes from multiple threads. (#62)
|
||||
|
||||
### 1.2.1 (Oct 2011)
|
||||
* [FIX] Some combinations of Arg.Do and Returns() caused incorrect values to be returned. (#59)
|
||||
* [UPDATE] WCF ServiceContractAttribute no longer applied to proxies. (#60)
|
||||
* [FIX] Passing null could cause argument actions to fail. (#61)
|
||||
* [FIX] Calls to virtual methods from constructors of classes being substituted for are no longer recorded, to prevent non-obvious behaviour when calling Returns() on an auto-substituted value. (#57)
|
||||
|
||||
### 1.2.0 (Sep 2011)
|
||||
* [NEW] Arg.Do() syntax for capturing arguments passed to a method and performing some action with them whenever the method is called.
|
||||
* [NEW] Arg.Invoke() syntax for invoking callbacks passed as arguments to a method whenever the method is called.
|
||||
* [NEW] Basic support for setting out/ref parameters.
|
||||
* [FIX] Property behaviour for indexed properties (Issue #53)
|
||||
* [UPDATE] [BREAKING] Auto-substitute for pure virtual classes, including common ASP.NET web abstractions. Use .Returns(x=>null) to explicitly return null from these members if required. Thanks to Tatham Oddie for original idea and patch, and Krzysztof Kozmic for suggesting and defining which classes would be safe to automatically proxy.
|
||||
* [UPDATE] Changed layout of package for eventual support for multiple framework targets.
|
||||
* [FIX] Failure to match calls with ref arguments using ReceivedWithAnyArgs().
|
||||
* [FIX] Incorrect ambiguous args exception when supplying value type arg specs for object arguments.
|
||||
|
||||
### 1.1.0 (May 2011)
|
||||
* [UPDATE] Updated to Castle.Core 2.5.3.
|
||||
* [FIX] Fixed bug when raising a delegate event with a null argument.
|
||||
* [FIX] CallInfo.Arg<T>() now works more reliably, including for null arguments.
|
||||
* [FIX] Better exception when accidentally calling substitute extension method with a null reference (e.g. foo.Received().Call() when foo is null)
|
||||
* [UPDATE] Exceptions thrown in custom argument matchers (Arg.Is<T>(x => ...)) will now silently fail to match the argument, rather than allowing exceptions to bubble up.
|
||||
* [NEW] Support for test fixtures run in parallel.
|
||||
|
||||
### 1.0.0 (Dec 2010)
|
||||
* [FIX] Using Returns(null) for value types throws, rather than returning default(T).
|
||||
|
||||
0.9.5 Release Candidate
|
||||
* [FIX] Fixed bug when trying to return null from a call to a substitute.
|
||||
* [FIX] Equals() for class substitutes fixed by not intercepting Object methods Equals(), ToString() and GetHashCode().
|
||||
* [NEW] Raise.Event<THandler>() methods to raise any type of event, including delegates.
|
||||
* [BREAKING] Raise.Action() methods removed. Use Raise.Event<THandler>() (e.g. Raise.Event<Action>>()).
|
||||
* [BREAKING] Renamed Raise.Event<TEventArgs>() methods to Raise.EventWith<TEventArgs>().
|
||||
* [UPDATE] Arg matchers can be specified using more specific, compatible type (Arg.Is<string>(..) for arg of type object).
|
||||
* [NEW] NSubstitute website and documentation http://nsubstitute.github.com
|
||||
* [FIX] Formating for argument matchers that take predicate functions.
|
||||
* [FIX] Match single argument matcher passed to params arg (#34)
|
||||
* [FIX] Detect ambiguous arg matchers in additional case (#31)
|
||||
* [FIX] Can modify event handler subscriptions from within event callback
|
||||
* [UPDATE] Update to Castle.Core 2.5.2
|
||||
* [FIX] Can substitute for SynchronizationContext in .NET4 (fixed in Castle.Core)
|
||||
* [NEW] NSubstitute available as NuPack package
|
||||
|
||||
### 0.9.0 Beta 1
|
||||
* [FIX] Now handles argument specifiers used for params arguments correctly
|
||||
* [UPDATE] Updated to Castle.Core 2.5 final.
|
||||
|
||||
### 0.1.3 alpha 4
|
||||
* [NEW] Support auto/recursive substituting for members that return interfaces or delegates.
|
||||
* [NEW] Support auto substituting for members that return arrays and strings (return empty values rather than null).
|
||||
* [NEW] Raise.Event<TEventArgs>() will now attempt to construct arguments with default ctors, so in most cases they will not need to be explictly provided.
|
||||
* [UPDATE] Added support for raising events with custom delegate types.
|
||||
* [UPDATE] Formatting for event subscription and unsubscription calls in call received/not received exceptions.
|
||||
* [UPDATE] Updated to pre-release build of Castle.Core 2.5 to get dynamic proxy to support modopts.
|
||||
* [FIX] Throw correct exception when raising an event and event handler throws. (Fix by Rodrigo Perera)
|
||||
* [FIX] Record call as received when it throws an exception from the When..Do callback.
|
||||
|
||||
### 0.1.2 alpha 3
|
||||
* [NEW] Marked non-matching parameters in the actual calls listed for CallNotReceivedException messages.
|
||||
* [NEW] Added WhenForAnyArgs..Do syntax for callbacks.
|
||||
* [UPDATE] Updated arg matching to be smarter when matchers are not used for all args.
|
||||
* [FIX] Fixed bug when substituting for delegates with multiple parameters.
|
||||
* [FIX] Removed redundant cast operator which sometimes caused the compiler trouble in resolving Raise.Event().
|
||||
|
||||
### 0.1.1 alpha 2
|
||||
* [NEW] Added ReturnsForAnyArgs() extension methods
|
||||
* [FIX] Compiled for Any CPU to run on x64 platforms
|
||||
|
||||
### 0.1.0 alpha
|
||||
* Initial release
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user