mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-21 16:38:38 +08:00
Compare commits
312 Commits
v1.75Beta2
...
v1.75.7010
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
be5c66bd93 | ||
|
|
5347e5a3aa | ||
|
|
9b22254b6c | ||
|
|
6a67e0ea8b | ||
|
|
7b118995ea | ||
|
|
35b4564644 | ||
|
|
30df947365 | ||
|
|
b1ec975612 | ||
|
|
1034e434c4 | ||
|
|
f419bff545 | ||
|
|
69eec0135e | ||
|
|
2849baf857 | ||
|
|
768fdcd0e4 | ||
|
|
9b38308ad1 | ||
|
|
afcdf96e5c | ||
|
|
3e40b08525 | ||
|
|
237cf037be | ||
|
|
2445c74638 | ||
|
|
6a69ed48a9 | ||
|
|
217693937f | ||
|
|
22300577cf | ||
|
|
6a07f4e731 | ||
|
|
63ace60dcc | ||
|
|
601951582d | ||
|
|
9250dde5b0 | ||
|
|
29ca72d8ca | ||
|
|
87c89a0de5 | ||
|
|
73f72e39d3 | ||
|
|
e00ba62606 | ||
|
|
48d53cecce | ||
|
|
e0fd81e938 | ||
|
|
04f6f4f9cf | ||
|
|
25d1e0a74d | ||
|
|
cbd9d16e4c | ||
|
|
cb708b3217 | ||
|
|
4e5a22a7e8 | ||
|
|
3722db93c6 | ||
|
|
b43331dc27 | ||
|
|
80c6ce81e1 | ||
|
|
1a776359c4 | ||
|
|
113e4035e5 | ||
|
|
a03095ab8e | ||
|
|
d03f830622 | ||
|
|
9b42dc9f10 | ||
|
|
fd7adf3c64 | ||
|
|
d0b7e72f15 | ||
|
|
5a61c6b7df | ||
|
|
c897eae04e | ||
|
|
c33095cd0e | ||
|
|
05d8b7983a | ||
|
|
166d9f7133 | ||
|
|
2ce31f35cc | ||
|
|
ce5d0cefe3 | ||
|
|
6cc668fe83 | ||
|
|
ac0aa8daf4 | ||
|
|
16b094be44 | ||
|
|
b3e6fd7b96 | ||
|
|
893d5d92f3 | ||
|
|
77add0b39d | ||
|
|
b4f8ab0a49 | ||
|
|
1d46c44c21 | ||
|
|
12da35f875 | ||
|
|
8970a15d4e | ||
|
|
82217478d9 | ||
|
|
4c792308bb | ||
|
|
978d94a2cd | ||
|
|
b195d89b76 | ||
|
|
875888a341 | ||
|
|
6631a13d20 | ||
|
|
28728fe29f | ||
|
|
aa954cbea9 | ||
|
|
dae339f494 | ||
|
|
5bcb59f876 | ||
|
|
9132592fd7 | ||
|
|
ca592fac77 | ||
|
|
ea657824c2 | ||
|
|
99e7072e27 | ||
|
|
ad32f4a0a3 | ||
|
|
b9cdd0996d | ||
|
|
e92a76f95b | ||
|
|
10d152342f | ||
|
|
7e4b0635b2 | ||
|
|
eec17f10d5 | ||
|
|
ac9d5dfa95 | ||
|
|
4c2b3738c2 | ||
|
|
6f29183b45 | ||
|
|
dd65c9c588 | ||
|
|
cb8bb05627 | ||
|
|
256f6d8fdd | ||
|
|
a88fdddecb | ||
|
|
fd5e3e24df | ||
|
|
244d27427d | ||
|
|
55c42a3cca | ||
|
|
3c9cfbdf92 | ||
|
|
46dd58d26e | ||
|
|
051dd2e567 | ||
|
|
17ccf40082 | ||
|
|
0f2b61694d | ||
|
|
0aed66df47 | ||
|
|
94a6e9a886 | ||
|
|
355f48b6ba | ||
|
|
d1a6526c22 | ||
|
|
975a308647 | ||
|
|
5138eaeb68 | ||
|
|
45dfaa1b21 | ||
|
|
715f92f3d5 | ||
|
|
8d5a765040 | ||
|
|
34fa6b158b | ||
|
|
78c1f6b8e3 | ||
|
|
adccb91106 | ||
|
|
1e213dfff7 | ||
|
|
d469fa1d40 | ||
|
|
737db469ba | ||
|
|
a44a33d508 | ||
|
|
a518d41c78 | ||
|
|
d5360c6568 | ||
|
|
d468107311 | ||
|
|
3f65e1bfa0 | ||
|
|
a22758f5cd | ||
|
|
88b5b9d1e7 | ||
|
|
e38f7c880e | ||
|
|
6367b58994 | ||
|
|
5a54b5ee64 | ||
|
|
002e41f418 | ||
|
|
f7787c748a | ||
|
|
f9b18b45a4 | ||
|
|
8966f44272 | ||
|
|
3dbcbae61f | ||
|
|
24508abe7a | ||
|
|
27f8f2542e | ||
|
|
44ee3ceec8 | ||
|
|
b08112aec0 | ||
|
|
9d2bbda2b9 | ||
|
|
6eff685b18 | ||
|
|
2d08146de8 | ||
|
|
f131420a44 | ||
|
|
245ea5463e |
184
CHANGELOG.TXT
184
CHANGELOG.TXT
@@ -1,3 +1,177 @@
|
||||
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:
|
||||
----------------
|
||||
#437: Modify version numbering scheme
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#422: Uncaught exception when clicking in connection tree whitespace
|
||||
#312: Resolved KeePass auto-type issue
|
||||
#427: Export does not respect filtering user/password/domain
|
||||
|
||||
|
||||
1.75 (2017-03-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
File hash check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
Exception will be: "MD5 Hashes didn't match!" for 1.75 Beta 1 - 1.75 RC1
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
#344 - Use SHA512 File Hashes to validate downloads (in the update mechanism & posted to the Downloads page)
|
||||
|
||||
|
||||
1.75 RC1 (2017-01-27):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
Added Release Channels to the update check functionality allowing users to select one of 3 release channels for updates: Stable, Beta, Dev
|
||||
#360: Help -> About, Version # is now selectable/copyable
|
||||
#221: RDP: Optional disconnect after X number of minutes of inactivity
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#369: Reset Layout Option Does Not Reset Notification Pane
|
||||
#362: Invalid cast exception when using the Notification Area Icon minimize/restore
|
||||
#334: Quick Connect displays warning when clicking on a folder
|
||||
#325: When using a connection with an external app, results in opening the same external app continuously
|
||||
#311: Import from Active Directory does not use machine's domain by default
|
||||
#258: Rename Tab dialog - populate original name in dialog (1.72 functionality)
|
||||
#211, #267: Recursive AD Import wasn't fully functional
|
||||
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
The usual general code clean up and refactoring
|
||||
#325: Code clean up and additional logging for External Tools based connections
|
||||
#298: Code clean up and additional logging around application startup
|
||||
#291, #236: External Tools code clean up and additional logging
|
||||
|
||||
|
||||
|
||||
1.75 Beta 3 (2016-12-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#289: Install fails during update process (only affects v1.75 beta 1 - v1.75 beta 2)
|
||||
|
||||
|
||||
1.75 Beta 2 (2016-12-01):
|
||||
|
||||
Features/Enhancements:
|
||||
@@ -10,7 +184,7 @@ Fixes:
|
||||
------
|
||||
#254: Component check window position issues and uncaught exception
|
||||
#260: Crash when attempting to load fully encrypted confCons v2.5
|
||||
#261: Double clicking folder in treeview doesnt expand it in 1.75 beta1
|
||||
#261: Double clicking folder in treeview doesn't expand it in 1.75 beta1
|
||||
#271: Install package is not using the last installation path
|
||||
#278: Silent installs not detecting prerequisites
|
||||
|
||||
@@ -54,7 +228,7 @@ Fixes:
|
||||
MR-965, MR-871, MR-629: Error 264 on RDP Connect attempt - Added timeout value to Tools -> Options -> Connections
|
||||
MR-946: Remove old/insecure SharpSSH and related components. Replace with SSH.NET for File Transfer Functionality
|
||||
MR-896: Added prerequisite installer check for KB2574819. Prevents "Class not registered" errors when opening RDP connections.
|
||||
PR-130: Fix Scan button width to fit russian translation
|
||||
PR-130: Fix Scan button width to fit Russian translation
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +236,7 @@ PR-130: Fix Scan button width to fit russian translation
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
Updated GeckoFx pacakge
|
||||
Updated GeckoFx package
|
||||
Updated DockPanelSuite library to 2.10 Final
|
||||
Japanese translation updated
|
||||
MR-942: Refactored code relating to loading the connections file
|
||||
@@ -137,7 +311,7 @@ Port Scan is now Asynchronous (and is significantly faster)
|
||||
Fixes:
|
||||
------
|
||||
MR-874: Added work-around to installer to ignore installation prerequisites
|
||||
MR-884: Slow startup in some scnearios checking authenticode certificate
|
||||
MR-884: Slow startup in some scenarios checking authenticode certificate
|
||||
MR-872: Crash in External Tools when arguments aren't quoted
|
||||
MR-854: crashes when right clicking on connection tab
|
||||
MR-852: Option "Allow only a single instance of the application" non-functional
|
||||
@@ -278,7 +452,7 @@ Fixed issue MR-398 - Full Screen mode doesn't correctly make use of available sp
|
||||
Fixed issue MR-402 - scrollbar touch moves putty window
|
||||
Fixed issue MR-406 - Items disappear from External Tools toolbar when accessing External Tools panel
|
||||
Fixed issue MR-410 - Unhandled exception when clicking New button under Theme
|
||||
Fixed issue MR-413 - Can't use aplication
|
||||
Fixed issue MR-413 - Can't use application
|
||||
Fixed new connections having a globe icon.
|
||||
Fixed the category names in the themes tab of the options dialog on Windows XP not showing correctly.
|
||||
Fixed PuTTY saved sessions with spaces or special characters not being listed.
|
||||
|
||||
@@ -8,7 +8,12 @@ Sean Kaim (github.com/kmscode)
|
||||
Thanks for the awesome new website!
|
||||
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
|
||||
@@ -96,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>
|
||||
|
||||
6
Jenkinsfile
vendored
6
Jenkinsfile
vendored
@@ -5,11 +5,7 @@ node('windows') {
|
||||
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
|
||||
|
||||
stage 'Checkout Branch'
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: scm.branches,
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
checkout scm
|
||||
|
||||
stage 'Restore NuGet Packages'
|
||||
def nugetPath = "C:\\nuget.exe"
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
README.MD
28
README.MD
@@ -1,16 +1,20 @@
|
||||
# Welcome to the mRemoteNG project!
|
||||
|
||||
[](https://twitter.com/intent/follow?screen_name=mRemoteNG)
|
||||
|
||||
|
||||
[](https://gitter.im/mRemoteNG/PublicChat)
|
||||
|
||||
[](https://www.paypal.me/DavidSparer)
|
||||
|
||||
[](http://ec2-52-39-111-114.us-west-2.compute.amazonaws.com:8080/job/mRemoteNG/job/mRemoteNG/job/develop/)
|
||||
[](https://waffle.io/mRemoteNG/mRemoteNG)
|
||||
[](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74)
|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/529)
|
||||
|
||||
[](https://waffle.io/mRemoteNG/mRemoteNG)
|
||||
|
||||
| Update Channel | Build Status | Downloads |
|
||||
| ---------------|--------------|-----------|
|
||||
| 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/) | - |
|
||||
|
||||
|
||||
|
||||
mRemoteNG is the next generation of mRemote, a full-featured, multi-tab remote connections manager.
|
||||
|
||||
@@ -22,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.
|
||||
@@ -36,8 +40,8 @@ https://support.microsoft.com/en-us/kb/2923545
|
||||
|
||||
Windows 8+ support RDP version 8+ out of the box.
|
||||
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connection successfully to a Windows 2003 host (for example).
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connect successfully to a Windows 2003 host (for example).
|
||||
|
||||
|
||||
|
||||
[](https://www.jetbrains.com/resharper/)
|
||||
[](https://www.jetbrains.com/resharper/)
|
||||
|
||||
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,41 +1,109 @@
|
||||
#Requires -Version 4.0
|
||||
param (
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TagName,
|
||||
|
||||
$tag = Read-Host -Prompt 'Tag name'
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet("Stable","Beta","Development")]
|
||||
$UpdateChannel
|
||||
)
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
|
||||
Write-Host PORTABLE
|
||||
Write-Host --------
|
||||
$file = gci ..\Release\*.zip | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".zip")
|
||||
Write-Host Version: $version
|
||||
function New-MsiUpdateFileContent {
|
||||
param (
|
||||
[System.IO.FileInfo]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$MsiFile,
|
||||
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
[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 }
|
||||
|
||||
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $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
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
|
||||
Write-Host MSI
|
||||
Write-Host ---
|
||||
$file = gci ..\Release\*.msi | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
function New-ZipUpdateFileContent {
|
||||
param (
|
||||
[System.IO.FileInfo]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$ZipFile,
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".msi")
|
||||
Write-Host Version: $version
|
||||
[string]
|
||||
[Parameter(Mandatory=$true)]
|
||||
$TagName
|
||||
)
|
||||
|
||||
$version = $ZipFile.BaseName -replace "[a-zA-Z-]*"
|
||||
$hash = Get-FileHash -Algorithm SHA512 $ZipFile | % { $_.Hash }
|
||||
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
$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
|
||||
}
|
||||
|
||||
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
|
||||
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
|
||||
|
||||
# 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"
|
||||
|
||||
|
||||
# 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 ""
|
||||
84
mRemoteNGTests/App/UpdaterTests.cs
Normal file
84
mRemoteNGTests/App/UpdaterTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNGTests.Properties;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.App
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdaterTests
|
||||
{
|
||||
[Test]
|
||||
public void UpdateStableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateStablePortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,14 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public class XmlConnectionNodeSerializerTests
|
||||
{
|
||||
private XmlConnectionNodeSerializer _connectionNodeSerializer;
|
||||
private ICryptographyProvider _cryptographyProvider;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(
|
||||
BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString());
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), new SaveFilter());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -48,8 +49,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void AttributesNotSerializedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
|
||||
{
|
||||
var saveFilter = new SaveFilter(true);
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
|
||||
Assert.That(targetAttribute?.Value, Is.EqualTo(string.Empty));
|
||||
@@ -59,8 +59,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void InheritanceNotSerialiedWhenFiltered(string attributeName, ConnectionInfo connectionInfo)
|
||||
{
|
||||
var saveFilter = new SaveFilter(true);
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(cryptoProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
_connectionNodeSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, "myPassword1".ConvertToSecureString(), saveFilter);
|
||||
var returnVal = _connectionNodeSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
var targetAttribute = returnVal.Attribute(XName.Get(attributeName));
|
||||
Assert.That(targetAttribute?.Value, Is.EqualTo(false.ToString()));
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void Setup()
|
||||
{
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var saveFilter = new SaveFilter();
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, saveFilter);
|
||||
_connectionTreeModel = SetupConnectionTreeModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
{
|
||||
var connectionTreeModel = SetupConnectionTreeModel();
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider).CompileDocument(connectionTreeModel, false, false);
|
||||
var saveFilter = new SaveFilter();
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, saveFilter).CompileDocument(connectionTreeModel, false, false);
|
||||
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
@@ -45,6 +47,27 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
Assert.That(connectionNode, Is.Not.Null);
|
||||
}
|
||||
|
||||
[TestCase("Username", "")]
|
||||
[TestCase("Domain", "")]
|
||||
[TestCase("Password", "")]
|
||||
[TestCase("InheritAutomaticResize", "False")]
|
||||
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
|
||||
{
|
||||
_serializer.SaveFilter = new SaveFilter(true);
|
||||
var connectionInfo = new ConnectionInfo
|
||||
{
|
||||
Name = "myConnection",
|
||||
Username = "somefilteredstuff",
|
||||
Domain = "somefilteredstuff",
|
||||
Password = "somefilteredstuff",
|
||||
Inheritance = {AutomaticResize = true}
|
||||
};
|
||||
var serializedConnections = _serializer.Serialize(connectionInfo);
|
||||
var xdoc = XDocument.Parse(serializedConnections);
|
||||
var attributeValue = xdoc.Root?.Element("Node")?.Attribute(attributeName)?.Value;
|
||||
Assert.That(attributeValue, Is.EqualTo(expectedValue));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel SetupConnectionTreeModel()
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
@@ -30,5 +31,43 @@ namespace mRemoteNGTests.Connection
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Domain, Is.EqualTo(_testDomain));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveEnumValuesToString()
|
||||
{
|
||||
const ProtocolType targetProtocol = ProtocolType.RAW;
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.Protocol = targetProtocol;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Protocol, Is.EqualTo(targetProtocol.ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveIntegerValuesToString()
|
||||
{
|
||||
const int targetValue = 123;
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.RDPMinutesToIdleTimeout = targetValue;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.RDPMinutesToIdleTimeout, Is.EqualTo(targetValue.ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSaveStringValuesToString()
|
||||
{
|
||||
const string targetName = "hello";
|
||||
var saveTarget = new AllStringPropertySaveTarget();
|
||||
DefaultConnectionInfo.Instance.Username = targetName;
|
||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||
Assert.That(saveTarget.Username, Is.EqualTo(targetName));
|
||||
}
|
||||
|
||||
|
||||
private class AllStringPropertySaveTarget
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Protocol { get; set; }
|
||||
public string RDPMinutesToIdleTimeout { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
77
mRemoteNGTests/Properties/Resources.Designer.cs
generated
77
mRemoteNGTests/Properties/Resources.Designer.cs
generated
@@ -60,6 +60,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string beta_update {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string beta_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" Protected="95syzRuZ4mRxpNkZQzoyX8SDpQXLyMq3GncO8o4SyTBoYvn3TAWgn05ZEU2DrjkM" ConfVersion="2.5">
|
||||
@@ -142,6 +168,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string dev_update {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string dev_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-16"?>
|
||||
///<!-- ****************************************************************-->
|
||||
@@ -276,5 +328,30 @@ namespace mRemoteNGTests.Properties {
|
||||
return ResourceManager.GetString("test_remotedesktopconnection_rdp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.72.5065.32737
|
||||
///dURL: http://downloads.mremoteng.org/mRemoteNG-Installer-1.72.exe
|
||||
///clURL: http://update.mremoteng.org/changes-1.72.txt
|
||||
///CertificateThumbprint: 1cbd910dbd6e77f26506e7f600736972f700673f
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string update {
|
||||
get {
|
||||
return ResourceManager.GetString("update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,12 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="beta_update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\beta-update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="beta_update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\beta-update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="confCons_v2_5" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_5.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
@@ -142,6 +148,12 @@
|
||||
<data name="confCons_v2_6_passwordis_Password_fullencryption" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_6_passwordis_Password_fullencryption.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="dev_update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\dev-update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="dev_update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\dev-update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="test_puttyConnectionManager_database" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\test_puttyConnectionManager_database.dat;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
@@ -163,4 +175,10 @@
|
||||
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
<data name="update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
</root>
|
||||
5
mRemoteNGTests/Resources/beta-update-portable.txt
Normal file
5
mRemoteNGTests/Resources/beta-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/beta-update.txt
Normal file
5
mRemoteNGTests/Resources/beta-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/dev-update-portable.txt
Normal file
5
mRemoteNGTests/Resources/dev-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/dev-update.txt
Normal file
5
mRemoteNGTests/Resources/dev-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/update-portable.txt
Normal file
5
mRemoteNGTests/Resources/update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/update.txt
Normal file
5
mRemoteNGTests/Resources/update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ExpandNodeClickHandlerTests
|
||||
{
|
||||
private ExpandNodeClickHandler _clickHandler;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_clickHandler = new ExpandNodeClickHandler(_connectionTree);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetedNodeIsExpanded()
|
||||
{
|
||||
var folder = new ContainerInfo();
|
||||
_clickHandler.Execute(folder);
|
||||
_connectionTree.Received().ToggleExpansion(folder);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NothingHappensWhenConnectionInfoProvided()
|
||||
{
|
||||
_clickHandler.Execute(new ConnectionInfo());
|
||||
_connectionTree.DidNotReceiveWithAnyArgs().ToggleExpansion(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownOnConstructorNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new ExpandNodeClickHandler(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class OpenConnectionClickHandlerTests
|
||||
{
|
||||
private OpenConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new OpenConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConnectionOpened()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().OpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new OpenConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SwitchToConnectionClickHandlerTests
|
||||
{
|
||||
private SwitchToConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new SwitchToConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SwitchesToConnection()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().SwitchToOpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().SwitchToOpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new SwitchToConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class TreeNodeCompositeClickHandlerTests
|
||||
{
|
||||
private TreeNodeCompositeClickHandler _clickHandler;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_clickHandler = new TreeNodeCompositeClickHandler();
|
||||
_connectionInfo = new ConnectionInfo();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExecutesAllItsHandlers()
|
||||
{
|
||||
var handler1 = Substitute.For<ITreeNodeClickHandler>();
|
||||
var handler2 = Substitute.For<ITreeNodeClickHandler>();
|
||||
_clickHandler.ClickHandlers = new[] {handler1, handler2};
|
||||
_clickHandler.Execute(_connectionInfo);
|
||||
handler1.Received().Execute(_connectionInfo);
|
||||
handler2.Received().Execute(_connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
51
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
51
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ConnectionTreeTests
|
||||
{
|
||||
private ConnectionTree _connectionTree;
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeModel = CreateConnectionTreeModel();
|
||||
_connectionTree = new ConnectionTree
|
||||
{
|
||||
PostSetupActions = new IConnectionTreeDelegate[] {new RootNodeExpander()}
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTree.Dispose();
|
||||
}
|
||||
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanDeleteLastFolderInTheTree()
|
||||
{
|
||||
var lastFolder = new ContainerInfo();
|
||||
_connectionTreeModel.RootNodes[0].AddChild(lastFolder);
|
||||
_connectionTree.ConnectionTreeModel = _connectionTreeModel;
|
||||
_connectionTree.SelectObject(lastFolder);
|
||||
_connectionTree.DeleteSelectedNode();
|
||||
Assert.That(_connectionTree.GetRootConnectionNode().HasChildren, Is.False);
|
||||
}
|
||||
|
||||
private ConnectionTreeModel CreateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
connectionTreeModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection));
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
mRemoteNGTests/Tree/PreviousSessionOpenerTests.cs
Normal file
50
mRemoteNGTests/Tree/PreviousSessionOpenerTests.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviousSessionOpenerTests
|
||||
{
|
||||
private PreviousSessionOpener _previousSessionOpener;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_previousSessionOpener = new PreviousSessionOpener(_connectionInitiator);
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.GetRootConnectionNode().Returns(BuildTree());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllRequestedSessionsAreReopened()
|
||||
{
|
||||
_previousSessionOpener.Execute(_connectionTree);
|
||||
_connectionInitiator.ReceivedWithAnyArgs(2).OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new PreviousSessionOpener(null));
|
||||
}
|
||||
|
||||
private RootNodeInfo BuildTree()
|
||||
{
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
root.AddChild(new ConnectionInfo());
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
mRemoteNGTests/Tree/PreviouslyOpenedFolderExpanderTests.cs
Normal file
49
mRemoteNGTests/Tree/PreviouslyOpenedFolderExpanderTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviouslyOpenedFolderExpanderTests
|
||||
{
|
||||
private PreviouslyOpenedFolderExpander _folderExpander;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_folderExpander = new PreviouslyOpenedFolderExpander();
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandsAllFoldersThatAreMarkedForExpansion()
|
||||
{
|
||||
var connectionTreeModel = GenerateConnectionTreeModel();
|
||||
_connectionTree.ConnectionTreeModel.Returns(connectionTreeModel);
|
||||
_connectionTree.GetRootConnectionNode().Returns(connectionTreeModel.RootNodes[0]);
|
||||
_folderExpander.Execute(_connectionTree);
|
||||
Assert.That(_connectionTree.ExpandedObjects, Is.EquivalentTo(connectionTreeModel.GetRecursiveChildList().OfType<ContainerInfo>().Where(info => info.IsExpanded)));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel GenerateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection) { IsExpanded = true };
|
||||
var folder1 = new ContainerInfo { IsExpanded = true };
|
||||
var folder2 = new ContainerInfo();
|
||||
var con1 = new ConnectionInfo();
|
||||
root.AddChild(folder1);
|
||||
folder1.AddChild(folder2);
|
||||
root.AddChild(con1);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SelectedConnectionDeletionConfirmerTests
|
||||
{
|
||||
private SelectedConnectionDeletionConfirmer _deletionConfirmer;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.SelectedNode.Returns(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingYesReturnsTrue()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickYes);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingNoReturnsFalse()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickNo);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.False);
|
||||
}
|
||||
|
||||
private DialogResult MockClickYes(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.Yes;
|
||||
}
|
||||
|
||||
private DialogResult MockClickNo(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.No;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
mRemoteNGTests/UI/Window/ConnectionTreeWindowTests.cs
Normal file
32
mRemoteNGTests/UI/Window/ConnectionTreeWindowTests.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.UI.Window;
|
||||
using NUnit.Framework;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.UI.Window
|
||||
{
|
||||
public class ConnectionTreeWindowTests
|
||||
{
|
||||
private ConnectionTreeWindow _connectionTreeWindow;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent());
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTreeWindow.Close();
|
||||
}
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanShowWindow()
|
||||
{
|
||||
_connectionTreeWindow.Show();
|
||||
Assert.That(_connectionTreeWindow.Visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -31,25 +31,25 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</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>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<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>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -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>
|
||||
@@ -101,13 +99,17 @@
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
@@ -126,7 +128,9 @@
|
||||
<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" />
|
||||
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
|
||||
<Compile Include="Connection\ConnectionInfoInheritanceTests.cs" />
|
||||
@@ -146,8 +150,15 @@
|
||||
<Compile Include="Security\CryptographyProviderFactoryTests.cs" />
|
||||
<Compile Include="Security\EncryptedSecureStringTests.cs" />
|
||||
<Compile Include="Security\LegacyRijndaelCryptographyProviderTests.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\ExpandNodeClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\NodeSearcherTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\OpenConnectionClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\PreviouslyOpenedFolderExpanderTests.cs" />
|
||||
<Compile Include="Tree\PreviousSessionOpenerTests.cs" />
|
||||
<Compile Include="Tree\RootNodeInfoTests.cs" />
|
||||
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
|
||||
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
|
||||
<Compile Include="UI\Controls\TestForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -157,6 +168,7 @@
|
||||
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
|
||||
<Compile Include="UI\Forms\PasswordFormTests.cs" />
|
||||
<Compile Include="UI\WindowListTests.cs" />
|
||||
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -207,6 +219,14 @@
|
||||
<ItemGroup>
|
||||
<None Include="Resources\confCons_v2_5_passwordis_Password_fullencryption.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\beta-update-portable.txt" />
|
||||
<Content Include="Resources\beta-update.txt" />
|
||||
<Content Include="Resources\dev-update-portable.txt" />
|
||||
<Content Include="Resources\dev-update.txt" />
|
||||
<Content Include="Resources\update-portable.txt" />
|
||||
<Content Include="Resources\update.txt" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
|
||||
2
mRemoteNGTests/mRemoteNGTests.csproj.DotSettings
Normal file
2
mRemoteNGTests/mRemoteNGTests.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=tree_005Cclickhandlers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -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
|
||||
|
||||
@@ -8,24 +8,23 @@ using System.Windows.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class CompatibilityChecker
|
||||
public static class CompatibilityChecker
|
||||
{
|
||||
public void CheckCompatibility()
|
||||
public static void CheckCompatibility()
|
||||
{
|
||||
CheckFipsPolicy();
|
||||
CheckLenovoAutoScrollUtility();
|
||||
}
|
||||
|
||||
private void CheckFipsPolicy()
|
||||
private static void CheckFipsPolicy()
|
||||
{
|
||||
if (FipsPolicyEnabledForServer2003() || FipsPolicyEnabledForServer2008AndNewer())
|
||||
{
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
Logger.Instance.InfoFormat("Checking FIPS Policy...");
|
||||
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2003()
|
||||
private static bool FipsPolicyEnabledForServer2003()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa");
|
||||
var fipsPolicy = regKey?.GetValue("FIPSAlgorithmPolicy");
|
||||
@@ -34,7 +33,7 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
private static bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy");
|
||||
var fipsPolicy = regKey?.GetValue("Enabled");
|
||||
@@ -43,12 +42,14 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private void CheckLenovoAutoScrollUtility()
|
||||
private static void CheckLenovoAutoScrollUtility()
|
||||
{
|
||||
Logger.Instance.InfoFormat("Checking Lenovo AutoScroll Utility...");
|
||||
|
||||
if (!Settings.Default.CompatibilityWarnLenovoAutoScrollUtility)
|
||||
return;
|
||||
|
||||
Process[] proccesses = new Process[] { };
|
||||
var proccesses = new Process[] { };
|
||||
try
|
||||
{
|
||||
proccesses = Process.GetProcessesByName("virtscrl");
|
||||
@@ -58,12 +59,10 @@ namespace mRemoteNG.App
|
||||
Runtime.MessageCollector.AddExceptionMessage("Error in CheckLenovoAutoScrollUtility", ex);
|
||||
}
|
||||
|
||||
if (proccesses.Length > 0)
|
||||
{
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
if (proccesses.Length <= 0) return;
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
|
||||
if (exportForm.ShowDialog(frmMain.Default) != DialogResult.OK)
|
||||
return ;
|
||||
return;
|
||||
|
||||
ConnectionInfo exportTarget;
|
||||
switch (exportForm.Scope)
|
||||
@@ -76,12 +76,17 @@ namespace mRemoteNG.App
|
||||
var factory = new CryptographyProviderFactory();
|
||||
var cryptographyProvider = factory.CreateAeadCryptographyProvider(mRemoteNG.Settings.Default.EncryptionEngine, mRemoteNG.Settings.Default.EncryptionBlockCipherMode);
|
||||
cryptographyProvider.KeyDerivationIterations = Settings.Default.EncryptionKeyDerivationIterations;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider);
|
||||
((XmlConnectionsSerializer) serializer).SaveFilter = saveFilter;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider)
|
||||
{
|
||||
Export = true,
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
case ConnectionsSaver.Format.mRCSV:
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat();
|
||||
((CsvConnectionsSerializerMremotengFormat)serializer).SaveFilter = saveFilter;
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat
|
||||
{
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(saveFormat), saveFormat, null);
|
||||
|
||||
@@ -11,23 +11,27 @@ namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class GeneralAppInfo
|
||||
{
|
||||
public static readonly string UrlHome = "http://www.mremoteng.org/";
|
||||
public static readonly string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public static readonly string UrlForum = "http://forum.mremoteng.org/";
|
||||
public static readonly string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static readonly string ApplicationVersion = Application.ProductVersion;
|
||||
public const string UrlHome = "http://www.mremoteng.org/";
|
||||
public const string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public const string UrlForum = "http://forum.mremoteng.org/";
|
||||
public const string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static string ApplicationVersion = Application.ProductVersion;
|
||||
public static readonly string ProductName = Application.ProductName;
|
||||
public static readonly string Copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCopyrightAttribute), false)).Copyright;
|
||||
public static readonly string HomePath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||
public static string ReportingFilePath = "";
|
||||
//public static string ReportingFilePath = "";
|
||||
public static readonly string PuttyPath = HomePath + "\\PuTTYNG.exe";
|
||||
public static string UserAgent
|
||||
{
|
||||
get
|
||||
{
|
||||
var details = new List<string>();
|
||||
details.Add("compatible");
|
||||
details.Add(OSVersion.Platform == PlatformID.Win32NT ? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}": OSVersion.VersionString);
|
||||
var details = new List<string>
|
||||
{
|
||||
"compatible",
|
||||
OSVersion.Platform == PlatformID.Win32NT
|
||||
? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}"
|
||||
: OSVersion.VersionString
|
||||
};
|
||||
if (Is64BitProcess)
|
||||
{
|
||||
details.Add("WOW64");
|
||||
|
||||
@@ -1,34 +1,72 @@
|
||||
namespace mRemoteNG.App.Info
|
||||
using System;
|
||||
|
||||
namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class UpdateChannelInfo
|
||||
{
|
||||
public static string FileName
|
||||
public const string STABLE = "Stable";
|
||||
public const string BETA = "Beta";
|
||||
public const string DEV = "Development";
|
||||
|
||||
/* no #if here since they are used for unit tests as well */
|
||||
public const string STABLE_PORTABLE = "update-portable.txt";
|
||||
public const string BETA_PORTABLE = "beta-update-portable.txt";
|
||||
public const string DEV_PORTABLE = "dev-update-portable.txt";
|
||||
|
||||
public const string STABLE_MSI = "update.txt";
|
||||
public const string BETA_MSI = "beta-update.txt";
|
||||
public const string DEV_MSI = "dev-update.txt";
|
||||
|
||||
|
||||
public static Uri GetUpdateChannelInfo()
|
||||
{
|
||||
var channel = IsValidChannel(Settings.Default.UpdateChannel) ? Settings.Default.UpdateChannel : STABLE;
|
||||
return GetUpdateTxtUri(channel);
|
||||
}
|
||||
|
||||
private static string GetChannelFileName(string channel)
|
||||
{
|
||||
#if PORTABLE
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return PORTABLE update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-portable-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-portable-debug.txt" : "update-portable.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_PORTABLE;
|
||||
case BETA:
|
||||
return BETA_PORTABLE;
|
||||
case DEV:
|
||||
return DEV_PORTABLE;
|
||||
default:
|
||||
return STABLE_PORTABLE;
|
||||
}
|
||||
#else //NOT portable
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return INSTALLER update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-debug.txt" : "update.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_MSI;
|
||||
case BETA:
|
||||
return BETA_MSI;
|
||||
case DEV:
|
||||
return DEV_MSI;
|
||||
default:
|
||||
return STABLE_MSI;
|
||||
}
|
||||
#endif //endif for PORTABLE
|
||||
}
|
||||
|
||||
private static Uri GetUpdateTxtUri(string channel)
|
||||
{
|
||||
return new Uri(new Uri(Settings.Default.UpdateAddress), new Uri(GetChannelFileName(channel), UriKind.Relative));
|
||||
}
|
||||
|
||||
private static bool IsValidChannel(string s)
|
||||
{
|
||||
return s.Equals(STABLE) || s.Equals(BETA) || s.Equals(DEV);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,10 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
@@ -41,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);
|
||||
|
||||
@@ -75,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
|
||||
@@ -285,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
|
||||
@@ -326,6 +343,11 @@ namespace mRemoteNG.App
|
||||
/// </summary>
|
||||
public const int WM_ACTIVATEAPP = 0x1C;
|
||||
|
||||
/// <summary>
|
||||
/// Sent to a window if the mouse causes the cursor to move within a window and mouse input is not captured.
|
||||
/// </summary>
|
||||
public const int WM_SETCURSOR = 0x20;
|
||||
|
||||
/// <summary>
|
||||
/// Sent when the cursor is in an inactive window and the user presses a mouse button. The parent window receives this message only if the child window passes it to the DefWindowProc function.
|
||||
/// </summary>
|
||||
@@ -449,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;
|
||||
|
||||
@@ -33,17 +33,17 @@ namespace mRemoteNG.App
|
||||
#region Public Properties
|
||||
public static WindowList WindowList { get; set; }
|
||||
public static MessageCollector MessageCollector { get; set; }
|
||||
public static Controls.NotificationAreaIcon NotificationAreaIcon { get; set; }
|
||||
public static NotificationAreaIcon NotificationAreaIcon { get; set; }
|
||||
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
|
||||
{
|
||||
get { return Windows.TreeForm.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTreeModel = value; }
|
||||
get { return Windows.TreeForm.ConnectionTree.ConnectionTreeModel; }
|
||||
set { Windows.TreeForm.ConnectionTree.ConnectionTreeModel = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace mRemoteNG.App
|
||||
// Load config
|
||||
connectionsLoader.ConnectionFileName = filename;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -274,7 +274,7 @@ namespace mRemoteNG.App
|
||||
{
|
||||
if (withDialog)
|
||||
{
|
||||
var loadDialog = Controls.ConnectionsLoadDialog();
|
||||
var loadDialog = ConnectionsLoadDialog();
|
||||
if (loadDialog.ShowDialog() != DialogResult.OK) return;
|
||||
connectionsLoader.ConnectionFileName = loadDialog.FileName;
|
||||
}
|
||||
@@ -283,12 +283,12 @@ namespace mRemoteNG.App
|
||||
connectionsLoader.ConnectionFileName = GetStartupConnectionFileName();
|
||||
}
|
||||
|
||||
CreateBackupFile(Convert.ToString(connectionsLoader.ConnectionFileName));
|
||||
CreateBackupFile(connectionsLoader.ConnectionFileName);
|
||||
}
|
||||
|
||||
connectionsLoader.UseDatabase = Settings.Default.UseSQLServer;
|
||||
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
|
||||
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
|
||||
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
@@ -353,6 +353,16 @@ namespace mRemoteNG.App
|
||||
}
|
||||
}
|
||||
|
||||
private static OpenFileDialog ConnectionsLoadDialog()
|
||||
{
|
||||
return new OpenFileDialog
|
||||
{
|
||||
CheckFileExists = true,
|
||||
InitialDirectory = ConnectionsFileInfo.DefaultConnectionsPath,
|
||||
Filter = Language.strFiltermRemoteXML + @"|*.xml|" + Language.strFilterAll + @"|*.*"
|
||||
};
|
||||
}
|
||||
|
||||
private static void CreateBackupFile(string fileName)
|
||||
{
|
||||
// This intentionally doesn't prune any existing backup files. We just assume the user doesn't want any new ones created.
|
||||
@@ -455,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();
|
||||
@@ -593,7 +603,8 @@ namespace mRemoteNG.App
|
||||
connectionInfo.Protocol = url.StartsWith("https:") ? ProtocolType.HTTPS : ProtocolType.HTTP;
|
||||
connectionInfo.SetDefaultPort();
|
||||
connectionInfo.IsQuickConnect = true;
|
||||
ConnectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
var connectionInitiator = new ConnectionInitiator();
|
||||
connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public static void GoToWebsite()
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
@@ -14,22 +7,26 @@ using System.IO;
|
||||
using System.Management;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.Connections.Multiuser;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private CompatibilityChecker _compatibilityChecker;
|
||||
private AppUpdater _appUpdate;
|
||||
|
||||
public static Startup Instance { get; } = new Startup();
|
||||
|
||||
private Startup()
|
||||
{
|
||||
_compatibilityChecker = new CompatibilityChecker();
|
||||
_appUpdate = new AppUpdater();
|
||||
}
|
||||
|
||||
@@ -41,49 +38,29 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Debug.Print("---------------------------" + Environment.NewLine + "[START] - " + Convert.ToString(DateTime.Now, CultureInfo.InvariantCulture));
|
||||
LogStartupData();
|
||||
_compatibilityChecker.CheckCompatibility();
|
||||
CompatibilityChecker.CheckCompatibility();
|
||||
ParseCommandLineArgs();
|
||||
IeBrowserEmulation.Register();
|
||||
GetConnectionIcons();
|
||||
DefaultConnectionInfo.Instance.LoadFrom(Settings.Default, (a)=>"ConDefault"+a);
|
||||
DefaultConnectionInheritance.Instance.LoadFrom(Settings.Default, (a)=>"InhDefault"+a);
|
||||
}
|
||||
|
||||
public void SetDefaultLayout()
|
||||
private static void GetConnectionIcons()
|
||||
{
|
||||
frmMain.Default.pnlDock.Visible = false;
|
||||
|
||||
frmMain.Default.pnlDock.DockLeftPortion = frmMain.Default.pnlDock.Width * 0.2;
|
||||
frmMain.Default.pnlDock.DockRightPortion = frmMain.Default.pnlDock.Width * 0.2;
|
||||
frmMain.Default.pnlDock.DockTopPortion = frmMain.Default.pnlDock.Height * 0.25;
|
||||
frmMain.Default.pnlDock.DockBottomPortion = frmMain.Default.pnlDock.Height * 0.25;
|
||||
|
||||
Windows.TreePanel.Show(frmMain.Default.pnlDock, DockState.DockLeft);
|
||||
Windows.ConfigPanel.Show(frmMain.Default.pnlDock);
|
||||
Windows.ConfigPanel.DockTo(Windows.TreePanel.Pane, DockStyle.Bottom, -1);
|
||||
|
||||
Windows.ScreenshotForm.Hide();
|
||||
|
||||
frmMain.Default.pnlDock.Visible = true;
|
||||
}
|
||||
|
||||
private void GetConnectionIcons()
|
||||
{
|
||||
string iPath = GeneralAppInfo.HomePath + "\\Icons\\";
|
||||
var iPath = GeneralAppInfo.HomePath + "\\Icons\\";
|
||||
if (Directory.Exists(iPath) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string f in Directory.GetFiles(iPath, "*.ico", SearchOption.AllDirectories))
|
||||
foreach (var f in Directory.GetFiles(iPath, "*.ico", SearchOption.AllDirectories))
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(f);
|
||||
var fInfo = new FileInfo(f);
|
||||
Array.Resize(ref ConnectionIcon.Icons, ConnectionIcon.Icons.Length + 1);
|
||||
ConnectionIcon.Icons.SetValue(fInfo.Name.Replace(".ico", ""), ConnectionIcon.Icons.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogStartupData()
|
||||
private static void LogStartupData()
|
||||
{
|
||||
if (!Settings.Default.WriteLogFile) return;
|
||||
LogApplicationData();
|
||||
@@ -93,17 +70,17 @@ namespace mRemoteNG.App
|
||||
LogCultureData();
|
||||
}
|
||||
|
||||
private void LogSystemData()
|
||||
private static void LogSystemData()
|
||||
{
|
||||
string osData = GetOperatingSystemData();
|
||||
string architecture = GetArchitectureData();
|
||||
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(Convert.ToString(s)))));
|
||||
var osData = GetOperatingSystemData();
|
||||
var architecture = GetArchitectureData();
|
||||
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(s))));
|
||||
}
|
||||
|
||||
private string GetOperatingSystemData()
|
||||
private static string GetOperatingSystemData()
|
||||
{
|
||||
string osVersion = string.Empty;
|
||||
string servicePack = string.Empty;
|
||||
var osVersion = string.Empty;
|
||||
var servicePack = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -118,13 +95,13 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Logger.Instance.WarnFormat($"Error retrieving operating system information from WMI. {ex.Message}");
|
||||
}
|
||||
string osData = string.Join(" ", new string[] { osVersion, servicePack });
|
||||
var osData = string.Join(" ", osVersion, servicePack);
|
||||
return osData;
|
||||
}
|
||||
|
||||
private string GetOSServicePack(string servicePack, ManagementObject managementObject)
|
||||
private static string GetOSServicePack(string servicePack, ManagementObject managementObject)
|
||||
{
|
||||
int servicePackNumber = Convert.ToInt32(managementObject.GetPropertyValue("ServicePackMajorVersion"));
|
||||
var servicePackNumber = Convert.ToInt32(managementObject.GetPropertyValue("ServicePackMajorVersion"));
|
||||
if (servicePackNumber != 0)
|
||||
{
|
||||
servicePack = $"Service Pack {servicePackNumber}";
|
||||
@@ -132,15 +109,15 @@ namespace mRemoteNG.App
|
||||
return servicePack;
|
||||
}
|
||||
|
||||
private string GetArchitectureData()
|
||||
private static string GetArchitectureData()
|
||||
{
|
||||
string architecture = string.Empty;
|
||||
var architecture = string.Empty;
|
||||
try
|
||||
{
|
||||
foreach (var o in new ManagementObjectSearcher("SELECT * FROM Win32_Processor WHERE DeviceID=\'CPU0\'").Get())
|
||||
{
|
||||
var managementObject = (ManagementObject) o;
|
||||
int addressWidth = Convert.ToInt32(managementObject.GetPropertyValue("AddressWidth"));
|
||||
var addressWidth = Convert.ToInt32(managementObject.GetPropertyValue("AddressWidth"));
|
||||
architecture = $"{addressWidth}-bit";
|
||||
}
|
||||
}
|
||||
@@ -151,7 +128,7 @@ namespace mRemoteNG.App
|
||||
return architecture;
|
||||
}
|
||||
|
||||
private void LogApplicationData()
|
||||
private static void LogApplicationData()
|
||||
{
|
||||
#if !PORTABLE
|
||||
Logger.Instance.InfoFormat($"{Application.ProductName} {Application.ProductVersion} starting.");
|
||||
@@ -161,17 +138,17 @@ namespace mRemoteNG.App
|
||||
#endif
|
||||
}
|
||||
|
||||
private void LogCmdLineArgs()
|
||||
private static void LogCmdLineArgs()
|
||||
{
|
||||
Logger.Instance.InfoFormat($"Command Line: {Environment.GetCommandLineArgs()}");
|
||||
}
|
||||
|
||||
private void LogCLRData()
|
||||
private static void LogCLRData()
|
||||
{
|
||||
Logger.Instance.InfoFormat($"Microsoft .NET CLR {Environment.Version}");
|
||||
}
|
||||
|
||||
private void LogCultureData()
|
||||
private static void LogCultureData()
|
||||
{
|
||||
Logger.Instance.InfoFormat(
|
||||
$"System Culture: {Thread.CurrentThread.CurrentUICulture.Name}/{Thread.CurrentThread.CurrentUICulture.NativeName}");
|
||||
@@ -197,7 +174,7 @@ namespace mRemoteNG.App
|
||||
return;
|
||||
}
|
||||
|
||||
DateTime nextUpdateCheck = Convert.ToDateTime(Settings.Default.CheckForUpdatesLastCheck.Add(TimeSpan.FromDays(Convert.ToDouble(Settings.Default.CheckForUpdatesFrequencyDays))));
|
||||
var nextUpdateCheck = Convert.ToDateTime(Settings.Default.CheckForUpdatesLastCheck.Add(TimeSpan.FromDays(Convert.ToDouble(Settings.Default.CheckForUpdatesFrequencyDays))));
|
||||
if (!Settings.Default.UpdatePending && DateTime.UtcNow < nextUpdateCheck)
|
||||
{
|
||||
return;
|
||||
@@ -211,7 +188,7 @@ namespace mRemoteNG.App
|
||||
{
|
||||
if (frmMain.Default.InvokeRequired)
|
||||
{
|
||||
frmMain.Default.Invoke(new AsyncCompletedEventHandler(GetUpdateInfoCompleted), new object[] { sender, e });
|
||||
frmMain.Default.Invoke(new AsyncCompletedEventHandler(GetUpdateInfoCompleted), sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,7 +202,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
if (e.Error != null)
|
||||
{
|
||||
throw (e.Error);
|
||||
throw e.Error;
|
||||
}
|
||||
|
||||
if (_appUpdate.IsUpdateAvailable())
|
||||
@@ -235,18 +212,45 @@ 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;
|
||||
|
||||
private void ParseCommandLineArgs()
|
||||
// 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()
|
||||
{
|
||||
try
|
||||
{
|
||||
CmdArgumentsInterpreter cmd = new CmdArgumentsInterpreter(Environment.GetCommandLineArgs());
|
||||
var cmd = new CmdArgumentsInterpreter(Environment.GetCommandLineArgs());
|
||||
|
||||
string ConsParam = "";
|
||||
var ConsParam = "";
|
||||
if (cmd["cons"] != null)
|
||||
{
|
||||
ConsParam = "cons";
|
||||
@@ -256,7 +260,7 @@ namespace mRemoteNG.App
|
||||
ConsParam = "c";
|
||||
}
|
||||
|
||||
string ResetPosParam = "";
|
||||
var ResetPosParam = "";
|
||||
if (cmd["resetpos"] != null)
|
||||
{
|
||||
ResetPosParam = "resetpos";
|
||||
@@ -266,7 +270,7 @@ namespace mRemoteNG.App
|
||||
ResetPosParam = "rp";
|
||||
}
|
||||
|
||||
string ResetPanelsParam = "";
|
||||
var ResetPanelsParam = "";
|
||||
if (cmd["resetpanels"] != null)
|
||||
{
|
||||
ResetPanelsParam = "resetpanels";
|
||||
@@ -276,7 +280,7 @@ namespace mRemoteNG.App
|
||||
ResetPanelsParam = "rpnl";
|
||||
}
|
||||
|
||||
string ResetToolbarsParam = "";
|
||||
var ResetToolbarsParam = "";
|
||||
if (cmd["resettoolbar"] != null)
|
||||
{
|
||||
ResetToolbarsParam = "resettoolbar";
|
||||
@@ -293,7 +297,7 @@ namespace mRemoteNG.App
|
||||
ResetToolbarsParam = "rtbr";
|
||||
}
|
||||
|
||||
string NoReconnectParam = "";
|
||||
var NoReconnectParam = "";
|
||||
if (cmd["noreconnect"] != null)
|
||||
{
|
||||
NoReconnectParam = "noreconnect";
|
||||
@@ -303,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;
|
||||
}
|
||||
else 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))
|
||||
@@ -350,6 +337,8 @@ namespace mRemoteNG.App
|
||||
{
|
||||
Settings.Default.ResetToolbars = true;
|
||||
}
|
||||
|
||||
Settings.Default.Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -9,118 +9,122 @@ using mRemoteNG.Security.SymmetricEncryption;
|
||||
using System.Security.Cryptography;
|
||||
#if !PORTABLE
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
#else
|
||||
using System.Windows.Forms;
|
||||
#endif
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
public class AppUpdater
|
||||
{
|
||||
private WebProxy _webProxy;
|
||||
public class AppUpdater
|
||||
{
|
||||
private WebProxy _webProxy;
|
||||
private Thread _getUpdateInfoThread;
|
||||
private Thread _getChangeLogThread;
|
||||
|
||||
#region Public Properties
|
||||
#region Public Properties
|
||||
|
||||
public UpdateInfo CurrentUpdateInfo { get; private set; }
|
||||
|
||||
public string ChangeLog { get; private set; }
|
||||
public string ChangeLog { get; private set; }
|
||||
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void SetProxySettings()
|
||||
{
|
||||
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
|
||||
var proxyAddress = Settings.Default.UpdateProxyAddress;
|
||||
var port = Settings.Default.UpdateProxyPort;
|
||||
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
|
||||
var username = Settings.Default.UpdateProxyAuthUser;
|
||||
#region Public Methods
|
||||
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
|
||||
private void SetProxySettings()
|
||||
{
|
||||
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
|
||||
var proxyAddress = Settings.Default.UpdateProxyAddress;
|
||||
var port = Settings.Default.UpdateProxyPort;
|
||||
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
|
||||
var username = Settings.Default.UpdateProxyAuthUser;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
|
||||
SetProxySettings(shouldWeUseProxy, proxyAddress, port, useAuthentication, username, password);
|
||||
}
|
||||
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
}
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
#if !PORTABLE
|
||||
CurrentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "exe"));
|
||||
CurrentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "msi"));
|
||||
#else
|
||||
var sfd = new SaveFileDialog
|
||||
{
|
||||
@@ -138,166 +142,174 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
#endif
|
||||
DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
private WebClient _downloadUpdateWebClient;
|
||||
private WebClient DownloadUpdateWebClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
|
||||
_downloadUpdateWebClient = CreateWebClient();
|
||||
|
||||
_downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged;
|
||||
_downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted;
|
||||
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private WebClient CreateWebClient()
|
||||
{
|
||||
var webClient = new WebClient();
|
||||
webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent);
|
||||
webClient.Proxy = _webProxy;
|
||||
return webClient;
|
||||
}
|
||||
|
||||
private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result, Exception exception, bool cancelled, object userToken)
|
||||
{
|
||||
var type = typeof(DownloadStringCompletedEventArgs);
|
||||
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
Type[] argumentTypes = {typeof(string), typeof(Exception), typeof(bool), typeof(object)};
|
||||
var constructor = type.GetConstructor(bindingFlags, null, argumentTypes, null);
|
||||
object[] arguments = {result, exception, cancelled, userToken};
|
||||
}
|
||||
|
||||
return (DownloadStringCompletedEventArgs)constructor.Invoke(arguments);
|
||||
}
|
||||
|
||||
private DownloadStringCompletedEventArgs DownloadString(Uri address)
|
||||
{
|
||||
var webClient = CreateWebClient();
|
||||
var result = string.Empty;
|
||||
Exception exception = null;
|
||||
var cancelled = false;
|
||||
|
||||
try
|
||||
{
|
||||
result = webClient.DownloadString(address);
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
cancelled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null);
|
||||
}
|
||||
|
||||
private void GetUpdateInfo()
|
||||
{
|
||||
var updateFileUri = new Uri(new Uri(Convert.ToString(Settings.Default.UpdateAddress)), new Uri(UpdateChannelInfo.FileName, UriKind.Relative));
|
||||
var e = DownloadString(updateFileUri);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
CurrentUpdateInfo = UpdateInfo.FromString(e.Result);
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private WebClient _downloadUpdateWebClient;
|
||||
|
||||
private WebClient DownloadUpdateWebClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
|
||||
_downloadUpdateWebClient = CreateWebClient();
|
||||
|
||||
_downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged;
|
||||
_downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted;
|
||||
|
||||
return _downloadUpdateWebClient;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private WebClient CreateWebClient()
|
||||
{
|
||||
var webClient = new WebClient();
|
||||
webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent);
|
||||
webClient.Proxy = _webProxy;
|
||||
return webClient;
|
||||
}
|
||||
|
||||
private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result,
|
||||
Exception exception, bool cancelled, object userToken)
|
||||
{
|
||||
var type = typeof(DownloadStringCompletedEventArgs);
|
||||
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
Type[] argumentTypes = {typeof(string), typeof(Exception), typeof(bool), typeof(object)};
|
||||
var constructor = type.GetConstructor(bindingFlags, null, argumentTypes, null);
|
||||
object[] arguments = {result, exception, cancelled, userToken};
|
||||
|
||||
return (DownloadStringCompletedEventArgs) constructor.Invoke(arguments);
|
||||
}
|
||||
|
||||
public DownloadStringCompletedEventArgs DownloadString(Uri address)
|
||||
{
|
||||
var webClient = CreateWebClient();
|
||||
var result = string.Empty;
|
||||
Exception exception = null;
|
||||
var cancelled = false;
|
||||
|
||||
try
|
||||
{
|
||||
result = webClient.DownloadString(address);
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
cancelled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null);
|
||||
}
|
||||
|
||||
private void GetUpdateInfo()
|
||||
{
|
||||
var e = DownloadString(UpdateChannelInfo.GetUpdateChannelInfo());
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
CurrentUpdateInfo = UpdateInfo.FromString(e.Result);
|
||||
|
||||
Settings.Default.CheckForUpdatesLastCheck = DateTime.UtcNow;
|
||||
if (!Settings.Default.UpdatePending)
|
||||
{
|
||||
if (!Settings.Default.UpdatePending)
|
||||
{
|
||||
Settings.Default.UpdatePending = IsUpdateAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetUpdateInfoCompletedEventEvent?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void GetChangeLog()
|
||||
{
|
||||
var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
ChangeLog = e.Result;
|
||||
}
|
||||
|
||||
private void GetChangeLog()
|
||||
{
|
||||
var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress);
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
ChangeLog = e.Result;
|
||||
}
|
||||
|
||||
GetChangeLogCompletedEventEvent?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
|
||||
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
DownloadUpdateProgressChangedEventEvent?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
var raiseEventArgs = e;
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
var raiseEventArgs = e;
|
||||
|
||||
if (!e.Cancelled && e.Error == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if !PORTABLE
|
||||
var updateAuthenticode = new Authenticode(CurrentUpdateInfo.UpdateFilePath)
|
||||
{
|
||||
RequireThumbprintMatch = true,
|
||||
ThumbprintToMatch = CurrentUpdateInfo.CertificateThumbprint
|
||||
};
|
||||
{
|
||||
RequireThumbprintMatch = true,
|
||||
ThumbprintToMatch = CurrentUpdateInfo.CertificateThumbprint
|
||||
};
|
||||
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
throw (updateAuthenticode.Exception);
|
||||
}
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
throw updateAuthenticode.Exception;
|
||||
}
|
||||
|
||||
throw (new Exception(updateAuthenticode.StatusMessage));
|
||||
}
|
||||
throw new Exception(updateAuthenticode.StatusMessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
using (var md5 = MD5.Create())
|
||||
using (var cksum = SHA512.Create())
|
||||
{
|
||||
using (var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath))
|
||||
{
|
||||
var hash = md5.ComputeHash(stream);
|
||||
var hash = cksum.ComputeHash(stream);
|
||||
var hashString = BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
|
||||
if (!hashString.Equals(CurrentUpdateInfo.Checksum))
|
||||
throw new Exception("MD5 Hashes didn't match!");
|
||||
throw new Exception("SHA512 Hashes didn't match!");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
raiseEventArgs = new AsyncCompletedEventArgs(ex, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEventArgs.Cancelled || raiseEventArgs.Error != null)
|
||||
{
|
||||
File.Delete(CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
raiseEventArgs = new AsyncCompletedEventArgs(ex, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEventArgs.Cancelled || raiseEventArgs.Error != null)
|
||||
{
|
||||
File.Delete(CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
|
||||
DownloadUpdateCompletedEventEvent?.Invoke(this, raiseEventArgs);
|
||||
|
||||
_downloadUpdateWebClient.Dispose();
|
||||
_downloadUpdateWebClient = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
_downloadUpdateWebClient = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
private AsyncCompletedEventHandler GetUpdateInfoCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler GetUpdateInfoCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -311,6 +323,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler GetChangeLogCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler GetChangeLogCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -323,7 +336,8 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
|
||||
public event DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEvent
|
||||
{
|
||||
add
|
||||
@@ -337,6 +351,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler DownloadUpdateCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler DownloadUpdateCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -348,6 +363,7 @@ namespace mRemoteNG.App.Update
|
||||
DownloadUpdateCompletedEventEvent = (AsyncCompletedEventHandler)Delegate.Remove(DownloadUpdateCompletedEventEvent, value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
@@ -14,7 +15,8 @@ namespace mRemoteNG.App.Update
|
||||
#if !PORTABLE
|
||||
public string CertificateThumbprint { get; private set; }
|
||||
#endif
|
||||
public string FileName { get; private set; }
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public string FileName { get; set; }
|
||||
public string Checksum { get; private set; }
|
||||
|
||||
public static UpdateInfo FromString(string input)
|
||||
@@ -30,16 +32,45 @@ namespace mRemoteNG.App.Update
|
||||
newInfo.Version = updateFile.GetVersion();
|
||||
newInfo.DownloadAddress = updateFile.GetUri("dURL");
|
||||
newInfo.ChangeLogAddress = updateFile.GetUri("clURL");
|
||||
#if false
|
||||
newInfo.ImageAddress = updateFile.GetUri("imgURL");
|
||||
newInfo.ImageLinkAddress = updateFile.GetUri("imgURLLink");
|
||||
#endif
|
||||
#if !PORTABLE
|
||||
newInfo.CertificateThumbprint = updateFile.GetThumbprint();
|
||||
#endif
|
||||
newInfo.FileName = updateFile.GetFileName();
|
||||
newInfo.Checksum = updateFile.GetChecksum();
|
||||
newInfo.IsValid = true;
|
||||
newInfo.IsValid = newInfo.CheckIfValid();
|
||||
}
|
||||
return newInfo;
|
||||
}
|
||||
|
||||
public bool CheckIfValid()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Version.ToString()))
|
||||
return false;
|
||||
if(string.IsNullOrEmpty(DownloadAddress.AbsoluteUri))
|
||||
return false;
|
||||
if (string.IsNullOrEmpty(ChangeLogAddress.AbsoluteUri))
|
||||
return false;
|
||||
#if false
|
||||
if (string.IsNullOrEmpty(ImageAddress.AbsoluteUri))
|
||||
return false;
|
||||
if (string.IsNullOrEmpty(ImageLinkAddress.AbsoluteUri))
|
||||
return false;
|
||||
#endif
|
||||
#if !PORTABLE
|
||||
if (string.IsNullOrEmpty(CertificateThumbprint))
|
||||
return false;
|
||||
#endif
|
||||
if (string.IsNullOrEmpty(FileName))
|
||||
return false;
|
||||
// ReSharper disable once ConvertIfStatementToReturnStatement
|
||||
if (string.IsNullOrEmpty(Checksum))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,11 +85,12 @@ 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 ;
|
||||
return;
|
||||
}
|
||||
|
||||
var rootTreeNode = Runtime.ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
||||
@@ -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();
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher != null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -158,7 +158,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_eventWatcher.EnableRaisingEvents = false;
|
||||
_eventWatcher.Dispose();
|
||||
@@ -231,7 +231,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_puttyConfFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_puttyConfFile))
|
||||
{
|
||||
@@ -299,7 +299,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_sessionFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_sessionFile))
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
// check/continue here so we don't create empty connection objects
|
||||
if(!_importSubOU) continue;
|
||||
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer);
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer, _importSubOU);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"];
|
||||
@@ -84,6 +99,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
connectionInfo.RenderingEngine = (HTTPBase.RenderingEngine)Enum.Parse(typeof(HTTPBase.RenderingEngine), (string)dataRow["RenderingEngine"]);
|
||||
connectionInfo.ICAEncryptionStrength = (ProtocolICA.EncryptionStrength)Enum.Parse(typeof(ProtocolICA.EncryptionStrength), (string)dataRow["ICAEncryptionStrength"]);
|
||||
connectionInfo.RDPAuthenticationLevel = (ProtocolRDP.AuthenticationLevel)Enum.Parse(typeof(ProtocolRDP.AuthenticationLevel), (string)dataRow["RDPAuthenticationLevel"]);
|
||||
connectionInfo.RDPMinutesToIdleTimeout = (int)dataRow["RDPMinutesToIdleTimeout"];
|
||||
connectionInfo.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
|
||||
connectionInfo.LoadBalanceInfo = (string)dataRow["LoadBalanceInfo"];
|
||||
connectionInfo.Colors = (ProtocolRDP.RDPColors)Enum.Parse(typeof(ProtocolRDP.RDPColors) ,(string)dataRow["Colors"]);
|
||||
connectionInfo.Resolution = (ProtocolRDP.RDPResolutions)Enum.Parse(typeof(ProtocolRDP.RDPResolutions), (string)dataRow["Resolution"]);
|
||||
@@ -153,6 +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["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"];
|
||||
@@ -189,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,141 +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("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("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)
|
||||
@@ -180,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;
|
||||
@@ -200,6 +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["LoadBalanceInfo"] = connectionInfo.LoadBalanceInfo;
|
||||
dataRow["Colors"] = connectionInfo.Colors;
|
||||
dataRow["Resolution"] = connectionInfo.Resolution;
|
||||
@@ -214,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;
|
||||
@@ -261,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;
|
||||
@@ -270,6 +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["InheritLoadBalanceInfo"] = connectionInfo.Inheritance.LoadBalanceInfo;
|
||||
dataRow["InheritPreExtApp"] = connectionInfo.Inheritance.PreExtApp;
|
||||
dataRow["InheritPostExtApp"] = connectionInfo.Inheritance.PostExtApp;
|
||||
@@ -316,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;
|
||||
@@ -325,6 +350,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
dataRow["InheritUsername"] = false;
|
||||
dataRow["InheritICAEncryptionStrength"] = false;
|
||||
dataRow["InheritRDPAuthenticationLevel"] = 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Security;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
@@ -13,14 +14,15 @@ namespace mRemoteNG.Config.Serializers
|
||||
private readonly SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter = new SaveFilter();
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
|
||||
{
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
}
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (encryptionKey == null)
|
||||
throw new ArgumentNullException(nameof(encryptionKey));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
_saveFilter = saveFilter;
|
||||
@@ -44,6 +46,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("Descr", connectionInfo.Description));
|
||||
element.Add(new XAttribute("Icon", connectionInfo.Icon));
|
||||
element.Add(new XAttribute("Panel", connectionInfo.Panel));
|
||||
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
|
||||
|
||||
element.Add(_saveFilter.SaveUsername
|
||||
? new XAttribute("Username", connectionInfo.Username)
|
||||
@@ -67,6 +70,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("RenderingEngine", connectionInfo.RenderingEngine));
|
||||
element.Add(new XAttribute("ICAEncryptionStrength", connectionInfo.ICAEncryptionStrength));
|
||||
element.Add(new XAttribute("RDPAuthenticationLevel", connectionInfo.RDPAuthenticationLevel));
|
||||
element.Add(new XAttribute("RDPMinutesToIdleTimeout", connectionInfo.RDPMinutesToIdleTimeout));
|
||||
element.Add(new XAttribute("RDPAlertIdleTimeout", connectionInfo.RDPAlertIdleTimeout));
|
||||
element.Add(new XAttribute("LoadBalanceInfo", connectionInfo.LoadBalanceInfo));
|
||||
element.Add(new XAttribute("Colors", connectionInfo.Colors));
|
||||
element.Add(new XAttribute("Resolution", connectionInfo.Resolution));
|
||||
@@ -159,6 +164,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", connectionInfo.Inheritance.Username.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", connectionInfo.Inheritance.ICAEncryptionStrength.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", connectionInfo.Inheritance.RDPAuthenticationLevel.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", connectionInfo.Inheritance.RDPMinutesToIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", connectionInfo.Inheritance.RDPAlertIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", connectionInfo.Inheritance.LoadBalanceInfo.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", connectionInfo.Inheritance.PreExtApp.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", connectionInfo.Inheritance.PostExtApp.ToString()));
|
||||
@@ -214,6 +221,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", false.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", false.ToString()));
|
||||
|
||||
@@ -485,8 +485,13 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
if (_confVersion >= 2.6)
|
||||
{
|
||||
connectionInfo.ConstantID = xmlnode.Attributes["Id"]?.Value ?? connectionInfo.ConstantID;
|
||||
connectionInfo.SoundQuality = (ProtocolRDP.RDPSoundQuality)Tools.MiscTools.StringToEnum(typeof(ProtocolRDP.RDPSoundQuality), Convert.ToString(xmlnode.Attributes["SoundQuality"].Value));
|
||||
connectionInfo.Inheritance.SoundQuality = bool.Parse(xmlnode.Attributes["InheritSoundQuality"].Value);
|
||||
connectionInfo.RDPMinutesToIdleTimeout = Convert.ToInt32(xmlnode.Attributes["RDPMinutesToIdleTimeout"]?.Value ?? "0");
|
||||
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPMinutesToIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["RDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.Inheritance.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
@@ -14,10 +15,17 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter;
|
||||
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider)
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_saveFilter = saveFilter;
|
||||
}
|
||||
|
||||
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
|
||||
@@ -77,7 +85,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey);
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey, _saveFilter);
|
||||
return connectionSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
var xml = "";
|
||||
try
|
||||
{
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, SaveFilter);
|
||||
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
|
||||
xml = WriteXmlToString(xmlDocument);
|
||||
}
|
||||
|
||||
@@ -20,47 +20,59 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
public void LoadExternalAppsFromXML()
|
||||
{
|
||||
var oldPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\" + GeneralAppInfo.ProductName + "\\" + SettingsFileInfo.ExtAppsFilesName;
|
||||
var newPath = SettingsFileInfo.SettingsPath + "\\" + SettingsFileInfo.ExtAppsFilesName;
|
||||
#if !PORTABLE
|
||||
var oldPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), GeneralAppInfo.ProductName, SettingsFileInfo.ExtAppsFilesName);
|
||||
#endif
|
||||
var newPath = Path.Combine(SettingsFileInfo.SettingsPath, SettingsFileInfo.ExtAppsFilesName);
|
||||
var xDom = new XmlDocument();
|
||||
if (File.Exists(newPath))
|
||||
{
|
||||
Logger.Instance.Info($"Loading External Apps from: {newPath}");
|
||||
xDom.Load(newPath);
|
||||
}
|
||||
#if !PORTABLE
|
||||
}
|
||||
else if (File.Exists(oldPath))
|
||||
{
|
||||
xDom.Load(oldPath);
|
||||
Logger.Instance.Info($"Loading External Apps from: {oldPath}");
|
||||
xDom.Load(oldPath);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Instance.Warn("Loading External Apps failed: Could not FIND file!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xDom.DocumentElement != null)
|
||||
foreach (XmlElement xEl in xDom.DocumentElement.ChildNodes)
|
||||
if (xDom.DocumentElement == null)
|
||||
{
|
||||
Logger.Instance.Warn("Loading External Apps failed: Could not LOAD file!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XmlElement xEl in xDom.DocumentElement.ChildNodes)
|
||||
{
|
||||
var extA = new ExternalTool
|
||||
{
|
||||
var extA = new ExternalTool
|
||||
{
|
||||
DisplayName = xEl.Attributes["DisplayName"].Value,
|
||||
FileName = xEl.Attributes["FileName"].Value,
|
||||
Arguments = xEl.Attributes["Arguments"].Value
|
||||
};
|
||||
DisplayName = xEl.Attributes["DisplayName"].Value,
|
||||
FileName = xEl.Attributes["FileName"].Value,
|
||||
Arguments = xEl.Attributes["Arguments"].Value
|
||||
};
|
||||
|
||||
if (xEl.HasAttribute("WaitForExit"))
|
||||
{
|
||||
extA.WaitForExit = bool.Parse(xEl.Attributes["WaitForExit"].Value);
|
||||
}
|
||||
|
||||
if (xEl.HasAttribute("TryToIntegrate"))
|
||||
{
|
||||
extA.TryIntegrate = bool.Parse(xEl.Attributes["TryToIntegrate"].Value);
|
||||
}
|
||||
|
||||
Runtime.ExternalTools.Add(extA);
|
||||
if (xEl.HasAttribute("WaitForExit"))
|
||||
{
|
||||
extA.WaitForExit = bool.Parse(xEl.Attributes["WaitForExit"].Value);
|
||||
}
|
||||
|
||||
if (xEl.HasAttribute("TryToIntegrate"))
|
||||
{
|
||||
extA.TryIntegrate = bool.Parse(xEl.Attributes["TryToIntegrate"].Value);
|
||||
}
|
||||
|
||||
Logger.Instance.Info($"Adding External App: {extA.DisplayName} {extA.FileName} {extA.Arguments}");
|
||||
Runtime.ExternalTools.Add(extA);
|
||||
}
|
||||
|
||||
_MainForm.SwitchToolBarText(Convert.ToBoolean(mRemoteNG.Settings.Default.ExtAppsTBShowText));
|
||||
|
||||
frmMain.Default.AddExternalToolsToToolBar();
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace mRemoteNG.Config.Settings
|
||||
}
|
||||
else
|
||||
{
|
||||
Startup.Instance.SetDefaultLayout();
|
||||
frmMain.Default.SetDefaultLayout();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -9,6 +9,7 @@ using mRemoteNG.Themes;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
|
||||
@@ -137,14 +138,14 @@ namespace mRemoteNG.Config.Settings
|
||||
private void SetKioskMode()
|
||||
{
|
||||
if (!mRemoteNG.Settings.Default.MainFormKiosk) return;
|
||||
MainForm.Fullscreen.Value = true;
|
||||
MainForm._fullscreen.Value = true;
|
||||
MainForm.mMenViewFullscreen.Checked = true;
|
||||
}
|
||||
|
||||
private static void SetShowSystemTrayIcon()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.ShowSystemTrayIcon)
|
||||
Runtime.NotificationAreaIcon = new Tools.Controls.NotificationAreaIcon();
|
||||
Runtime.NotificationAreaIcon = new NotificationAreaIcon();
|
||||
}
|
||||
|
||||
private static void SetPuttyPath()
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
mRemoteNG.Settings.Default.MainFormState = with1.WindowState;
|
||||
|
||||
if (with1.Fullscreen != null)
|
||||
if (with1._fullscreen != null)
|
||||
{
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1.Fullscreen.Value;
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1._fullscreen.Value;
|
||||
}
|
||||
|
||||
mRemoteNG.Settings.Default.FirstStart = false;
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace mRemoteNG.Connection
|
||||
private ProtocolICA.EncryptionStrength _icaEncryption;
|
||||
private bool _useConsoleSession;
|
||||
private ProtocolRDP.AuthenticationLevel _rdpAuthenticationLevel;
|
||||
private int _rdpMinutesToIdleTimeout;
|
||||
private bool _rdpAlertIdleTimeout;
|
||||
private string _loadBalanceInfo;
|
||||
private HTTPBase.RenderingEngine _renderingEngine;
|
||||
private bool _useCredSsp;
|
||||
@@ -225,6 +227,30 @@ namespace mRemoteNG.Connection
|
||||
set { SetField(ref _rdpAuthenticationLevel, value, "RDPAuthenticationLevel"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout")]
|
||||
public virtual int RDPMinutesToIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout); }
|
||||
set {
|
||||
if(value < 0) {
|
||||
value = 0;
|
||||
} else if(value > 240) {
|
||||
value = 240;
|
||||
}
|
||||
SetField(ref _rdpMinutesToIdleTimeout, value, "RDPMinutesToIdleTimeout");
|
||||
}
|
||||
}
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout")]
|
||||
public bool RDPAlertIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout); }
|
||||
set { SetField(ref _rdpAlertIdleTimeout, value, "RDPAlertIdleTimeout"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo")]
|
||||
|
||||
@@ -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:
|
||||
@@ -248,6 +252,8 @@ namespace mRemoteNG.Connection
|
||||
ICAEncryptionStrength = (ProtocolICA.EncryptionStrength) Enum.Parse(typeof(ProtocolICA.EncryptionStrength), Settings.Default.ConDefaultICAEncryptionStrength);
|
||||
UseConsoleSession = Settings.Default.ConDefaultUseConsoleSession;
|
||||
RDPAuthenticationLevel = (ProtocolRDP.AuthenticationLevel) Enum.Parse(typeof(ProtocolRDP.AuthenticationLevel), Settings.Default.ConDefaultRDPAuthenticationLevel);
|
||||
RDPMinutesToIdleTimeout = Settings.Default.ConDefaultRDPMinutesToIdleTimeout;
|
||||
RDPAlertIdleTimeout = Settings.Default.ConDefaultRDPAlertIdleTimeout;
|
||||
LoadBalanceInfo = Settings.Default.ConDefaultLoadBalanceInfo;
|
||||
RenderingEngine = (HTTPBase.RenderingEngine) Enum.Parse(typeof(HTTPBase.RenderingEngine), Settings.Default.ConDefaultRenderingEngine);
|
||||
UseCredSsp = Settings.Default.ConDefaultUseCredSsp;
|
||||
|
||||
@@ -83,9 +83,19 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameAuthenticationLevel"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionAuthenticationLevel"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set;}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPMinutesToIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPMinutesToIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPAlertIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))] public bool RDPAlertIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionLoadBalanceInfo"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool LoadBalanceInfo {get; set;}
|
||||
|
||||
@@ -12,14 +12,52 @@ using TabPage = Crownwood.Magic.Controls.TabPage;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public static class ConnectionInitiator
|
||||
public class ConnectionInitiator : IConnectionInitiator
|
||||
{
|
||||
public static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
public void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
{
|
||||
OpenConnection(containerInfo, force, null);
|
||||
}
|
||||
|
||||
private static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
public void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SwitchToOpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var interfaceControl = FindConnectionContainer(connectionInfo);
|
||||
if (interfaceControl == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)interfaceControl.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)interfaceControl.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)interfaceControl.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Private
|
||||
private void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
var children = containerInfo.Children;
|
||||
if (children.Count == 0) return;
|
||||
@@ -33,31 +71,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
private void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -104,7 +118,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,19 +129,6 @@ namespace mRemoteNG.Connection
|
||||
extA?.Start(connectionInfo);
|
||||
}
|
||||
|
||||
public static bool SwitchToOpenConnection(ConnectionInfo nCi)
|
||||
{
|
||||
var IC = FindConnectionContainer(nCi);
|
||||
if (IC == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)IC.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)IC.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)IC.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static InterfaceControl FindConnectionContainer(ConnectionInfo connectionInfo)
|
||||
{
|
||||
if (connectionInfo.OpenConnections.Count <= 0) return null;
|
||||
@@ -185,11 +186,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
Control connectionContainer = ((ConnectionWindow)connectionForm).AddConnectionTab(connectionInfo);
|
||||
|
||||
if (connectionInfo.Protocol == ProtocolType.IntApp)
|
||||
{
|
||||
if (Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon != null)
|
||||
((TabPage)connectionContainer).Icon = Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon;
|
||||
}
|
||||
if (connectionInfo.Protocol != ProtocolType.IntApp) return connectionContainer;
|
||||
|
||||
var extT = Runtime.GetExtAppByName(connectionInfo.ExtApp);
|
||||
|
||||
if(extT == null) return connectionContainer;
|
||||
|
||||
if (extT.Icon != null)
|
||||
((TabPage)connectionContainer).Icon = extT.Icon;
|
||||
|
||||
return connectionContainer;
|
||||
}
|
||||
|
||||
@@ -210,10 +215,9 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
newProtocol.InterfaceControl = new InterfaceControl(connectionContainer, newProtocol, connectionInfo);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Event handlers
|
||||
private static void Prot_Event_Disconnected(object sender, string disconnectedMessage)
|
||||
{
|
||||
try
|
||||
@@ -230,7 +234,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.strProtocolEventDisconnectFailed, ex.Message), true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strProtocolEventDisconnectFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +244,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
var Prot = (ProtocolBase)sender;
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strConnenctionCloseEvent, true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, Prot.InterfaceControl.Info.Hostname, Prot.InterfaceControl.Info.Protocol.ToString(), Environment.UserName));
|
||||
string connDetail;
|
||||
if (Prot.InterfaceControl.Info.Hostname == "" && Prot.InterfaceControl.Info.Protocol == ProtocolType.IntApp)
|
||||
connDetail = Prot.InterfaceControl.Info.ExtApp;
|
||||
else if (Prot.InterfaceControl.Info.Hostname != "")
|
||||
connDetail = Prot.InterfaceControl.Info.Hostname;
|
||||
else
|
||||
connDetail = "UNKNOWN";
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, connDetail, Prot.InterfaceControl.Info.Protocol, Environment.UserName));
|
||||
Prot.InterfaceControl.Info.OpenConnections.Remove(Prot);
|
||||
|
||||
if (Prot.InterfaceControl.Info.PostExtApp == "") return;
|
||||
@@ -249,7 +261,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnenctionCloseEventFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnenctionCloseEventFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,8 +285,9 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionEventConnectionFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionEventConnectionFailed, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
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 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];
|
||||
@@ -35,19 +42,27 @@ 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)
|
||||
{
|
||||
var propertyFromDestination = typeof(TDestination).GetProperty(propertyNameMutator(property.Name));
|
||||
var localValue = property.GetValue(Instance, null);
|
||||
|
||||
var descriptor = TypeDescriptor.GetProperties(Instance)[property.Name];
|
||||
var converter = descriptor.Converter;
|
||||
if (converter != null && converter.CanConvertFrom(localValue.GetType()))
|
||||
propertyFromDestination.SetValue(destinationInstance, converter.ConvertFrom(localValue), null);
|
||||
else
|
||||
propertyFromDestination.SetValue(destinationInstance, localValue, null);
|
||||
try
|
||||
{
|
||||
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);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector?.AddExceptionStackTrace($"Error saving default connectioninfo property {property.Name}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
15
mRemoteV1/Connection/IConnectionInitiator.cs
Normal file
15
mRemoteV1/Connection/IConnectionInitiator.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using mRemoteNG.Container;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public interface IConnectionInitiator
|
||||
{
|
||||
void OpenConnection(ConnectionInfo connectionInfo);
|
||||
|
||||
void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None);
|
||||
|
||||
void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force);
|
||||
|
||||
bool SwitchToOpenConnection(ConnectionInfo connectionInfo);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ namespace mRemoteNG.Connection.Protocol.Http
|
||||
WebBrowser objWebBrowser = wBrowser as WebBrowser;
|
||||
if (objWebBrowser == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
// This can only be set once the WebBrowser control is shown, it will throw a COM exception otherwise.
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace mRemoteNG.Connection.Protocol.ICA
|
||||
{
|
||||
if (((int)Force & (int)ConnectionInfo.Force.NoCredentials) == (int)ConnectionInfo.Force.NoCredentials)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
string _user = _Info.Username;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
@@ -20,41 +21,52 @@ namespace mRemoteNG.Connection.Protocol
|
||||
#region Public Methods
|
||||
public override bool Initialize()
|
||||
{
|
||||
if (InterfaceControl.Info != null)
|
||||
{
|
||||
_externalTool = Runtime.GetExtAppByName(Convert.ToString(InterfaceControl.Info.ExtApp));
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
}
|
||||
|
||||
return base.Initialize();
|
||||
if (InterfaceControl.Info == null) return base.Initialize();
|
||||
|
||||
_externalTool = Runtime.GetExtAppByName(InterfaceControl.Info.Name);
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
|
||||
return base.Initialize();
|
||||
}
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_externalTool.TryIntegrate == false)
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, $"Attempting to start: {_externalTool.DisplayName}", true);
|
||||
|
||||
if (_externalTool.TryIntegrate == false)
|
||||
{
|
||||
_externalTool.Start(InterfaceControl.Info);
|
||||
Close();
|
||||
return false;
|
||||
/* Don't call close here... There's nothing for the override to do in this case since
|
||||
* _process is not created in this scenario. When returning false, ProtocolBase.Close()
|
||||
* 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);
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalToolArgumentParser argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo);
|
||||
_process = new Process();
|
||||
|
||||
_process.StartInfo.UseShellExecute = true;
|
||||
_process.StartInfo.FileName = argParser.ParseArguments(_externalTool.FileName);
|
||||
_process.StartInfo.Arguments = argParser.ParseArguments(_externalTool.Arguments);
|
||||
|
||||
_process.EnableRaisingEvents = true;
|
||||
_process.Exited += ProcessExited;
|
||||
var argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo);
|
||||
_process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = argParser.ParseArguments(_externalTool.FileName),
|
||||
Arguments = argParser.ParseArguments(_externalTool.Arguments)
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
|
||||
_process.Exited += ProcessExited;
|
||||
|
||||
_process.Start();
|
||||
_process.WaitForInputIdle(Convert.ToInt32(Settings.Default.MaxPuttyWaitTime * 1000));
|
||||
|
||||
int startTicks = Environment.TickCount;
|
||||
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + (Settings.Default.MaxPuttyWaitTime * 1000))
|
||||
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
|
||||
|
||||
var startTicks = Environment.TickCount;
|
||||
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + Settings.Default.MaxPuttyWaitTime * 1000)
|
||||
{
|
||||
_process.Refresh();
|
||||
if (_process.MainWindowTitle != "Default IME")
|
||||
@@ -68,10 +80,10 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
|
||||
NativeMethods.SetParent(_handle, InterfaceControl.Handle);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppHandle, _handle.ToString()), true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppTitle, _process.MainWindowTitle), true);
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, string.Format(Language.strIntAppParentHandle, InterfaceControl.Parent.Handle.ToString()), 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();
|
||||
@@ -88,15 +100,12 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ConnectionWindow.InTabDrag)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if (ConnectionWindow.InTabDrag) return;
|
||||
NativeMethods.SetForegroundWindow(_handle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppFocusFailed, ex: ex, logOnly: true);
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppFocusFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,45 +113,49 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InterfaceControl.Size == Size.Empty)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
NativeMethods.MoveWindow(_handle, Convert.ToInt32(-SystemInformation.FrameBorderSize.Width), Convert.ToInt32(-(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height)), InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width * 2), InterfaceControl.Height + SystemInformation.CaptionHeight + (SystemInformation.FrameBorderSize.Height * 2), true);
|
||||
if (InterfaceControl.Size == Size.Empty) return;
|
||||
NativeMethods.MoveWindow(_handle, -SystemInformation.FrameBorderSize.Width, -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height), InterfaceControl.Width + SystemInformation.FrameBorderSize.Width * 2, InterfaceControl.Height + SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height * 2, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppResizeFailed, ex: ex, logOnly: true);
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppResizeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppKillFailed, ex: ex, logOnly: true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(message: Language.strIntAppDisposeFailed, ex: ex, logOnly: true);
|
||||
}
|
||||
|
||||
base.Close();
|
||||
/* only attempt this if we have a valid process object
|
||||
* Non-integated tools will still call base.Close() and don't have a valid process object.
|
||||
* See Connect() above... This just muddies up the log.
|
||||
*/
|
||||
if (_process != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppKillFailed, ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppDisposeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
base.Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace mRemoteNG.Connection.Protocol
|
||||
|
||||
#region Public Properties
|
||||
#region Control
|
||||
public string Name { get; set; }
|
||||
private string Name { get; }
|
||||
|
||||
protected UI.Window.ConnectionWindow ConnectionWindow
|
||||
{
|
||||
get { return _connectionWindow; }
|
||||
set
|
||||
private set
|
||||
{
|
||||
_connectionWindow = value;
|
||||
_connectionWindow.ResizeBegin += ResizeBegin;
|
||||
@@ -61,7 +61,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public ProtocolBase()
|
||||
protected ProtocolBase()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t focus Control (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't focus Control (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t SetProps (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't SetProps (Connection.Protocol.Base)", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
Thread t = new Thread(CloseBG);
|
||||
var t = new Thread(CloseBG);
|
||||
t.SetApartmentState(ApartmentState.STA);
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
@@ -153,31 +153,31 @@ namespace mRemoteNG.Connection.Protocol
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "Could not dispose control, probably form is already closed (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't dispose control, probably form is already closed (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (_interfaceControl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_interfaceControl.Parent == null) return;
|
||||
if (_interfaceControl.Parent.Tag != null)
|
||||
{
|
||||
SetTagToNothing();
|
||||
}
|
||||
|
||||
if (_interfaceControl == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_interfaceControl.Parent == null) return;
|
||||
|
||||
if (_interfaceControl.Parent.Tag != null)
|
||||
{
|
||||
SetTagToNothing();
|
||||
}
|
||||
|
||||
DisposeInterface();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "Could not set InterfaceControl.Parent.Tag or Dispose Interface, probably form is already closed (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
}
|
||||
}
|
||||
DisposeInterface();
|
||||
}
|
||||
catch (Exception 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.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn\'t Close InterfaceControl BG (Connection.Protocol.Base)" + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("Couldn't Close InterfaceControl BG (Connection.Protocol.Base)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (_interfaceControl.InvokeRequired)
|
||||
{
|
||||
DisposeInterfaceCB s = new DisposeInterfaceCB(DisposeInterface);
|
||||
var s = new DisposeInterfaceCB(DisposeInterface);
|
||||
_interfaceControl.Invoke(s);
|
||||
}
|
||||
else
|
||||
@@ -200,7 +200,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (_interfaceControl.Parent.InvokeRequired)
|
||||
{
|
||||
SetTagToNothingCB s = new SetTagToNothingCB(SetTagToNothing);
|
||||
var s = new SetTagToNothingCB(SetTagToNothing);
|
||||
_interfaceControl.Parent.Invoke(s);
|
||||
}
|
||||
else
|
||||
@@ -214,7 +214,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
if (Control.InvokeRequired)
|
||||
{
|
||||
DisposeControlCB s = new DisposeControlCB(DisposeControl);
|
||||
var s = new DisposeControlCB(DisposeControl);
|
||||
Control.Invoke(s);
|
||||
}
|
||||
else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user