Compare commits

..

139 Commits

Author SHA1 Message Date
David Sparer
3943b8753f split releases 2017-03-10 14:41:14 -07:00
David Sparer
9e26ea1866 bumped assembly version 2017-03-10 14:26:35 -07:00
David Sparer
8152a87514 bumped patch version 2017-03-10 14:20:23 -07:00
David Sparer
b28775c2c6 made sqlbulkcopy column-position independant 2017-03-10 14:18:55 -07:00
David Sparer
3eb96ef765 set changelog and bumped patch version 2017-03-10 11:40:20 -07:00
David Sparer
8805584cbe updated sql code
- added upgrade script to bring db version up to 2.6
- refactored db upgrade code to a new class
- resolved an issue with db column naming for one of the new features
- updated new sql db creation script
2017-03-10 11:13:26 -07:00
David Sparer
be5c66bd93 Merge pull request #438 from mRemoteNG/1_75_hotfixes
1.75 hotfix 1
2017-03-06 10:33:04 -07:00
David Sparer
5347e5a3aa implemented new versioning scheme. resolves #437 2017-03-06 10:27:25 -07:00
David Sparer
9b22254b6c update changelog 2017-03-06 10:24:41 -07:00
David Sparer
6a67e0ea8b resolved issue with export filter not being respected. resolves #427 2017-03-02 16:42:00 -07:00
David Sparer
7b118995ea updated changelog 2017-03-02 13:26:40 -07:00
David Sparer
35b4564644 turned off a feature of ObjectListView that was stealing focus from keepass autotype events. resolves #312 2017-03-02 13:02:51 -07:00
David Sparer
30df947365 resolved issue when clicking in connection tree white space #422 2017-03-02 08:55:10 -07:00
David Sparer
b1ec975612 Merge pull request #425 from mRemoteNG/1_75_release
1 75 release
2017-03-02 08:51:19 -07:00
David Sparer
1034e434c4 updated changelog with release date 2017-03-01 16:23:40 -07:00
David Sparer
f419bff545 #394 resolved bug where export flag would not get set on the exported connections file 2017-02-16 08:29:31 -07:00
Sean Kaim
69eec0135e Update to SHA512 file hashes 2017-02-15 15:21:18 -05:00
David Sparer
2849baf857 Merge branch '378_ssh_connection_launched_on_single_click' into v1_75_release_candidates 2017-01-30 11:37:10 -07:00
David Sparer
768fdcd0e4 using MouseClick events rather than the OLV CellClick events. this should resolve #378 2017-01-30 11:33:27 -07:00
David Sparer
9b38308ad1 set date for rc1 build in changelog 2017-01-27 15:28:36 -07:00
Sean Kaim
afcdf96e5c changelog / credits update 2017-01-27 17:13:50 -05:00
David Sparer
3e40b08525 Merge pull request #348 from countchappy/develop
RDP Minutes to Idle Timeout - users cant enter invalid timeout values
2017-01-27 14:58:05 -07:00
countchappy
237cf037be RDP Minutes to Idle Timeout - Update 5
Incorrect values entered in the Minutes to Idle Timout setting will be
corrected to fit in the range of 0-240, rather than be truncated.
2017-01-27 14:56:40 -05:00
Sean Kaim
2445c74638 code clean up and minor refactoring 2017-01-25 17:50:10 -05:00
Sean Kaim
6a69ed48a9 Merge pull request #372 from mRemoteNG/serialize_connectioninfo_id
Serialize connectioninfo ID
2017-01-25 17:01:29 -05:00
David Sparer
217693937f connectioninfo id is now serialized to the confCons file 2017-01-25 14:02:20 -07:00
Sean Kaim
22300577cf Merge pull request #371 from jcefoli/develop
Quick fix for #369 (Reset Layout Ignores Notification Pane)
2017-01-25 15:06:39 -05:00
Joe Cefoli
6a07f4e731 Quick fix for #369 2017-01-25 14:02:16 -05:00
David Sparer
63ace60dcc Merge pull request #367 from mRemoteNG/295_default_con_values_not_saved
resolved issue where saving default con properties would fail
2017-01-25 09:58:50 -07:00
David Sparer
601951582d resolved issue where saving default con properties would fail
enum, int, bool -> string was throwing an exception. now using a simpler strategy for type conversion
resolves #295
2017-01-25 09:54:54 -07:00
Sean Kaim
9250dde5b0 Merge pull request #364 from mRemoteNG/176_scheduled_updates
1.76 scheduled updates to 1.75
2017-01-24 20:04:47 -05:00
Sean Kaim
29ca72d8ca Change log update 2017-01-24 20:03:20 -05:00
Sean Kaim
87c89a0de5 reformat code 2017-01-24 19:55:18 -05:00
Sean Kaim
73f72e39d3 Fix incorrect cast & code clean up
Fixes #362
2017-01-24 19:49:22 -05:00
Sean Kaim
e00ba62606 Refactored Tools.Controls.cs
Fixes #363
2017-01-24 17:52:15 -05:00
Sean Kaim
48d53cecce Rename Tab dialog - populate original name
Fixes #258
2017-01-24 17:36:41 -05:00
David Sparer
e0fd81e938 resolved bug when clicking in blank space in the connection tree 2017-01-23 15:32:06 -07:00
Sean Kaim
04f6f4f9cf Make version selectable/copyable
fixes #360

Also update copyright year since it's 2017 now...
2017-01-23 12:59:29 -05:00
David Sparer
25d1e0a74d Merge pull request #352 from mRemoteNG/299_better_testing_of_connection_tree
Refactor connection tree to be more testable
2017-01-18 09:03:26 -07:00
David Sparer
cbd9d16e4c simplified the connection tree refresh method.
the complexity of trying to add refresh optimizations was causing bugs. i will need to find a new way of reducing flicker
2017-01-17 15:31:40 -07:00
David Sparer
cb708b3217 resolved bug where some context menu hot keys would not work after opening the menu on the root node 2017-01-17 13:45:25 -07:00
David Sparer
4e5a22a7e8 resolved a minor bug where creating a new node would screw up the selected node in the tree
We were trying to do multiselection when it is currently not supported by our implementation.
2017-01-17 09:47:00 -07:00
Sean Kaim
3722db93c6 Merge pull request #349 from jogleasonjr/patch-1
Fix typo in README.MD
2017-01-16 17:56:59 -05:00
John Gleason
b43331dc27 Fix typo in README.MD 2017-01-16 15:20:07 -06:00
countchappy
80c6ce81e1 RDP Minutes to Idle Timeout - Update 4
Added an option to alert if disconnected due to inactivity.
2017-01-16 15:14:27 -05:00
David Sparer
1a776359c4 added test for folder expander 2017-01-14 11:44:09 -07:00
David Sparer
113e4035e5 refactored the deletion confirmer to make it testable 2017-01-14 11:14:30 -07:00
David Sparer
a03095ab8e refactored the node deletion confirmer to be interface-based. this will lead to improved testability 2017-01-14 10:38:11 -07:00
David Sparer
d03f830622 added null test for the composite click handler 2017-01-14 10:36:54 -07:00
David Sparer
9b42dc9f10 Refactored some click handlers and created a test for it
During testing I realized that the double and single click handlers were exactly the same thing, so i combined them into the composite click handler.
2017-01-14 10:11:22 -07:00
David Sparer
fd7adf3c64 added some more tests 2017-01-13 17:43:06 -07:00
David Sparer
d0b7e72f15 Merge pull request #342 from countchappy/develop
RDP Optional Minutes to Idle Timeout
2017-01-13 17:05:25 -07:00
countchappy
5a61c6b7df RDP Minutes to Idle Timeout - Update 3.1 2017-01-13 18:49:39 -05:00
countchappy
c897eae04e RDP Minutes to Idle Timeout - Update 3
Fixed name and description not showing up in the config window.
2017-01-13 18:08:36 -05:00
countchappy
c33095cd0e RDP Minutes to Idle Timeout - Update 2.1
Fixed my goof!
2017-01-13 17:11:07 -05:00
David Sparer
05d8b7983a reorganized some test files and added tests for null args 2017-01-13 12:12:22 -07:00
countchappy
166d9f7133 RDP Minutes to Idle Timeout - Update 2
Added null conditional operator to prevent throwing a null reference
error for beta users.
2017-01-13 13:41:19 -05:00
David Sparer
2ce31f35cc more file organizing 2017-01-13 10:54:39 -07:00
David Sparer
ce5d0cefe3 organized some files 2017-01-13 10:41:28 -07:00
David Sparer
6cc668fe83 added more tests for connectiontree delegates 2017-01-12 15:30:30 -07:00
David Sparer
ac0aa8daf4 added a method to the IConnectionTree interface to make testing another class possible 2017-01-12 15:20:32 -07:00
David Sparer
16b094be44 we no longer need the extensions now that we are subclassing TreeListView 2017-01-12 15:16:55 -07:00
David Sparer
b3e6fd7b96 created test for another tree handler 2017-01-12 15:09:24 -07:00
David Sparer
893d5d92f3 made all relevant classes use IConnectionTree 2017-01-12 15:09:05 -07:00
David Sparer
77add0b39d added an interface for iconnectiontree. this kind of hacky and really just exists to make the tests work. this indicates we have some coupling on ConnectionTree that shouldn't be there.. 2017-01-12 15:08:12 -07:00
David Sparer
b4f8ab0a49 moved a call to settings further up in the abstraction level to make testing easier 2017-01-12 14:13:35 -07:00
David Sparer
1d46c44c21 added tests for another click handler 2017-01-12 13:57:44 -07:00
David Sparer
12da35f875 made the rest of the connectioninitiator functions non-static 2017-01-12 13:57:15 -07:00
David Sparer
8970a15d4e added tests for one of the click handlers 2017-01-12 13:33:12 -07:00
David Sparer
82217478d9 made one of the methods for the connectioninitiator non-static (they should eventually all be non-static).
This change was made to making testing easier (make connectioninitiator mockable)
2017-01-12 13:31:29 -07:00
David Sparer
4c792308bb moved all click-actions for the tree to separate classes to make them easily composable
this has the nice effect of also pushing any calls to the settings class outside the classes that are actualy doing work, making them much easier to test in isolation
2017-01-12 12:47:23 -07:00
David Sparer
978d94a2cd resolved issue with unit test. we could not select a tree object without that object being visible 2017-01-12 11:12:18 -07:00
David Sparer
b195d89b76 moved a few more functions closer to their call site 2017-01-12 11:02:11 -07:00
David Sparer
875888a341 moved a method closer to its call site 2017-01-12 10:51:05 -07:00
David Sparer
6631a13d20 cleanup 2017-01-12 10:31:50 -07:00
David Sparer
28728fe29f moved some connectiontree post setup actions into their own classes. post setup actions are now managed by a composite 2017-01-12 10:29:30 -07:00
David Sparer
aa954cbea9 minor cleanup 2017-01-12 09:24:59 -07:00
David Sparer
dae339f494 moved the image getter delegate code into its imagelist since the img names have to match up. seems like a better division of responsibility 2017-01-12 09:17:34 -07:00
David Sparer
5bcb59f876 moved the setup of the tree image list to its own class 2017-01-12 08:59:34 -07:00
David Sparer
9132592fd7 moved the setup of the name column to its own class 2017-01-12 08:58:52 -07:00
Sean Kaim
ca592fac77 update change log 2017-01-11 17:56:37 -05:00
Sean Kaim
ea657824c2 Streamlined non-integrated IntApp connections
This seems to fix #325
2017-01-11 17:49:37 -05:00
Sean Kaim
99e7072e27 code clean up
relates to #325
2017-01-11 17:01:08 -05:00
David Sparer
ad32f4a0a3 Merge branch 'develop' into 299_better_testing_of_connection_tree 2017-01-11 15:00:44 -07:00
David Sparer
b9cdd0996d moved click handling responsibility out of the connectiontreewindow and into the context menu class 2017-01-11 14:58:29 -07:00
Sean Kaim
e92a76f95b "return ;" annoyed me...
And I did a find and replace in the solution instead of the one file I
was working on... So I'm going with it...
2017-01-11 16:56:14 -05:00
countchappy
10d152342f RDP Minutes to Idle Timeout - Update 1
Fixed some language file stuff.
2017-01-11 16:44:53 -05:00
countchappy
7e4b0635b2 RDP Minutes To Idle Timeout
Allows users to configure a number of minutes until the session will
automatically disconnect if left idle.
2017-01-11 15:23:43 -05:00
Sean Kaim
eec17f10d5 update changelog 2017-01-10 10:54:03 -05:00
Sean Kaim
ac9d5dfa95 code clean up 2017-01-10 10:51:34 -05:00
Sean Kaim
4c2b3738c2 Don't attempt to connect to folders
Fixes #334
2017-01-10 10:46:34 -05:00
Sean Kaim
6f29183b45 code clean up and logging / exception handling 2017-01-09 11:32:04 -05:00
Sean Kaim
dd65c9c588 update changelog 2017-01-06 12:53:56 -05:00
Sean Kaim
cb8bb05627 Merge pull request #329 from mRemoteNG/release_channels
Add Release channels
2017-01-06 12:32:05 -05:00
David Sparer
256f6d8fdd extracted and renamed some methods 2017-01-06 10:15:33 -07:00
Sean Kaim
a88fdddecb allow all tests to pass regardless of build type 2017-01-06 11:58:00 -05:00
Sean Kaim
fd5e3e24df Run tests from local resources 2017-01-06 11:16:02 -05:00
Sean Kaim
244d27427d update some log messages 2017-01-05 14:30:24 -05:00
Sean Kaim
55c42a3cca Merge remote-tracking branch 'refs/remotes/origin/develop' into release_channels 2017-01-05 11:21:46 -05:00
Sean Kaim
3c9cfbdf92 log exception messages only 2017-01-05 11:13:43 -05:00
Sean Kaim
46dd58d26e External Tool/Connection - code clean up & logging
Relates to #325
2017-01-05 11:05:59 -05:00
Sean Kaim
051dd2e567 Add Beta and Dev tests 2017-01-04 11:15:51 -05:00
Sean Kaim
17ccf40082 re-add version check & adjust CPU target for tests
fixed compliler warning regarding architecture mismatch.
2017-01-04 10:47:23 -05:00
Sean Kaim
0f2b61694d Merge remote-tracking branch 'refs/remotes/origin/develop' into release_channels 2017-01-04 09:15:22 -05:00
Sean Kaim
0aed66df47 fix build & test failure 2017-01-03 18:17:03 -05:00
Sean Kaim
94a6e9a886 code clean up around startup / frmMain
Slightly related to #298
2016-12-22 10:01:20 -05:00
Sean Kaim
355f48b6ba We want only Valid info! 2016-12-16 17:29:03 -05:00
Sean Kaim
d1a6526c22 Added functional UpdateStableChannel test
It's working! It's working!
2016-12-16 17:27:57 -05:00
Sean Kaim
975a308647 reworking code to better test & code cleanup 2016-12-15 17:44:55 -05:00
Sean Kaim
5138eaeb68 Merge remote-tracking branch 'refs/remotes/origin/develop' into release_channels 2016-12-15 15:02:30 -05:00
David Sparer
45dfaa1b21 removed unused code 2016-12-13 13:11:50 -07:00
David Sparer
715f92f3d5 removed unnecessary code 2016-12-13 13:07:52 -07:00
Sean Kaim
8d5a765040 pass importSubOU option in to recursive calls
Fixes remaining problems reported in #211
2016-12-13 14:22:39 -05:00
Sean Kaim
34fa6b158b load the default domain when opening the form
Related to #311
2016-12-13 13:34:44 -05:00
David Sparer
78c1f6b8e3 Fixed bug where we could not drop between items (rearrange) 2016-12-13 10:28:38 -07:00
David Sparer
adccb91106 removed unnecessary code 2016-12-13 10:06:50 -07:00
David Sparer
1e213dfff7 resolved issue with deleting the last folder in the tree 2016-12-13 09:58:24 -07:00
David Sparer
d469fa1d40 Made the deletion confirmation functionality plugable to make testing easier 2016-12-13 09:51:18 -07:00
David Sparer
737db469ba Fixed test name 2016-12-13 09:27:32 -07:00
David Sparer
a44a33d508 minor cleanup 2016-12-13 09:16:05 -07:00
David Sparer
a518d41c78 updated connection tree window tests 2016-12-13 09:07:21 -07:00
David Sparer
d5360c6568 Completed splitting the connection tree from the connection tree window 2016-12-13 09:00:38 -07:00
Sean Kaim
d468107311 Load users default/current domain
Fixes #311

Caused by 97a0e2413e

Some code clean up as well...
2016-12-13 10:50:36 -05:00
Sean Kaim
3f65e1bfa0 add tests for update channels
Some code clean up as well...
2016-12-13 10:31:16 -05:00
David Sparer
a22758f5cd organized code into regions to help prepare for later refactoring 2016-12-09 12:57:26 -07:00
David Sparer
88b5b9d1e7 began moving connectiontree functions out of the code for the window and into its own class.
this will improve testability and reduce class complexity
2016-12-07 15:07:15 -07:00
Sean Kaim
e38f7c880e code clean up
Added some log messages for #298
2016-12-06 19:13:09 -05:00
David Sparer
6367b58994 began adding unit tests for the connectiontree ui 2016-12-06 15:28:56 -07:00
David Sparer
5a54b5ee64 Merge pull request #292 from ForensicITGuy/develop
Added code and screenshots for Quick Connect help files
2016-12-06 08:36:00 -07:00
ForensicITGuy
002e41f418 Added Quick Connect screenshots into project. Modified folder name and HTML code to include spaces as observed in the other screenshot folders. Set to track content and copy if newer in output. 2016-12-06 01:04:52 -06:00
David Sparer
f7787c748a Added multiple build badges based on update channel to readme.md 2016-12-03 11:17:41 -07:00
David Sparer
f9b18b45a4 updated the jenkins build badge to point to the sanitized url. added a title to readme.md 2016-12-03 10:46:20 -07:00
David Sparer
8966f44272 resolved issue with Jenkins not being about the build PRs 2016-12-02 16:49:49 -07:00
Tony M Lambert
3dbcbae61f Added code for Quick Connect documentation
Added HTML code to document Quick Connect functionality
2016-12-02 15:49:04 -06:00
Sean Kaim
24508abe7a rename channels 2016-12-02 16:41:37 -05:00
Tony M Lambert
27f8f2542e Added screenshots for Quickconnect documentation 2016-12-02 15:25:05 -06:00
Sean Kaim
44ee3ceec8 User Selectable Release Channels
Final = Final
Beta = Beta & RC
Pre-Release = Alpha, Beta & RC
2016-12-02 14:57:49 -05:00
Sean Kaim
b08112aec0 Load Ext Tools - add logging
Relates to #291 & #236
2016-12-02 12:20:02 -05:00
Sean Kaim
9d2bbda2b9 ExtTools code clean up
Relates to #291 & #236
2016-12-02 12:11:46 -05:00
129 changed files with 3896 additions and 2176 deletions

View File

@@ -1,14 +1,89 @@
1.75 Beta 3 (2016-12-01):
1.75.7002 (2017-03-10):
Fixes:
------
#289: Install fails during update process (only affects v1.75 beta 1 - v1.75 beta 2)
#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:
@@ -21,7 +96,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
@@ -65,7 +140,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
@@ -73,7 +148,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
@@ -148,7 +223,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
@@ -289,7 +364,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.

View File

@@ -8,9 +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
Past Contributors
=================

6
Jenkinsfile vendored
View File

@@ -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"

View File

@@ -1,16 +1,20 @@
# Welcome to the mRemoteNG project!
[![Twitter Follow](https://img.shields.io/twitter/follow/mRemoteNG.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=mRemoteNG)
[![Join the chat at https://gitter.im/mRemoteNG/PublicChat/](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mRemoteNG/PublicChat)
[![PayPal](https://img.shields.io/badge/%24-PayPal-blue.svg)](https://www.paypal.me/DavidSparer)
[![Build Status](http://ec2-52-39-111-114.us-west-2.compute.amazonaws.com:8080/buildStatus/icon?job=mRemoteNG/mRemoteNG/develop)](http://ec2-52-39-111-114.us-west-2.compute.amazonaws.com:8080/job/mRemoteNG/job/mRemoteNG/job/develop/)
[![Issues In Progress](https://badge.waffle.io/mRemoteNG/mRemoteNG.png?label=In%20Progress&title=In%20Progress)](https://waffle.io/mRemoteNG/mRemoteNG)
[![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.74/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/529/badge)](https://bestpractices.coreinfrastructure.org/projects/529)
[![Issues In Progress](https://badge.waffle.io/mRemoteNG/mRemoteNG.png?label=In%20Progress&title=In%20Progress)](https://waffle.io/mRemoteNG/mRemoteNG)
| Update Channel | Build Status | Downloads |
| ---------------|--------------|-----------|
| Stable | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/master)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.74/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74) |
| Beta | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/beta_channel)](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/beta_channel/) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.75Beta3/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Beta3) |
| Development | [![Build Status](https://jenkins.mremoteng.org/buildStatus/icon?job=mRemoteNG/mRemoteNG/develop)](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.
@@ -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).
[![Developed with ReSharper](https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/develop/.github/icon_ReSharper.png)](https://www.jetbrains.com/resharper/)
[![Developed with ReSharper](https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/develop/.github/icon_ReSharper.png)](https://www.jetbrains.com/resharper/)

View File

@@ -18,7 +18,7 @@ Write-Host Version: $version
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash
@@ -38,5 +38,5 @@ Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash

View 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);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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; }
}
}
}

View File

@@ -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 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
///&lt;Connections Name=&quot;Connections&quot; Export=&quot;False&quot; Protected=&quot;95syzRuZ4mRxpNkZQzoyX8SDpQXLyMq3GncO8o4SyTBoYvn3TAWgn05ZEU2DrjkM&quot; ConfVersion=&quot;2.5&quot;&gt;
@@ -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 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;
///&lt;!-- ****************************************************************--&gt;
@@ -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);
}
}
}
}

View File

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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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));
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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));
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}

View 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);
}
}
}

View File

@@ -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,7 +31,7 @@
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -40,7 +40,7 @@
<OutputPath>bin\x86\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>
@@ -49,7 +49,7 @@
<DefineConstants>TRACE;PORTABLE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -101,12 +101,15 @@
</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\DataTableSerializerTests.cs" />
<Compile Include="Config\Serializers\PortScanDeserializerTests.cs" />
@@ -127,6 +130,7 @@
<Compile Include="Security\KeyDerivation\Pkcs5S2KeyGeneratorTests.cs" />
<Compile Include="Security\SecureStringExtensionsTests.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>

View 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>

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
#pragma warning disable 169
namespace mRemoteNG.App
{
@@ -326,6 +327,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>

View File

@@ -33,7 +33,7 @@ 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
@@ -42,8 +42,8 @@ namespace mRemoteNG.App
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;
}
@@ -288,7 +288,7 @@ namespace mRemoteNG.App
connectionsLoader.UseDatabase = Settings.Default.UseSQLServer;
ConnectionTreeModel = connectionsLoader.LoadConnections(false);
Windows.TreeForm.ConnectionTreeModel = ConnectionTreeModel;
Windows.TreeForm.ConnectionTree.ConnectionTreeModel = ConnectionTreeModel;
if (Settings.Default.UseSQLServer)
{
@@ -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.
@@ -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()

View File

@@ -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,31 @@ 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);
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 +72,17 @@ namespace mRemoteNG.App
LogCultureData();
}
private void LogSystemData()
private static void LogSystemData()
{
string osData = GetOperatingSystemData();
string architecture = GetArchitectureData();
var osData = GetOperatingSystemData();
var architecture = GetArchitectureData();
Logger.Instance.InfoFormat(string.Join(" ", Array.FindAll(new[] { osData, architecture }, s => !string.IsNullOrEmpty(Convert.ToString(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 +97,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 +111,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 +130,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 +140,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 +176,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 +190,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 +204,7 @@ namespace mRemoteNG.App
}
if (e.Error != null)
{
throw (e.Error);
throw e.Error;
}
if (_appUpdate.IsUpdateAvailable())
@@ -240,13 +219,13 @@ namespace mRemoteNG.App
}
private void ParseCommandLineArgs()
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 +235,7 @@ namespace mRemoteNG.App
ConsParam = "c";
}
string ResetPosParam = "";
var ResetPosParam = "";
if (cmd["resetpos"] != null)
{
ResetPosParam = "resetpos";
@@ -266,7 +245,7 @@ namespace mRemoteNG.App
ResetPosParam = "rp";
}
string ResetPanelsParam = "";
var ResetPanelsParam = "";
if (cmd["resetpanels"] != null)
{
ResetPanelsParam = "resetpanels";
@@ -276,7 +255,7 @@ namespace mRemoteNG.App
ResetPanelsParam = "rpnl";
}
string ResetToolbarsParam = "";
var ResetToolbarsParam = "";
if (cmd["resettoolbar"] != null)
{
ResetToolbarsParam = "resettoolbar";
@@ -293,7 +272,7 @@ namespace mRemoteNG.App
ResetToolbarsParam = "rtbr";
}
string NoReconnectParam = "";
var NoReconnectParam = "";
if (cmd["noreconnect"] != null)
{
NoReconnectParam = "noreconnect";
@@ -313,7 +292,7 @@ namespace mRemoteNG.App
Settings.Default.CustomConsPath = GeneralAppInfo.HomePath + "\\" + cmd[ConsParam];
return;
}
else if (File.Exists(ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam]))
if (File.Exists(ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam]))
{
Settings.Default.LoadConsFromCustomLocation = true;
Settings.Default.CustomConsPath = ConnectionsFileInfo.DefaultConnectionsPath + "\\" + cmd[ConsParam];

View File

@@ -9,116 +9,120 @@ 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(), "msi"));
#else
@@ -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
}
}

View File

@@ -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;
}
}
}

View File

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

View File

@@ -85,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();

View File

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

View File

@@ -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))
{

View File

@@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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)

View File

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

View File

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

View File

@@ -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();

View File

@@ -48,7 +48,7 @@ namespace mRemoteNG.Config.Settings
}
else
{
Startup.Instance.SetDefaultLayout();
frmMain.Default.SetDefaultLayout();
}
}
catch (Exception ex)

View File

@@ -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()

View File

@@ -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;

View File

@@ -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")]

View File

@@ -248,6 +248,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;

View File

@@ -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;}

View File

@@ -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
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using mRemoteNG.App;
namespace mRemoteNG.Connection
@@ -39,15 +40,17 @@ namespace mRemoteNG.Connection
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);
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);
}
}
}
}

View 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);
}
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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.ExtApp);
_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));
_process.WaitForInputIdle(Settings.Default.MaxPuttyWaitTime * 1000);
int startTicks = Environment.TickCount;
while (_handle.ToInt32() == 0 & Environment.TickCount < startTicks + (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

View File

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

View File

@@ -30,6 +30,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
private ConnectionInfo _connectionInfo;
private bool _loginComplete;
private bool _redirectKeys;
private bool _alertOnIdleDisconnect;
#endregion
#region Properties
@@ -129,9 +130,12 @@ namespace mRemoteNG.Connection.Protocol.RDP
SetCredentials();
SetResolution();
_rdpClient.FullScreenTitle = _connectionInfo.Name;
//not user changeable
_rdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
_alertOnIdleDisconnect = _connectionInfo.RDPAlertIdleTimeout;
_rdpClient.AdvancedSettings2.MinutesToIdleTimeout = _connectionInfo.RDPMinutesToIdleTimeout;
//not user changeable
_rdpClient.AdvancedSettings2.GrabFocusOnConnect = true;
_rdpClient.AdvancedSettings3.EnableAutoReconnect = true;
_rdpClient.AdvancedSettings3.MaxReconnectAttempts = Settings.Default.RdpReconnectionCount;
_rdpClient.AdvancedSettings2.keepAliveInterval = 60000; //in milliseconds (10,000 = 10 seconds)
@@ -176,8 +180,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
{
_loginComplete = false;
SetEventHandlers();
try
try
{
_rdpClient.Connect();
base.Connect();
@@ -616,7 +620,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
_rdpClient.OnFatalError += RDPEvent_OnFatalError;
_rdpClient.OnDisconnected += RDPEvent_OnDisconnected;
_rdpClient.OnLeaveFullScreenMode += RDPEvent_OnLeaveFullscreenMode;
}
_rdpClient.OnIdleTimeoutNotification += RDPEvent_OnIdleTimeoutNotification;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace(Language.strRdpSetEventHandlersFailed, ex);
@@ -625,7 +630,20 @@ namespace mRemoteNG.Connection.Protocol.RDP
#endregion
#region Private Events & Handlers
private void RDPEvent_OnFatalError(int errorCode)
private void RDPEvent_OnIdleTimeoutNotification()
{
Close(); //Simply close the RDP Session if the idle timeout has been triggered.
if (_alertOnIdleDisconnect)
{
string message = "The " + _connectionInfo.Name + " session was disconnected due to inactivity";
const string caption = "Session Disconnected";
MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void RDPEvent_OnFatalError(int errorCode)
{
Event_ErrorOccured(this, Convert.ToString(errorCode));
}

View File

@@ -75,7 +75,7 @@ namespace mRemoteNG.Connection
var puttyProcess = new PuttyProcessController();
if (!puttyProcess.Start())
{
return ;
return;
}
if (puttyProcess.SelectListBoxItem(PuttySession))
{

View File

@@ -116,7 +116,7 @@ namespace mRemoteNG.Messages
return lvItem;
}
public void AddExceptionMessage(string message, Exception ex, MessageClass msgClass = MessageClass.ErrorMsg, bool logOnly = false)
public void AddExceptionMessage(string message, Exception ex, MessageClass msgClass = MessageClass.ErrorMsg, bool logOnly = true)
{
AddMessage(msgClass, message + Environment.NewLine + Tools.MiscTools.GetExceptionMessageRecursive(ex), logOnly);
}
@@ -186,7 +186,7 @@ namespace mRemoteNG.Messages
}
}
delegate void AddToListCB(ListViewItem lvItem);
private delegate void AddToListCB(ListViewItem lvItem);
private void AddToList(ListViewItem lvItem)
{
if (MCForm.lvErrorCollector.InvokeRequired)

View File

@@ -14,7 +14,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Multi-protocol remote connections manager")]
[assembly: AssemblyCompany("")]
[assembly:AssemblyProduct("mRemoteNG")]
[assembly: AssemblyCopyright("Copyright © 2016 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly: AssemblyCopyright("Copyright © 2017 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly:AssemblyTrademark("")]
[assembly:ComVisible(false)]
@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.75.*")]
[assembly: AssemblyVersion("1.75.7002.*")]
[assembly:NeutralResourcesLanguageAttribute("en")]

View File

@@ -2099,13 +2099,16 @@ namespace mRemoteNG {
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("release")]
public string UpdateChannel {
get {
return ((string)(this["UpdateChannel"]));
}
set {
this["UpdateChannel"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
@@ -2347,5 +2350,53 @@ namespace mRemoteNG {
this["InhDefaultSoundQuality"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int ConDefaultRDPMinutesToIdleTimeout {
get {
return ((int)(this["ConDefaultRDPMinutesToIdleTimeout"]));
}
set {
this["ConDefaultRDPMinutesToIdleTimeout"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool InhDefaultRDPMinutesToIdleTimeout {
get {
return ((bool)(this["InhDefaultRDPMinutesToIdleTimeout"]));
}
set {
this["InhDefaultRDPMinutesToIdleTimeout"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool ConDefaultRDPAlertIdleTimeout {
get {
return ((bool)(this["ConDefaultRDPAlertIdleTimeout"]));
}
set {
this["ConDefaultRDPAlertIdleTimeout"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool InhDefaultRDPAlertIdleTimeout {
get {
return ((bool)(this["InhDefaultRDPAlertIdleTimeout"]));
}
set {
this["InhDefaultRDPAlertIdleTimeout"] = value;
}
}
}
}

View File

@@ -521,7 +521,7 @@
<Setting Name="IdentifyQuickConnectTabs" Roaming="true" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="UpdateChannel" Type="System.String" Scope="Application">
<Setting Name="UpdateChannel" Type="System.String" Scope="User">
<Value Profile="(Default)">release</Value>
</Setting>
<Setting Name="ThemeName" Type="System.String" Scope="User">
@@ -584,5 +584,17 @@
<Setting Name="InhDefaultSoundQuality" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="ConDefaultRDPMinutesToIdleTimeout" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="InhDefaultRDPMinutesToIdleTimeout" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="ConDefaultRDPAlertIdleTimeout" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="InhDefaultRDPAlertIdleTimeout" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -1,13 +1,60 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Quick Connect</title>
<link href="Main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>
Sorry, not yet...</p>
</body>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Quick Connect</title>
<link href="Main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>
The Quick Connect functionality of mRemoteNG allows you to quickly connect to a remote host using a variety of network protocols.
</p>
<p class="heading1">
Use Cases
</p>
<p>
The primary use case for Quick Connect is to connect to remote hosts when you already remember the DNS hostname/IP address and the appropriate protocol for the connection.
<br />
<br />
An additional use case is to connect to remote hosts saved as a connection quickly.
</p>
<p class="heading1">
Prerequisites
</p>
<ul>
<li>Knowledge of a DNS host name or IP address</li>
<li>Knowledge of an appropriate protocol to communicate with remote host</li>
</ul>
<p> OR </p>
<ul>
<li>A predefined mRemoteNG connection</li>
</ul>
<p class="heading1">
Using QuickConnect
</p>
<p>
To use Quick Connect, ensure the Quick Connect toolbar is enabled by selecting <b>View</b> and then <b>Quick Connect Toolbar</b>.
<br />
Next, input a DNS host name or IP address into the box labeled "Connect". This box will also save previous entries during your session.
<br />
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/01.png" />
<br />
<br />
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/02.png" />
<br />
<br />
Select the appropriate network protocol by clicking the arrow next to the Connect box.
<br />
<img alt="Quick Connect Toolbar" src="Screenshots/Quick Connect/03.png" />
<br />
<br />
If you wish to use an existing connection, select the globe icon next to the protocol button and select the appropriate connection.
</p>
</body>
</html>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -4117,6 +4117,24 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Select whether to receive an alert after the RDP session disconnects due to inactivity.
/// </summary>
internal static string strPropertyDescriptionRDPAlertIdleTimeout {
get {
return ResourceManager.GetString("strPropertyDescriptionRDPAlertIdleTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The number of minutes for the RDP session to sit idle before automatically disconnecting (for no limit use 0).
/// </summary>
internal static string strPropertyDescriptionRDPMinutesToIdleTimeout {
get {
return ResourceManager.GetString("strPropertyDescriptionRDPMinutesToIdleTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select whether local disk drives should be shown on the remote host..
/// </summary>
@@ -4603,6 +4621,24 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Alert on Idle Disconnect.
/// </summary>
internal static string strPropertyNameRDPAlertIdleTimeout {
get {
return ResourceManager.GetString("strPropertyNameRDPAlertIdleTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Minutes to Idle.
/// </summary>
internal static string strPropertyNameRDPMinutesToIdleTimeout {
get {
return ResourceManager.GetString("strPropertyNameRDPMinutesToIdleTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Disk Drives.
/// </summary>

View File

@@ -2421,4 +2421,16 @@ mRemoteNG will now quit and begin with the installation.</value>
<data name="strDownloadPortable" xml:space="preserve">
<value>Download</value>
</data>
<data name="strPropertyDescriptionRDPMinutesToIdleTimeout" xml:space="preserve">
<value>The number of minutes for the RDP session to sit idle before automatically disconnecting (for no limit use 0)</value>
</data>
<data name="strPropertyNameRDPMinutesToIdleTimeout" xml:space="preserve">
<value>Minutes to Idle</value>
</data>
<data name="strPropertyDescriptionRDPAlertIdleTimeout" xml:space="preserve">
<value>Select whether to receive an alert after the RDP session disconnects due to inactivity</value>
</data>
<data name="strPropertyNameRDPAlertIdleTimeout" xml:space="preserve">
<value>Alert on Idle Disconnect</value>
</data>
</root>

View File

@@ -34,6 +34,7 @@
<xs:attribute name="Descr" type="xs:string" use="required" />
<xs:attribute name="Icon" type="xs:string" use="required" />
<xs:attribute name="Panel" type="xs:string" use="required" />
<xs:attribute name="Id" type="xs:string" use="required" />
<xs:attribute name="Username" type="xs:string" use="required" />
<xs:attribute name="Domain" type="xs:string" use="required" />
<xs:attribute name="Password" type="xs:string" use="required" />
@@ -46,6 +47,8 @@
<xs:attribute name="RenderingEngine" type="xs:string" use="required" />
<xs:attribute name="ICAEncryptionStrength" type="xs:string" use="required" />
<xs:attribute name="RDPAuthenticationLevel" type="xs:string" use="required" />
<xs:attribute name="RDPMinutesToIdleTimeout" type="xs:int" use="required" />
<xs:attribute name="RDPAlertIdleTimeout" type="xs:boolean" use="required" />
<xs:attribute name="LoadBalanceInfo" type="xs:string" use="required" />
<xs:attribute name="Colors" type="xs:string" use="required" />
<xs:attribute name="Resolution" type="xs:string" use="required" />
@@ -114,6 +117,8 @@
<xs:attribute name="InheritUsername" type="xs:boolean" use="optional" />
<xs:attribute name="InheritICAEncryptionStrength" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDPAuthenticationLevel" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDPMinutesToIdleTimeout" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDPAlertIdleTimeout" type="xs:boolean" use="optional" />
<xs:attribute name="InheritLoadBalanceInfo" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPreExtApp" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPostExtApp" type="xs:boolean" use="optional" />

View File

@@ -117,7 +117,7 @@ namespace mRemoteNG.Themes
{
if (_name == value)
{
return ;
return;
}
_name = value;
NotifyPropertyChanged("Name");
@@ -135,7 +135,7 @@ namespace mRemoteNG.Themes
{
if (_windowBackgroundColor == value)
{
return ;
return;
}
_windowBackgroundColor = value;
NotifyPropertyChanged("WindowBackgroundColor");
@@ -152,7 +152,7 @@ namespace mRemoteNG.Themes
{
if (_menuBackgroundColor == value)
{
return ;
return;
}
_menuBackgroundColor = value;
NotifyPropertyChanged("MenuBackgroundColor");
@@ -169,7 +169,7 @@ namespace mRemoteNG.Themes
{
if (_menuTextColor == value)
{
return ;
return;
}
_menuTextColor = value;
NotifyPropertyChanged("MenuTextColor");
@@ -187,7 +187,7 @@ namespace mRemoteNG.Themes
{
if (_toolbarBackgroundColor == value || value.A < 255)
{
return ;
return;
}
_toolbarBackgroundColor = value;
NotifyPropertyChanged("ToolbarBackgroundColor");
@@ -204,7 +204,7 @@ namespace mRemoteNG.Themes
{
if (_toolbarTextColor == value)
{
return ;
return;
}
_toolbarTextColor = value;
NotifyPropertyChanged("ToolbarTextColor");
@@ -223,7 +223,7 @@ namespace mRemoteNG.Themes
{
if (_connectionsPanelBackgroundColor == value || value.A < 255)
{
return ;
return;
}
_connectionsPanelBackgroundColor = value;
NotifyPropertyChanged("ConnectionsPanelBackgroundColor");
@@ -240,7 +240,7 @@ namespace mRemoteNG.Themes
{
if (_connectionsPanelTextColor == value)
{
return ;
return;
}
_connectionsPanelTextColor = value;
NotifyPropertyChanged("ConnectionsPanelTextColor");
@@ -260,7 +260,7 @@ namespace mRemoteNG.Themes
{
if (_connectionsPanelTreeLineColor == value)
{
return ;
return;
}
_connectionsPanelTreeLineColor = value;
NotifyPropertyChanged("ConnectionsPanelTreeLineColor");
@@ -280,7 +280,7 @@ namespace mRemoteNG.Themes
{
if (_searchBoxBackgroundColor == value || value.A < 255)
{
return ;
return;
}
_searchBoxBackgroundColor = value;
NotifyPropertyChanged("SearchBoxBackgroundColor");
@@ -300,7 +300,7 @@ namespace mRemoteNG.Themes
{
if (_searchBoxTextPromptColor == value)
{
return ;
return;
}
_searchBoxTextPromptColor = value;
NotifyPropertyChanged("SearchBoxTextPromptColor");
@@ -320,7 +320,7 @@ namespace mRemoteNG.Themes
{
if (_searchBoxTextColor == value)
{
return ;
return;
}
_searchBoxTextColor = value;
NotifyPropertyChanged("SearchBoxTextColor");
@@ -342,7 +342,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelBackgroundColor == value || value.A < 255)
{
return ;
return;
}
_configPanelBackgroundColor = value;
NotifyPropertyChanged("ConfigPanelBackgroundColor");
@@ -362,7 +362,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelTextColor == value)
{
return ;
return;
}
_configPanelTextColor = value;
NotifyPropertyChanged("ConfigPanelTextColor");
@@ -382,7 +382,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelCategoryTextColor == value)
{
return ;
return;
}
_configPanelCategoryTextColor = value;
NotifyPropertyChanged("ConfigPanelCategoryTextColor");
@@ -402,7 +402,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelHelpBackgroundColor == value || value.A < 255)
{
return ;
return;
}
_configPanelHelpBackgroundColor = value;
NotifyPropertyChanged("ConfigPanelHelpBackgroundColor");
@@ -422,7 +422,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelHelpTextColor == value)
{
return ;
return;
}
_configPanelHelpTextColor = value;
NotifyPropertyChanged("ConfigPanelHelpTextColor");
@@ -442,7 +442,7 @@ namespace mRemoteNG.Themes
{
if (_configPanelGridLineColor == value)
{
return ;
return;
}
_configPanelGridLineColor = value;
NotifyPropertyChanged("ConfigPanelGridLineColor");

View File

@@ -81,7 +81,7 @@ namespace mRemoteNG.Themes
{
if (e.PropertyName == "Name")
{
return ;
return;
}
ThemeChangedEvent?.Invoke();
}

View File

@@ -11,6 +11,7 @@ namespace mRemoteNG.Tools
{
public class ExternalTool
{
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
#region Public Properties
public string DisplayName { get; set; }
public string FileName { get; set; }
@@ -57,7 +58,7 @@ namespace mRemoteNG.Tools
private void StartExternalProcess()
{
Process process = new Process();
var process = new Process();
SetProcessProperties(process, ConnectionInfo);
process.Start();
@@ -69,7 +70,7 @@ namespace mRemoteNG.Tools
private void SetProcessProperties(Process process, ConnectionInfo startConnectionInfo)
{
ExternalToolArgumentParser argParser = new ExternalToolArgumentParser(startConnectionInfo);
var argParser = new ExternalToolArgumentParser(startConnectionInfo);
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = argParser.ParseArguments(FileName);
process.StartInfo.Arguments = argParser.ParseArguments(Arguments);
@@ -79,18 +80,18 @@ namespace mRemoteNG.Tools
{
try
{
ConnectionInfo newConnectionInfo = BuildConnectionInfoForIntegratedApp();
ConnectionInitiator.OpenConnection(newConnectionInfo);
var newConnectionInfo = BuildConnectionInfoForIntegratedApp();
_connectionInitiator.OpenConnection(newConnectionInfo);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage(message: "ExternalApp.StartIntegrated() failed.", ex: ex, logOnly: true);
Runtime.MessageCollector.AddExceptionMessage("ExternalApp.StartIntegrated() failed.", ex);
}
}
private ConnectionInfo BuildConnectionInfoForIntegratedApp()
{
ConnectionInfo newConnectionInfo = GetAppropriateInstanceOfConnectionInfo();
var newConnectionInfo = GetAppropriateInstanceOfConnectionInfo();
SetConnectionInfoFields(newConnectionInfo);
return newConnectionInfo;
}

View File

@@ -14,7 +14,7 @@ using static System.String;
namespace mRemoteNG.Tools
{
public class MiscTools
public static class MiscTools
{
public static Icon GetIconFromFile(string FileName)
{
@@ -112,7 +112,7 @@ namespace mRemoteNG.Tools
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, "Taking Screenshot failed" + Environment.NewLine + ex.Message, true);
Runtime.MessageCollector.AddExceptionStackTrace("Taking Screenshot failed", ex);
}
return null;
@@ -120,7 +120,7 @@ namespace mRemoteNG.Tools
public class EnumTypeConverter : EnumConverter
{
private Type _enumType;
private readonly Type _enumType;
public EnumTypeConverter(Type type) : base(type)
{
@@ -135,8 +135,8 @@ namespace mRemoteNG.Tools
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
{
if (value == null) return null;
var fi = _enumType.GetField(Enum.GetName(_enumType, value: value));
var dna = (DescriptionAttribute) (Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute)));
var fi = _enumType.GetField(Enum.GetName(_enumType, value));
var dna = (DescriptionAttribute) Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return dna != null ? dna.Description : value.ToString();
}
@@ -150,9 +150,9 @@ namespace mRemoteNG.Tools
{
foreach (var fi in _enumType.GetFields())
{
var dna = (DescriptionAttribute) (Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute)));
var dna = (DescriptionAttribute) Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
if ((dna != null) && ((string) value == dna.Description))
if (dna != null && (string) value == dna.Description)
{
return Enum.Parse(_enumType, fi.Name);
}
@@ -167,12 +167,7 @@ namespace mRemoteNG.Tools
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
@@ -193,7 +188,7 @@ namespace mRemoteNG.Tools
return false;
}
throw (new Exception("Values must be \"Yes\" or \"No\""));
throw new Exception("Values must be \"Yes\" or \"No\"");
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
@@ -220,63 +215,5 @@ namespace mRemoteNG.Tools
return svc;
}
}
public class Fullscreen
{
public Fullscreen(Form handledForm)
{
_handledForm = handledForm;
}
private readonly Form _handledForm;
private FormWindowState _savedWindowState;
private FormBorderStyle _savedBorderStyle;
private Rectangle _savedBounds;
private bool _value;
public bool Value
{
get
{
return _value;
}
set
{
if (_value == value)
{
return ;
}
if (!_value)
{
EnterFullscreen();
}
else
{
ExitFullscreen();
}
_value = value;
}
}
private void EnterFullscreen()
{
_savedBorderStyle = _handledForm.FormBorderStyle;
_savedWindowState = _handledForm.WindowState;
_savedBounds = _handledForm.Bounds;
_handledForm.FormBorderStyle = FormBorderStyle.None;
if (_handledForm.WindowState == FormWindowState.Maximized)
{
_handledForm.WindowState = FormWindowState.Normal;
}
_handledForm.WindowState = FormWindowState.Maximized;
}
private void ExitFullscreen()
{
_handledForm.FormBorderStyle = _savedBorderStyle;
_handledForm.WindowState = _savedWindowState;
_handledForm.Bounds = _savedBounds;
}
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.UI.Forms;
namespace mRemoteNG.Tools
{
public class NotificationAreaIcon
{
private readonly NotifyIcon _nI;
private readonly ContextMenuStrip _cMen;
private readonly ToolStripMenuItem _cMenCons;
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
public bool Disposed { get; private set; }
public NotificationAreaIcon()
{
try
{
_cMenCons = new ToolStripMenuItem
{
Text = Language.strConnections,
Image = Resources.Root
};
var cMenSep1 = new ToolStripSeparator();
var cMenExit = new ToolStripMenuItem {Text = Language.strMenuExit};
cMenExit.Click += cMenExit_Click;
_cMen = new ContextMenuStrip
{
Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, Convert.ToByte(0)),
RenderMode = ToolStripRenderMode.Professional
};
_cMen.Items.AddRange(new ToolStripItem[] {_cMenCons, cMenSep1, cMenExit});
_nI = new NotifyIcon
{
Text = @"mRemoteNG",
BalloonTipText = @"mRemoteNG",
Icon = Resources.mRemote_Icon,
ContextMenuStrip = _cMen,
Visible = true
};
_nI.MouseClick += nI_MouseClick;
_nI.MouseDoubleClick += nI_MouseDoubleClick;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace("Creating new SysTrayIcon failed", ex);
}
}
public void Dispose()
{
try
{
_nI.Visible = false;
_nI.Dispose();
_cMen.Dispose();
Disposed = true;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace("Disposing SysTrayIcon failed", ex);
}
}
private void nI_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
_cMenCons.DropDownItems.Clear();
var menuItemsConverter = new ConnectionsTreeToMenuItemsConverter
{
MouseUpEventHandler = ConMenItem_MouseUp
};
// ReSharper disable once CoVariantArrayConversion
ToolStripItem[] rootMenuItems = menuItemsConverter.CreateToolStripDropDownItems(Runtime.ConnectionTreeModel).ToArray();
_cMenCons.DropDownItems.AddRange(rootMenuItems);
}
private static void nI_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (frmMain.Default.Visible)
HideForm();
else
ShowForm();
}
private static void ShowForm()
{
frmMain.Default.Show();
frmMain.Default.WindowState = frmMain.Default.PreviousWindowState;
if (Settings.Default.ShowSystemTrayIcon) return;
Runtime.NotificationAreaIcon.Dispose();
Runtime.NotificationAreaIcon = null;
}
private static void HideForm()
{
frmMain.Default.Hide();
frmMain.Default.PreviousWindowState = frmMain.Default.WindowState;
}
private void ConMenItem_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
if (!(((ToolStripMenuItem) sender).Tag is ConnectionInfo)) return;
if (frmMain.Default.Visible == false)
ShowForm();
_connectionInitiator.OpenConnection((ConnectionInfo) ((ToolStripMenuItem) sender).Tag);
}
private static void cMenExit_Click(object sender, EventArgs e)
{
Shutdown.Quit();
}
}
}

View File

@@ -83,7 +83,7 @@ namespace mRemoteNG.Tools
public void WaitForExit()
{
if (Process == null || Process.HasExited)
return ;
return;
Process.WaitForExit();
}
#endregion

View File

@@ -1,161 +0,0 @@
using System;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.UI.Forms;
namespace mRemoteNG.Tools
{
public class Controls
{
public class NotificationAreaIcon
{
private NotifyIcon _nI;
private ContextMenuStrip _cMen;
private ToolStripMenuItem _cMenCons;
public bool Disposed { get; set; }
public NotificationAreaIcon()
{
try
{
_cMenCons = new ToolStripMenuItem
{
Text = Language.strConnections,
Image = Resources.Root
};
var cMenSep1 = new ToolStripSeparator();
var cMenExit = new ToolStripMenuItem {Text = Language.strMenuExit};
cMenExit.Click += cMenExit_Click;
_cMen = new ContextMenuStrip
{
Font =
new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, Convert.ToByte(0)),
RenderMode = ToolStripRenderMode.Professional
};
_cMen.Items.AddRange(new ToolStripItem[] {_cMenCons, cMenSep1, cMenExit});
_nI = new NotifyIcon
{
Text = "mRemote",
BalloonTipText = "mRemote",
Icon = Resources.mRemote_Icon,
ContextMenuStrip = _cMen,
Visible = true
};
_nI.MouseClick += nI_MouseClick;
_nI.MouseDoubleClick += nI_MouseDoubleClick;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Creating new SysTrayIcon failed" + Environment.NewLine + ex.Message, true);
}
}
public void Dispose()
{
try
{
_nI.Visible = false;
_nI.Dispose();
_cMen.Dispose();
Disposed = true;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Disposing SysTrayIcon failed" + Environment.NewLine + ex.Message, true);
}
}
private void nI_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
_cMenCons.DropDownItems.Clear();
var menuItemsConverter = new ConnectionsTreeToMenuItemsConverter
{
MouseUpEventHandler = ConMenItem_MouseUp
};
ToolStripItem[] rootMenuItems = menuItemsConverter.CreateToolStripDropDownItems(Runtime.ConnectionTreeModel).ToArray();
_cMenCons.DropDownItems.AddRange(rootMenuItems);
}
private void nI_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (frmMain.Default.Visible)
{
HideForm();
}
else
{
ShowForm();
}
}
private void ShowForm()
{
frmMain.Default.Show();
frmMain.Default.WindowState = frmMain.Default.PreviousWindowState;
if (Settings.Default.ShowSystemTrayIcon) return;
Runtime.NotificationAreaIcon.Dispose();
Runtime.NotificationAreaIcon = null;
}
private void HideForm()
{
frmMain.Default.Hide();
frmMain.Default.PreviousWindowState = frmMain.Default.WindowState;
}
private void ConMenItem_MouseUp(Object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
if (!(((Control) sender).Tag is ConnectionInfo)) return;
if (frmMain.Default.Visible == false)
{
ShowForm();
}
ConnectionInitiator.OpenConnection((ConnectionInfo)((Control)sender).Tag);
}
private void cMenExit_Click(Object sender, EventArgs e)
{
Shutdown.Quit();
}
}
public static SaveFileDialog ConnectionsSaveAsDialog()
{
var saveFileDialog = new SaveFileDialog();
saveFileDialog.CheckPathExists = true;
saveFileDialog.InitialDirectory = App.Info.ConnectionsFileInfo.DefaultConnectionsPath;
saveFileDialog.FileName = App.Info.ConnectionsFileInfo.DefaultConnectionsFile;
saveFileDialog.OverwritePrompt = true;
saveFileDialog.Filter = Language.strFiltermRemoteXML + "|*.xml|" + Language.strFilterAll + "|*.*";
return saveFileDialog;
}
public static OpenFileDialog ConnectionsLoadDialog()
{
var lDlg = new OpenFileDialog
{
CheckFileExists = true,
InitialDirectory = App.Info.ConnectionsFileInfo.DefaultConnectionsPath,
Filter = Language.strFiltermRemoteXML + "|*.xml|" + Language.strFilterAll + "|*.*"
};
return lDlg;
}
}
}

View File

@@ -0,0 +1,11 @@

namespace mRemoteNG.Tree
{
public class AlwaysConfirmYes : IConfirm
{
public bool Confirm()
{
return true;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tree
{
public class ExpandNodeClickHandler : ITreeNodeClickHandler
{
private readonly IConnectionTree _connectionTree;
public ExpandNodeClickHandler(IConnectionTree connectionTree)
{
if (connectionTree == null)
throw new ArgumentNullException(nameof(connectionTree));
_connectionTree = connectionTree;
}
public void Execute(ConnectionInfo clickedNode)
{
var clickedNodeAsContainer = clickedNode as ContainerInfo;
if (clickedNodeAsContainer == null) return;
_connectionTree.ToggleExpansion(clickedNodeAsContainer);
}
}
}

View File

@@ -0,0 +1,10 @@
using mRemoteNG.Connection;
namespace mRemoteNG.Tree
{
public interface ITreeNodeClickHandler
{
void Execute(ConnectionInfo clickedNode);
}
}

View File

@@ -0,0 +1,26 @@
using System;
using mRemoteNG.Connection;
namespace mRemoteNG.Tree
{
public class OpenConnectionClickHandler : ITreeNodeClickHandler
{
private readonly IConnectionInitiator _connectionInitiator;
public OpenConnectionClickHandler(IConnectionInitiator connectionInitiator)
{
if (connectionInitiator == null)
throw new ArgumentNullException(nameof(connectionInitiator));
_connectionInitiator = connectionInitiator;
}
public void Execute(ConnectionInfo clickedNode)
{
if (clickedNode == null)
throw new ArgumentNullException(nameof(clickedNode));
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
_connectionInitiator.OpenConnection(clickedNode);
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using mRemoteNG.Connection;
namespace mRemoteNG.Tree
{
public class SwitchToConnectionClickHandler : ITreeNodeClickHandler
{
private readonly IConnectionInitiator _connectionInitiator;
public SwitchToConnectionClickHandler(IConnectionInitiator connectionInitiator)
{
if (connectionInitiator == null)
throw new ArgumentNullException(nameof(connectionInitiator));
_connectionInitiator = connectionInitiator;
}
public void Execute(ConnectionInfo clickedNode)
{
if (clickedNode == null)
throw new ArgumentNullException(nameof(clickedNode));
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
_connectionInitiator.SwitchToOpenConnection(clickedNode);
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using mRemoteNG.Connection;
namespace mRemoteNG.Tree
{
public class TreeNodeCompositeClickHandler : ITreeNodeClickHandler
{
public IEnumerable<ITreeNodeClickHandler> ClickHandlers { get; set; } = new ITreeNodeClickHandler[0];
public void Execute(ConnectionInfo clickedNode)
{
if (clickedNode == null)
throw new ArgumentNullException(nameof(clickedNode));
foreach (var handler in ClickHandlers)
{
handler.Execute(clickedNode);
}
}
}
}

View File

@@ -0,0 +1,7 @@
namespace mRemoteNG.Tree
{
public interface IConfirm
{
bool Confirm();
}
}

View File

@@ -1,24 +0,0 @@
using System.Windows.Forms;
using BrightIdeasSoftware;
namespace mRemoteNG.Tree
{
public static class ObjectListViewExtensions
{
public static void Invoke(this Control control, MethodInvoker action)
{
control.Invoke(action);
}
public static void InvokeExpand(this TreeListView control, object model)
{
control.Invoke(() => control.Expand(model));
}
public static void InvokeRebuildAll(this TreeListView control, bool preserveState)
{
control.Invoke(() => control.RebuildAll(preserveState));
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tree
{
public class PreviousSessionOpener : IConnectionTreeDelegate
{
private readonly IConnectionInitiator _connectionInitiator;
public PreviousSessionOpener(IConnectionInitiator connectionInitiator)
{
if (connectionInitiator == null)
throw new ArgumentNullException(nameof(connectionInitiator));
_connectionInitiator = connectionInitiator;
}
public void Execute(IConnectionTree connectionTree)
{
var connectionInfoList = connectionTree.GetRootConnectionNode().GetRecursiveChildList().Where(node => !(node is ContainerInfo));
var previouslyOpenedConnections = connectionInfoList.Where(item => item.PleaseConnect);
foreach (var connectionInfo in previouslyOpenedConnections)
{
_connectionInitiator.OpenConnection(connectionInfo);
}
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Linq;
using mRemoteNG.Container;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tree
{
public class PreviouslyOpenedFolderExpander : IConnectionTreeDelegate
{
public void Execute(IConnectionTree connectionTree)
{
var rootNode = connectionTree.GetRootConnectionNode();
var containerList = connectionTree.ConnectionTreeModel.GetRecursiveChildList(rootNode).OfType<ContainerInfo>();
var previouslyExpandedNodes = containerList.Where(container => container.IsExpanded);
connectionTree.ExpandedObjects = previouslyExpandedNodes;
connectionTree.InvokeRebuildAll(true);
}
}
}

View File

@@ -0,0 +1,14 @@
using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tree
{
public class RootNodeExpander : IConnectionTreeDelegate
{
public void Execute(IConnectionTree connectionTree)
{
var rootConnectionNode = connectionTree.GetRootConnectionNode();
connectionTree.InvokeExpand(rootConnectionNode);
}
}
}

Some files were not shown because too many files have changed in this diff Show More