Compare commits
200 Commits
v1.75Beta1
...
v1.75Hotfi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3943b8753f | ||
|
|
9e26ea1866 | ||
|
|
8152a87514 | ||
|
|
b28775c2c6 | ||
|
|
3eb96ef765 | ||
|
|
8805584cbe | ||
|
|
be5c66bd93 | ||
|
|
5347e5a3aa | ||
|
|
9b22254b6c | ||
|
|
6a67e0ea8b | ||
|
|
7b118995ea | ||
|
|
35b4564644 | ||
|
|
30df947365 | ||
|
|
b1ec975612 | ||
|
|
1034e434c4 | ||
|
|
f419bff545 | ||
|
|
69eec0135e | ||
|
|
2849baf857 | ||
|
|
768fdcd0e4 | ||
|
|
9b38308ad1 | ||
|
|
afcdf96e5c | ||
|
|
3e40b08525 | ||
|
|
237cf037be | ||
|
|
2445c74638 | ||
|
|
6a69ed48a9 | ||
|
|
217693937f | ||
|
|
22300577cf | ||
|
|
6a07f4e731 | ||
|
|
63ace60dcc | ||
|
|
601951582d | ||
|
|
9250dde5b0 | ||
|
|
29ca72d8ca | ||
|
|
87c89a0de5 | ||
|
|
73f72e39d3 | ||
|
|
e00ba62606 | ||
|
|
48d53cecce | ||
|
|
e0fd81e938 | ||
|
|
04f6f4f9cf | ||
|
|
25d1e0a74d | ||
|
|
cbd9d16e4c | ||
|
|
cb708b3217 | ||
|
|
4e5a22a7e8 | ||
|
|
3722db93c6 | ||
|
|
b43331dc27 | ||
|
|
80c6ce81e1 | ||
|
|
1a776359c4 | ||
|
|
113e4035e5 | ||
|
|
a03095ab8e | ||
|
|
d03f830622 | ||
|
|
9b42dc9f10 | ||
|
|
fd7adf3c64 | ||
|
|
d0b7e72f15 | ||
|
|
5a61c6b7df | ||
|
|
c897eae04e | ||
|
|
c33095cd0e | ||
|
|
05d8b7983a | ||
|
|
166d9f7133 | ||
|
|
2ce31f35cc | ||
|
|
ce5d0cefe3 | ||
|
|
6cc668fe83 | ||
|
|
ac0aa8daf4 | ||
|
|
16b094be44 | ||
|
|
b3e6fd7b96 | ||
|
|
893d5d92f3 | ||
|
|
77add0b39d | ||
|
|
b4f8ab0a49 | ||
|
|
1d46c44c21 | ||
|
|
12da35f875 | ||
|
|
8970a15d4e | ||
|
|
82217478d9 | ||
|
|
4c792308bb | ||
|
|
978d94a2cd | ||
|
|
b195d89b76 | ||
|
|
875888a341 | ||
|
|
6631a13d20 | ||
|
|
28728fe29f | ||
|
|
aa954cbea9 | ||
|
|
dae339f494 | ||
|
|
5bcb59f876 | ||
|
|
9132592fd7 | ||
|
|
ca592fac77 | ||
|
|
ea657824c2 | ||
|
|
99e7072e27 | ||
|
|
ad32f4a0a3 | ||
|
|
b9cdd0996d | ||
|
|
e92a76f95b | ||
|
|
10d152342f | ||
|
|
7e4b0635b2 | ||
|
|
eec17f10d5 | ||
|
|
ac9d5dfa95 | ||
|
|
4c2b3738c2 | ||
|
|
6f29183b45 | ||
|
|
dd65c9c588 | ||
|
|
cb8bb05627 | ||
|
|
256f6d8fdd | ||
|
|
a88fdddecb | ||
|
|
fd5e3e24df | ||
|
|
244d27427d | ||
|
|
55c42a3cca | ||
|
|
3c9cfbdf92 | ||
|
|
46dd58d26e | ||
|
|
051dd2e567 | ||
|
|
17ccf40082 | ||
|
|
0f2b61694d | ||
|
|
0aed66df47 | ||
|
|
94a6e9a886 | ||
|
|
355f48b6ba | ||
|
|
d1a6526c22 | ||
|
|
975a308647 | ||
|
|
5138eaeb68 | ||
|
|
45dfaa1b21 | ||
|
|
715f92f3d5 | ||
|
|
8d5a765040 | ||
|
|
34fa6b158b | ||
|
|
78c1f6b8e3 | ||
|
|
adccb91106 | ||
|
|
1e213dfff7 | ||
|
|
d469fa1d40 | ||
|
|
737db469ba | ||
|
|
a44a33d508 | ||
|
|
a518d41c78 | ||
|
|
d5360c6568 | ||
|
|
d468107311 | ||
|
|
3f65e1bfa0 | ||
|
|
a22758f5cd | ||
|
|
88b5b9d1e7 | ||
|
|
e38f7c880e | ||
|
|
6367b58994 | ||
|
|
5a54b5ee64 | ||
|
|
002e41f418 | ||
|
|
f7787c748a | ||
|
|
f9b18b45a4 | ||
|
|
8966f44272 | ||
|
|
3dbcbae61f | ||
|
|
24508abe7a | ||
|
|
27f8f2542e | ||
|
|
44ee3ceec8 | ||
|
|
b08112aec0 | ||
|
|
9d2bbda2b9 | ||
|
|
6eff685b18 | ||
|
|
2d08146de8 | ||
|
|
f131420a44 | ||
|
|
245ea5463e | ||
|
|
71bb90a769 | ||
|
|
e71a22fbb3 | ||
|
|
802c4c28f5 | ||
|
|
2cda6fc057 | ||
|
|
a0303c70f9 | ||
|
|
f5b9f58747 | ||
|
|
0d8dee0ed7 | ||
|
|
ace02263dd | ||
|
|
a2398bfb3a | ||
|
|
cd7ddb5ba1 | ||
|
|
ae37a4c85d | ||
|
|
32e1716061 | ||
|
|
d92616f39f | ||
|
|
0c13db46fd | ||
|
|
b6fc9a8ec1 | ||
|
|
a672141352 | ||
|
|
df354e483a | ||
|
|
89874545b1 | ||
|
|
b0fdd09f39 | ||
|
|
fbf620ae36 | ||
|
|
509f7da12e | ||
|
|
64a40e4ed0 | ||
|
|
ab253dbf28 | ||
|
|
feb19df20f | ||
|
|
d5d2241f1b | ||
|
|
5af1a0aa87 | ||
|
|
816621651d | ||
|
|
8f2aa08dbe | ||
|
|
d20e1a6e9c | ||
|
|
2a5a4c9ace | ||
|
|
2e7fd3fb60 | ||
|
|
56579100f1 | ||
|
|
1e5cd24acd | ||
|
|
7f152cef20 | ||
|
|
3958d2d597 | ||
|
|
84a3b31e8d | ||
|
|
cc15c12d19 | ||
|
|
50e7b89b15 | ||
|
|
0b507cb66a | ||
|
|
b1c697ea09 | ||
|
|
dbcf15e45b | ||
|
|
21d864ce7a | ||
|
|
dcf1f1af10 | ||
|
|
9c25a39b7b | ||
|
|
d79687db53 | ||
|
|
77428e0fe5 | ||
|
|
53df3b5cfa | ||
|
|
f2e1c9e959 | ||
|
|
a004b2f3e0 | ||
|
|
65b4398b0e | ||
|
|
0b83d2869d | ||
|
|
1a408b810c | ||
|
|
bab5879c3d | ||
|
|
70408ca8ee | ||
|
|
82848aa4cd | ||
|
|
5131604ba7 | ||
|
|
1be821b07a |
61
.github/CONTRIBUTING.md
vendored
@@ -1 +1,60 @@
|
||||
Please see the [Wiki](https://github.com/mRemoteNG/mRemoteNG/wiki/Development) for contributing information.
|
||||
# Welcome!
|
||||
|
||||
We are really glad you are interested in contributing to mRemoteNG!
|
||||
|
||||
Open source software is best when shared with others. This also applies to the work that goes into the software. Your ideas and passion are what make this software great.
|
||||
|
||||
|
||||
### Ways you can contribute
|
||||
There are many ways that you can help improve mRemoteNG, even if you don't know how to program.
|
||||
|
||||
For example, you might:
|
||||
- add documentation or "how-to" articles on the [Wiki](https://github.com/mRemoteNG/mRemoteNG/wiki)
|
||||
- answer support questions on the [forum](http://forum.mremoteng.org)
|
||||
- [add or improve a translation](https://github.com/mRemoteNG/mRemoteNG/wiki/How to Help Translating mRemoteNG)
|
||||
- submit a [pull request](https://github.com/mRemoteNG/mRemoteNG/pulls) for a [bug or feature ticket](https://github.com/mRemoteNG/mRemoteNG/issues)
|
||||
|
||||
|
||||
# Submitting GitHub Issues
|
||||
The GitHub Issue tracker is our preferred channel for bug reports and feature requests.
|
||||
- For questions or general discussion, please use [our public Gitter chat](https://gitter.im/mRemoteNG/PublicChat) or the [forum](http://forum.mremoteng.org).
|
||||
- If you find a security vulnerability, do **NOT** open an issue. Email support@mremoteng.org instead.
|
||||
|
||||
### Bug reports
|
||||
A bug is any behavior that does not consistently produce the expected result.
|
||||
|
||||
Guidelines for bug reports:
|
||||
1. Do not open bug reports for questions.
|
||||
1. Use the GitHub Issue search to make sure your bug hasn't already been reported.
|
||||
1. Include as much detailed information as possible. We've included a default template when opening an issue to make this easier.
|
||||
1. Please tag your your bug report with the [`Bug`](https://github.com/mRemoteNG/mRemoteNG/issues?q=is%3Aissue+is%3Aopen+label%3ABug) label.
|
||||
|
||||
### Feature requests
|
||||
Feature requests are great! Take some time to compose a well thought out proposal. It's up to you to convince the project maintainers that your feature is a good idea. To ensure your request receives the consideration that it deserves, include as much detail as possible. For example:
|
||||
- What is the purpose of the new feature?
|
||||
- What situation led you to want this feature?
|
||||
- How does the application perform now and how would the new feature change this?
|
||||
- If applicable, consider including visual mock-ups to show us what you mean.
|
||||
- Please tag your feature request with the [`Feature Request`](https://github.com/mRemoteNG/mRemoteNG/issues?q=is%3Aissue+is%3Aopen+label%3A%22Feature+Request%22) label.
|
||||
|
||||
# Pull requests
|
||||
Good pull requests are a huge help! If you haven't already, please consider reading [GitHub's guide to contributing to open source](https://guides.github.com/activities/contributing-to-open-source/)
|
||||
|
||||
Our requests when it comes to pull requests:
|
||||
- Be clear about what your PR seeks to do.
|
||||
- Keep your PR focused. It should be clear what code changed to achieve your stated goal.
|
||||
- Add or update tests when possible. Some of the code base is still very hard to effectively test. If you can, please try to create or update tests that relate to your PR.
|
||||
- Please talk with one of the project maintainers before starting work on large pull requests. Otherwise, you run the risk of putting a lot of time into a feature or refactor that gets denied.
|
||||
- If you have access to Static Code Analysis tools (like ReSharper), please don't analyze/fix everything in one giant PR. As great as these tools are, they can sometimes cause unintended problems.
|
||||
|
||||
# Code Style
|
||||
- Please make use of simple types and var where possible
|
||||
- Prefer "using" over .Dispose()
|
||||
- Avoid nesting "using"
|
||||
|
||||
# Your first contributions
|
||||
Want to help but don't know where to start? Check out the issues that we've labeled with [`Help Wanted`](https://github.com/mRemoteNG/mRemoteNG/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+Wanted%22) or [`ready`](https://github.com/mRemoteNG/mRemoteNG/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3A%22ready%22). These will vary in difficulty, but should be possible for new contributors.
|
||||
|
||||
Want to help but don't know C#? Check out the issues that we've labeled with [`Documentation`](https://github.com/mRemoteNG/mRemoteNG/labels/Documentation).
|
||||
|
||||
Sorry, we currently do not have any tags for truly beginner-friendly issues :(
|
||||
|
||||
BIN
.github/icon_ReSharper.png
vendored
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
111
CHANGELOG.TXT
@@ -1,3 +1,106 @@
|
||||
1.75.7002 (2017-03-10):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#448: Resolved issue with SQL saving
|
||||
|
||||
|
||||
1.75.7001 (2017-03-10):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#408: Update SQL scripts
|
||||
|
||||
|
||||
1.75 hotfix 1 (2017-03-06):
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
#437: Modify version numbering scheme
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#422: Uncaught exception when clicking in connection tree whitespace
|
||||
#312: Resolved KeePass auto-type issue
|
||||
#427: Export does not respect filtering user/password/domain
|
||||
|
||||
|
||||
1.75 (2017-03-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
File hash check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
Exception will be: "MD5 Hashes didn't match!" for 1.75 Beta 1 - 1.75 RC1
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
#344 - Use SHA512 File Hashes to validate downloads (in the update mechanism & posted to the Downloads page)
|
||||
|
||||
|
||||
1.75 RC1 (2017-01-27):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
Added Release Channels to the update check functionality allowing users to select one of 3 release channels for updates: Stable, Beta, Dev
|
||||
#360: Help -> About, Version # is now selectable/copyable
|
||||
#221: RDP: Optional disconnect after X number of minutes of inactivity
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#369: Reset Layout Option Does Not Reset Notification Pane
|
||||
#362: Invalid cast exception when using the Notification Area Icon minimize/restore
|
||||
#334: Quick Connect displays warning when clicking on a folder
|
||||
#325: When using a connection with an external app, results in opening the same external app continuously
|
||||
#311: Import from Active Directory does not use machine's domain by default
|
||||
#258: Rename Tab dialog - populate original name in dialog (1.72 functionality)
|
||||
#211, #267: Recursive AD Import wasn't fully functional
|
||||
|
||||
|
||||
General Changes:
|
||||
----------------
|
||||
The usual general code clean up and refactoring
|
||||
#325: Code clean up and additional logging for External Tools based connections
|
||||
#298: Code clean up and additional logging around application startup
|
||||
#291, #236: External Tools code clean up and additional logging
|
||||
|
||||
|
||||
|
||||
1.75 Beta 3 (2016-12-01):
|
||||
|
||||
Known Issue:
|
||||
------------
|
||||
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
|
||||
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#289: Install fails during update process (only affects v1.75 beta 1 - v1.75 beta 2)
|
||||
|
||||
|
||||
1.75 Beta 2 (2016-12-01):
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
#273: Added Turkish translation provided by forum user "rizaemet"
|
||||
#217: Create user manual documentation for the SSH File Transfer feature
|
||||
|
||||
|
||||
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 doesn't expand it in 1.75 beta1
|
||||
#271: Install package is not using the last installation path
|
||||
#278: Silent installs not detecting prerequisites
|
||||
|
||||
|
||||
1.75 Beta 1 (2016-11-15):
|
||||
|
||||
General Changes:
|
||||
@@ -37,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
|
||||
|
||||
|
||||
|
||||
@@ -45,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
|
||||
@@ -120,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
|
||||
@@ -261,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.
|
||||
|
||||
@@ -8,6 +8,11 @@ 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
|
||||
=================
|
||||
@@ -38,6 +43,7 @@ Emanuel Silva
|
||||
Robert Siwiec
|
||||
Hayato Iriumi
|
||||
Sebastien Thieury (github.com/SebThieu)
|
||||
Riza Emet
|
||||
|
||||
|
||||
Included Source Code
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<!-- http://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/ -->
|
||||
<!-- This pattern allows a cmdline value to take precedence over values set from searchers (registry/file/etc) -->
|
||||
|
||||
<!-- Save the INSTALLDIR value from the cmdline, if it was provided -->
|
||||
<CustomAction Id="SaveCmdlineINSTALLDIR" Property="CMDLINE_INSTALLDIR" Value="[INSTALLDIR]" Execute="firstSequence" />
|
||||
|
||||
<!-- Set the INSTALLDIR value to the cmdline value, if one was provided -->
|
||||
<CustomAction Id="SetFromCmdlineINSTALLDIR" Property="INSTALLDIR" Value="[CMDLINE_INSTALLDIR]" Execute="firstSequence" />
|
||||
|
||||
|
||||
<InstallUISequence>
|
||||
<Custom Action="SaveCmdlineINSTALLDIR" Before="AppSearch" />
|
||||
<Custom Action="SetFromCmdlineINSTALLDIR" After="AppSearch">
|
||||
CMDLINE_INSTALLDIR
|
||||
</Custom>
|
||||
</InstallUISequence>
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="SaveCmdlineINSTALLDIR" Before="AppSearch" />
|
||||
<Custom Action="SetFromCmdlineINSTALLDIR" After="AppSearch">
|
||||
CMDLINE_INSTALLDIR
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -4,7 +4,7 @@
|
||||
<Fragment>
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="$(var.PlatformProgramFilesFolder)">
|
||||
<Directory Id="APPLICATIONROOTDIRECTORY" Name="$(var.ProductName)">
|
||||
<Directory Id="INSTALLDIR" Name="$(var.ProductName)">
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?include $(sys.CURRENTDIR)Includes\Config.wxi?>
|
||||
<Fragment>
|
||||
<Component Id="C.MainExe" Directory="APPLICATIONROOTDIRECTORY" Guid="*">
|
||||
<Component Id="C.MainExe" Directory="INSTALLDIR" Guid="*">
|
||||
<File Id="MainExeFile" Source="$(var.SolutionDir)mRemoteV1\bin\$(var.Configuration)\mRemoteNG.exe" />
|
||||
</Component>
|
||||
</Fragment>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<ComponentGroup Id="CG.ProjectInfoFiles" Directory="APPLICATIONROOTDIRECTORY">
|
||||
<ComponentGroup Id="CG.ProjectInfoFiles" Directory="INSTALLDIR">
|
||||
<Component Id="C.Changelog" Guid="*">
|
||||
<File Id="ChangelogFile" Name="Changelog.txt" Source="$(var.SolutionDir)CHANGELOG.TXT" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<DirectoryRef Id="APPLICATIONROOTDIRECTORY">
|
||||
<DirectoryRef Id="INSTALLDIR">
|
||||
<Component Id="C.PuttyNGFile" Guid="*">
|
||||
<File Id="PuttyNGFile" Name="PuTTYNG.exe" Source="$(var.HarvestPath)\PuTTYNG.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Component Id="C.RegistryEntries" Guid="*">
|
||||
<RegistryKey Root="HKLM" Key="Software\mRemoteNG">
|
||||
<RegistryValue Type="string" Name="InstallDir" Value="[INSTALLDIR]" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
<DirectoryRef Id="DesktopFolder">
|
||||
<Component Id="C.DesktopShortcut" Guid="F78E5A16-A2F7-4BD9-9250-CBF3016CCCDA">
|
||||
<Shortcut Id="DesktopShortcut" Name="$(var.ProductName)" Target="[APPLICATIONROOTDIRECTORY][MAINEXE]" WorkingDirectory="APPLICATIONROOTDIRECTORY" Icon="mRemoteNG.ico" />
|
||||
<Shortcut Id="DesktopShortcut" Name="$(var.ProductName)" Target="[INSTALLDIR][MAINEXE]" WorkingDirectory="INSTALLDIR" Icon="mRemoteNG.ico" />
|
||||
<RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Name="DesktopShortcut" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="C.ApplicationStartMenuShortcut" Guid="193B9E14-F40E-44F1-8514-BED253BCBF75">
|
||||
<Shortcut Id="ApplicationStartMenuShortcut" Name="$(var.ProductName)" Target="[APPLICATIONROOTDIRECTORY][MAINEXE]" WorkingDirectory="APPLICATIONROOTDIRECTORY" Icon="mRemoteNG.ico" />
|
||||
<Shortcut Id="CreditsShortcut" Name="Credits" Target="[APPLICATIONROOTDIRECTORY]Credits.txt" WorkingDirectory="APPLICATIONROOTDIRECTORY" />
|
||||
<Shortcut Id="LicenseShortcut" Name="License" Target="[APPLICATIONROOTDIRECTORY]License.txt" WorkingDirectory="APPLICATIONROOTDIRECTORY" />
|
||||
<Shortcut Id="ReadmeShortcut" Name="Readme" Target="[APPLICATIONROOTDIRECTORY]Readme.txt" WorkingDirectory="APPLICATIONROOTDIRECTORY" />
|
||||
<Shortcut Id="ApplicationStartMenuShortcut" Name="$(var.ProductName)" Target="[INSTALLDIR][MAINEXE]" WorkingDirectory="INSTALLDIR" Icon="mRemoteNG.ico" />
|
||||
<Shortcut Id="CreditsShortcut" Name="Credits" Target="[INSTALLDIR]Credits.txt" WorkingDirectory="INSTALLDIR" />
|
||||
<Shortcut Id="LicenseShortcut" Name="License" Target="[INSTALLDIR]License.txt" WorkingDirectory="INSTALLDIR" />
|
||||
<Shortcut Id="ReadmeShortcut" Name="Readme" Target="[INSTALLDIR]Readme.txt" WorkingDirectory="INSTALLDIR" />
|
||||
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
|
||||
<RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Name="ApplicationStartMenuShortcut" Type="integer" Value="1" KeyPath="yes"/>
|
||||
</Component>
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CustomActions\CheckForInstalledWindowsUpdates.wxs" />
|
||||
<Compile Include="CustomActions\SaveInstallLocation.wxs" />
|
||||
<Compile Include="CustomActions\UninstallLegacyVersions.wxs" />
|
||||
<Compile Include="Fragments\FilesFragment.wxs" />
|
||||
<Compile Include="Fragments\DirectoriesFragment.wxs" />
|
||||
<Compile Include="Fragments\MainExeFragment.wxs" />
|
||||
<Compile Include="Fragments\MiscTextFilesFragment.wxs" />
|
||||
<Compile Include="Fragments\PuTTYNGFragment.wxs" />
|
||||
<Compile Include="Fragments\RegistryEntriesFragment.wxs" />
|
||||
<Compile Include="Fragments\ShortcutFragment.wxs" />
|
||||
<Compile Include="mRemoteNGV1.wxs" />
|
||||
</ItemGroup>
|
||||
@@ -112,18 +114,6 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Portable|x86' ">
|
||||
<DefineConstants>HarvestPath=$(SolutionDir)mRemoteV1\bin\Release Portable;HelpFilesHarvestPath=$(SolutionDir)mRemoteV1\Resources\Help</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>REM Clean the TargetDir
|
||||
rmdir /S /Q "$(TargetDir)"
|
||||
|
||||
echo $(ConfigurationName) > buildenv.tmp
|
||||
|
||||
REM Harvest bin directory of the mRemoteV1 project
|
||||
call "$(WIX)bin\heat.exe" dir "$(SolutionDir)mRemoteV1\bin\$(Configuration)" -ag -dr APPLICATIONROOTDIRECTORY -var var.HarvestPath -srd -cg MandatoryComponents -template fragment -out "$(ProjectDir)Fragments\FilesFragment.wxs" -t "$(ProjectDir)Filters\Harvest_Filter.xslt" -v
|
||||
|
||||
REM Convert the license file "COPYING.TXT" to "License.rtf" to be shown in the installer GUI
|
||||
call "$(ProjectDir)Resources\Pandoc\pandoc.exe" -s -t rtf -o "$(ProjectDir)\Resources\License.rtf" "$(SolutionDir)COPYING.TXT"</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>set /p buildenv=<buildenv.tmp
|
||||
|
||||
@@ -140,4 +130,16 @@ powershell -ExecutionPolicy Bypass -File "$(SolutionDir)Tools\rename_installer_w
|
||||
REM Copy MSI to Release folder
|
||||
IF %25buildenv: Portable=%25==Release (powershell -ExecutionPolicy Bypass -File "$(SolutionDir)Tools\copy_release_installer.ps1" $(TargetDir) $(SolutionDir)Release)</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>REM Clean the TargetDir
|
||||
rmdir /S /Q "$(TargetDir)"
|
||||
|
||||
echo $(ConfigurationName) > buildenv.tmp
|
||||
|
||||
REM Harvest bin directory of the mRemoteV1 project
|
||||
call "$(WIX)bin\heat.exe" dir "$(SolutionDir)mRemoteV1\bin\$(Configuration)" -ag -dr INSTALLDIR -var var.HarvestPath -srd -cg MandatoryComponents -template fragment -out "$(ProjectDir)Fragments\FilesFragment.wxs" -t "$(ProjectDir)Filters\Harvest_Filter.xslt" -v
|
||||
|
||||
REM Convert the license file "COPYING.TXT" to "License.rtf" to be shown in the installer GUI
|
||||
call "$(ProjectDir)Resources\Pandoc\pandoc.exe" -s -t rtf -o "$(ProjectDir)\Resources\License.rtf" "$(SolutionDir)COPYING.TXT"</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -12,8 +12,9 @@
|
||||
<Binary Id="CustomActions.CA.dll" SourceFile="$(var.SolutionDir)InstallerProjects\CustomActions\bin\$(var.Configuration)\CustomActions.CA.dll" />
|
||||
<Property Id="ARPPRODUCTICON" Value="mRemoteNG.ico" />
|
||||
<Property Id="ARPHELPLINK" Value="http://www.mremoteng.org" />
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize" />
|
||||
<Property Id="MAINEXE" Value="$(var.ExeProcessName)" />
|
||||
<Property Id="APPLICATIONROOTDIRECTORY">
|
||||
<Property Id="INSTALLDIR">
|
||||
<RegistrySearch Id='mRemoteNGRegistry' Type='raw' Root='HKLM' Key='Software\mRemoteNG' Name='InstallDir' />
|
||||
</Property>
|
||||
<Property Id='RDP_DTLS_KB' Value='$(var.RdpDtlsKb)' />
|
||||
@@ -26,6 +27,7 @@
|
||||
<PropertyRef Id="NETFRAMEWORK40FULL" />
|
||||
<PropertyRef Id="WIX_IS_NETFRAMEWORK_40_OR_LATER_INSTALLED" />
|
||||
<Icon Id="mRemoteNG.ico" SourceFile="Resources\mRemoteNG.ico" />
|
||||
<CustomActionRef Id='SaveCmdlineINSTALLDIR' />
|
||||
|
||||
|
||||
<InstallUISequence>
|
||||
@@ -35,6 +37,14 @@
|
||||
<Custom Action="CheckIfLegacyVersionInstalled" After="LaunchConditions" />
|
||||
<Custom Action="UninstallLegacyVersion" After="CheckIfLegacyVersionInstalled">(NOT Installed) AND (LEGACYVERSIONINSTALLED = 1)</Custom>
|
||||
</InstallUISequence>
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="CheckIfRdpDtlsUpdateInstalled" After="AppSearch">(NOT Installed) AND (VersionNT = 601 OR VersionNT64 = 601)</Custom>
|
||||
<Custom Action="CheckIfMinimumRdpInstalled" After="CheckIfRdpDtlsUpdateInstalled">(NOT Installed) AND (VersionNT = 601 OR VersionNT64 = 601)</Custom>
|
||||
<LaunchConditions After="SetWIX_IS_NETFRAMEWORK_40_OR_LATER_INSTALLED" />
|
||||
<Custom Action="CheckIfLegacyVersionInstalled" After="LaunchConditions" />
|
||||
<Custom Action="UninstallLegacyVersion" After="CheckIfLegacyVersionInstalled">(NOT Installed) AND (LEGACYVERSIONINSTALLED = 1)</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
|
||||
<!-- Need to be admin to install -->
|
||||
@@ -65,10 +75,11 @@
|
||||
|
||||
|
||||
<Feature Id="F.Complete" Title="!(loc.Feature_Complete)" Display="expand" AllowAdvertise="no" Level="1">
|
||||
<Feature Id="F.MinimalFeature" Title="$(var.ProductName)" Absent="disallow" ConfigurableDirectory="APPLICATIONROOTDIRECTORY" Level="1">
|
||||
<Feature Id="F.MinimalFeature" Title="$(var.ProductName)" Absent="disallow" ConfigurableDirectory="INSTALLDIR" Level="1">
|
||||
<ComponentGroupRef Id="MandatoryComponents" Primary="yes" />
|
||||
<ComponentRef Id="C.MainExe" Primary="yes" />
|
||||
<ComponentGroupRef Id="CG.ProjectInfoFiles" Primary="yes" />
|
||||
<ComponentRef Id="C.RegistryEntries" Primary="yes" />
|
||||
</Feature>
|
||||
|
||||
<Feature Id="F.PuttyNG" Title="PuTTYNG" Absent="allow" AllowAdvertise="no" Level="1">
|
||||
|
||||
6
Jenkinsfile
vendored
@@ -5,11 +5,7 @@ node('windows') {
|
||||
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
|
||||
|
||||
stage 'Checkout Branch'
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: scm.branches,
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
checkout scm
|
||||
|
||||
stage 'Restore NuGet Packages'
|
||||
def nugetPath = "C:\\nuget.exe"
|
||||
|
||||
24
README.MD
@@ -1,13 +1,19 @@
|
||||
# Welcome to the mRemoteNG project!
|
||||
|
||||
[](https://twitter.com/intent/follow?screen_name=mRemoteNG)
|
||||
|
||||
|
||||
[](https://gitter.im/mRemoteNG/PublicChat)
|
||||
|
||||
[](https://www.paypal.me/DavidSparer)
|
||||
|
||||
[](http://ec2-52-39-111-114.us-west-2.compute.amazonaws.com:8080/job/mRemoteNG/job/mRemoteNG/job/develop/)
|
||||
[](http://waffle.io/mRemoteNG/mRemoteNG)
|
||||
[](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/529)
|
||||
|
||||
[](https://waffle.io/mRemoteNG/mRemoteNG)
|
||||
|
||||
| Update Channel | Build Status | Downloads |
|
||||
| ---------------|--------------|-----------|
|
||||
| Stable | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/master/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.74) |
|
||||
| Beta | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/beta_channel/) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75Beta3) |
|
||||
| Development | [](https://jenkins.mremoteng.org/job/mRemoteNG/job/mRemoteNG/job/develop/) | - |
|
||||
|
||||
|
||||
|
||||
mRemoteNG is the next generation of mRemote, a full-featured, multi-tab remote connections manager.
|
||||
@@ -34,4 +40,8 @@ https://support.microsoft.com/en-us/kb/2923545
|
||||
|
||||
Windows 8+ support RDP version 8+ out of the box.
|
||||
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connection successfully to a Windows 2003 host (for example).
|
||||
RDP versions are backwards compatible, so an mRemoteNG client running on Windows 10 can connect successfully to a Windows 2003 host (for example).
|
||||
|
||||
|
||||
|
||||
[](https://www.jetbrains.com/resharper/)
|
||||
|
||||
@@ -1,12 +1,42 @@
|
||||
#Requires -Version 4.0
|
||||
|
||||
$file = gci ..\Release | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$releaseFolder = Join-Path -Path $PSScriptRoot -ChildPath "..\Release" -Resolve
|
||||
$tag = Read-Host -Prompt 'Tag name'
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
|
||||
Write-Host PORTABLE
|
||||
Write-Host --------
|
||||
$file = Get-ChildItem -Path "$releaseFolder\*.zip" | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".zip")
|
||||
Write-Host Version: $version
|
||||
|
||||
Write-Host dURL:
|
||||
Write-Host clURL:
|
||||
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 }
|
||||
Write-Host CertificateThumbprint: $hash
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
|
||||
|
||||
Write-Host
|
||||
Write-Host
|
||||
Write-Host
|
||||
|
||||
Write-Host MSI
|
||||
Write-Host ---
|
||||
$file = Get-ChildItem -Path "$releaseFolder\*.msi" | sort LastWriteTime | select -last 1 | % { $_.FullName }
|
||||
$filename = $file.Split("\") | select -last 1
|
||||
|
||||
$version = $file.tostring().Split("-")[2].trim(".msi")
|
||||
Write-Host Version: $version
|
||||
|
||||
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
|
||||
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
|
||||
|
||||
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
|
||||
Write-Host Checksum: $hash
|
||||
84
mRemoteNGTests/App/UpdaterTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNGTests.Properties;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.App
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdaterTests
|
||||
{
|
||||
[Test]
|
||||
public void UpdateStableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateStablePortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateBetaPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.beta_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UpdateDevPortableChannel()
|
||||
{
|
||||
GeneralAppInfo.ApplicationVersion = "1.0.0.0";
|
||||
var CurrentUpdateInfo = UpdateInfo.FromString(Resources.dev_update_portable);
|
||||
Assert.That(CurrentUpdateInfo.CheckIfValid(), Is.True);
|
||||
Version v;
|
||||
Version.TryParse(GeneralAppInfo.ApplicationVersion, out v);
|
||||
var IsNewer = CurrentUpdateInfo.Version > v;
|
||||
Assert.That(IsNewer, Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
|
||||
@@ -18,10 +18,7 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
|
||||
public void Setup(string confCons, string password)
|
||||
{
|
||||
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(confCons)
|
||||
{
|
||||
AuthenticationRequestor = password.ConvertToSecureString
|
||||
};
|
||||
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(confCons, password.ConvertToSecureString);
|
||||
_connectionTreeModel = _xmlConnectionsDeserializer.Deserialize();
|
||||
}
|
||||
|
||||
@@ -126,6 +123,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
get
|
||||
{
|
||||
yield return new TestCaseData(new Datagram("confCons v2.5", Resources.confCons_v2_5, "mR3m"));
|
||||
yield return new TestCaseData(new Datagram("confCons v2.5 fullencryption", Resources.confCons_v2_5_fullencryption, "mR3m"));
|
||||
yield return new TestCaseData(new Datagram("confCons v2.5 custompassword,fullencryption", Resources.confCons_v2_5_passwordis_Password_fullencryption, "Password"));
|
||||
yield return new TestCaseData(new Datagram("confCons v2.6", Resources.confCons_v2_6, "mR3m"));
|
||||
yield return new TestCaseData(new Datagram("confCons v2.6 5k Iterations", Resources.confCons_v2_6_5k_iterations, "mR3m"));
|
||||
yield return new TestCaseData(new Datagram("confCons v2.6 fullencryption", Resources.confCons_v2_6_fullencryption, "mR3m"));
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
public void Setup()
|
||||
{
|
||||
_cryptographyProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var saveFilter = new SaveFilter();
|
||||
_documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, saveFilter);
|
||||
_connectionTreeModel = SetupConnectionTreeModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
{
|
||||
var connectionTreeModel = SetupConnectionTreeModel();
|
||||
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider).CompileDocument(connectionTreeModel, false, false);
|
||||
var saveFilter = new SaveFilter();
|
||||
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, saveFilter).CompileDocument(connectionTreeModel, false, false);
|
||||
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
@@ -45,6 +47,27 @@ namespace mRemoteNGTests.Config.Serializers
|
||||
Assert.That(connectionNode, Is.Not.Null);
|
||||
}
|
||||
|
||||
[TestCase("Username", "")]
|
||||
[TestCase("Domain", "")]
|
||||
[TestCase("Password", "")]
|
||||
[TestCase("InheritAutomaticResize", "False")]
|
||||
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
|
||||
{
|
||||
_serializer.SaveFilter = new SaveFilter(true);
|
||||
var connectionInfo = new ConnectionInfo
|
||||
{
|
||||
Name = "myConnection",
|
||||
Username = "somefilteredstuff",
|
||||
Domain = "somefilteredstuff",
|
||||
Password = "somefilteredstuff",
|
||||
Inheritance = {AutomaticResize = true}
|
||||
};
|
||||
var serializedConnections = _serializer.Serialize(connectionInfo);
|
||||
var xdoc = XDocument.Parse(serializedConnections);
|
||||
var attributeValue = xdoc.Root?.Element("Node")?.Attribute(attributeName)?.Value;
|
||||
Assert.That(attributeValue, Is.EqualTo(expectedValue));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel SetupConnectionTreeModel()
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
105
mRemoteNGTests/Properties/Resources.Designer.cs
generated
@@ -60,6 +60,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string beta_update {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string beta_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("beta_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" Protected="95syzRuZ4mRxpNkZQzoyX8SDpQXLyMq3GncO8o4SyTBoYvn3TAWgn05ZEU2DrjkM" ConfVersion="2.5">
|
||||
@@ -71,9 +97,27 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to qqv8WEdruAEzSfdnPZMQ8w5cLhsl55V/Vu6h81Ucv7s7OT3vwnocgLmfId8rxpfVBnZwdn1Pdvea0XgwnQKJV5qdrVZEiy694Vv84B3wXjxU1wT72rWu1C5TNLhNEZp9JqjjAxOttIbOFL5X0dM+zI4YrCmTZI2Qt04TaC47MTr2niO7XvQSvjDeZRPnzeHsEiJvxHvBSm9yJ64Iupect0zKIpFPiDuOoHDhFQegUCZ26IdZCX2IHb3pH866rYV+yiAGhqt7pokBHUKURVtN6eKpbYzlDyGPbLRJf/eD13KnlaVC6sbf7YiCP3JwJrkN5mLdnrZbmZGQJG3Sn9rrGeShItYG/vvayFAQ5jxz1Wddixik/1frJOtUCaKW1svh8X9EvJo/RaBwgbTLIWth/WTgT4E+9DAVocdgMDGXrpsulnLTkX8doxeWHmBq2vAOhlYFNlhw2ZL3Yp/fbuVK9OMt7PbGkf3x3nThSf0R61Ip4NRjCzWempepEHoLMeiv [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_5_fullencryption {
|
||||
get {
|
||||
return ResourceManager.GetString("confCons_v2_5_fullencryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to cpfCUuZuIpTYihGooKKG5eRIZVB8P4bANitHVY57yrzyr9wf6lHlgUKx3Y3/YDYXDeS9uawycgbGSVOCnKmah3zEJ31V3BMlA809AdgQoYV9GFXLhgz8auO0mdcfYo2FP7UYS/I2bAfoNOaLvvgmqamm7Lu5FtvSvqdCf3PmpJAW042BijgkDhqritfDAyBvqUbNtE7yvrJohiSv5Ur7qFMXMIUCK0Fc4o3PXM++exN9XfTrtPAwQpjchxoEEmXBOQVnPB4QIn6eg6Wr/4XgtWYFIbtCCzyA5/L91CsDdKBZZktNSRrJTyMmPYGLn1k3Ted77rsoVUovrhxqfXgErPxDLBFAOA9wAjk7NscTRQJGxbgEU5H514g4U6h9wWlLaFyswQQCIskAbmoBrFJz72X9ooS4IVh1q9gLvCKuqb1VM6tNC0RCcLS5EHpxG6kIVpmnNtSa/0EvwaiSLMskC74TpYJ6nBUpfZT783jTikAFNDVI4eA43mJLEIBvrxBR [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_5_passwordis_Password_fullencryption {
|
||||
get {
|
||||
return ResourceManager.GetString("confCons_v2_5_passwordis_Password_fullencryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="False" Protected="Bqmajt4G5RDLsV5nn3s7QHZkkeWXQqgSDA4RSA8fWYx1bxRaorsmZ0ub4Z6mOBbefuXBbaWnsVRn0+NOJ3zTjkUJ" ConfVersion="2.6">
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="False" Protected="8LmIO3+MWBY0zTmfjfOEdCGxhTAwnlohb1veTGNZFt6lAYvY2UOzWyjVzkx6V93smpbP0ZOuexN15u7rvwJEjawC" ConfVersion="2.6">
|
||||
/// <Node Name="Folder1" Type="Container" Expanded="True" Descr="" Icon="mRemoteNG" Panel="General" Username="" Domain="" Password="" Hostname="" Protocol="ICA" PuttySession="Default Settings" Port="1494" Connec [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_6 {
|
||||
@@ -84,7 +128,7 @@ namespace mRemoteNGTests.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="5000" FullFileEncryption="False" Protected="ZrxA5XJSUirgITMc2UxVRY4mLPxzNsyaqpgJXNdjcUdTlA/p4ZQP4bKqp44ZMrZlNU9jZgsvodGEVqS5/26St+Sk" ConfVersion="2.6">
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="5000" FullFileEncryption="False" Protected="Z1IOT8h7neJ5V7es5Iv63A2WsDG6QWl10F/Rb9ljKxvCseEITty1BfMNgiaVPfm7w61uabQKqu2waDCXUpLo1OZW" ConfVersion="2.6">
|
||||
/// <Node Name="Folder1" Type="Container" Expanded="True" Descr="" Icon="mRemoteNG" Panel="General" Username="" Domain="" Password="" Hostname="" Protocol="ICA" PuttySession="Default Settings" Port="1494" Connec [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_6_5k_iterations {
|
||||
@@ -95,7 +139,7 @@ namespace mRemoteNGTests.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="True" Protected="tfNq70KLL8id4QnOeC9OrjMlACoArKa7pFJKcG1vrrRxMkvHpJPiEx/JlbPBJ3x4HXXx806ipsFiMkU1+OT7eE3Z" ConfVersion="2.6">NAxOa6dYlXPZCtpxWfiFrINjIC0dicQU7YdmKRnOn6POI07mMWU/Yy5uhPeXfVfzWgbPlKGyOMk5pgTw0pYIpTZpmqRKzZN+MzFw7NTW9QgD3Uhq528OItO2/MdpGQZ8AYM+qrDHHCXG9bGkczDwe5BZ8cDnGfbFrYTINGBZ9wxjLfyA9oYxzfrzoHDACbM8gD8wvmO26ML/lShwQS+/9B [rest of string was truncated]";.
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="True" Protected="qrOUhRlBLCnjjmfU1r8uwhgIBwZ+D1+trBgPmcQyEnW0xf2adLeOfUhZHnto2NOsMneXDibsS8PH0B1moOyvua22" ConfVersion="2.6">pCvan5X5+bSJy8oZq3QhrYs9zAS4v2tu9/4eYk4GAeB2EDep9Ed1zkshaLP165sWHE9oJ6bHnWSrSr/XXiDGdosvxl+O3hSSi02On9/TspuHhPDuuDb7UY2+mLh/LVoJqAjz2NmK7f3QkID2aanHkHzE/MDFiez8gLU8SdW9RxlSXT+L8MEjIXnq34yDVsfV89tGoP01T84ShTCZpRAQMq [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_6_fullencryption {
|
||||
get {
|
||||
@@ -105,7 +149,7 @@ namespace mRemoteNGTests.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="False" Protected="et1WJ5jh501ty5nzV139lFcoK4Cjm2HwYiFDgEtTTW6iIMTiJ7ilw0gkDOOahwig8neVelBnGaP1AAmRY4B6" ConfVersion="2.6">
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="False" Protected="e/T6ajrPtNNlHreSeD4QBqToTuiqtNACKiPJv7vU+l6TWCu9JNsmL+Y8lJ4aTl5YVcstXpQjxsZ9i8+YV4Gs" ConfVersion="2.6">
|
||||
/// <Node Name="Folder1" Type="Container" Expanded="True" Descr="" Icon="mRemoteNG" Panel="General" Username="" Domain="" Password="" Hostname="" Protocol="ICA" PuttySession="Default Settings" Port="1494" ConnectToC [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_6_passwordis_Password {
|
||||
@@ -116,7 +160,7 @@ namespace mRemoteNGTests.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="True" Protected="RD3KGFlcH+4MxnYNje/ruXy6kN6pXgOwg8u6jlyU4u1RFWd8gm8DAGyAdycTDCr37dCNsi6F4Huj41haRQg4" ConfVersion="2.6">/au8q00e4YHoMGSnNWL/zRCzSQd1EaDgZ6VHuJ92iffxh5Spuhy86nsoiMr99UMaUF8UjlrYsboZC2B5sLO6t1lqKuB9okjY/jaLHTlGB7mmaHlDHXo7WEChz51xO+caUGfXCXPHgHOFsz/yCJIv3E9LwVOsAIH2qTfMp19OsytF3+Lb4T8v3nMAKb1iw63WcjFsp/835TMcZWWjI+SwPNKMze [rest of string was truncated]";.
|
||||
///<Connections Name="Connections" Export="False" EncryptionEngine="AES" BlockCipherMode="GCM" KdfIterations="1000" FullFileEncryption="True" Protected="d7pvbk1N6aswOmTgjCKkkavQKM2xTpknkdnMgzi+bOPgwr9WirGy82kaQldQ06af7MrZgJwvc9hKAcGxBfYt" ConfVersion="2.6">P9haenvGQ9HxnJSUUY+3SdALKoWQau0gF3Vxk6eCERKJ9G2gi87zhBcMCH+PwSsh/5ohPfOansFvUcDvPeE10slCTVqQmQFeU+daQY4OMk+2Q0UR/rEDRlbjGlM8YKVv2xjLRPRs6AbNJsKLv4zo8T/x3ySlZnuiMiGTGt4Wstfle/QfwNbBeV88N5IPbbKy2FWQf5yOlPtrjgPrcl0cRtRI3c [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string confCons_v2_6_passwordis_Password_fullencryption {
|
||||
get {
|
||||
@@ -124,6 +168,32 @@ namespace mRemoteNGTests.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6164.27544
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
///Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string dev_update {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string dev_update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("dev_update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-16"?>
|
||||
///<!-- ****************************************************************-->
|
||||
@@ -258,5 +328,30 @@ namespace mRemoteNGTests.Properties {
|
||||
return ResourceManager.GetString("test_remotedesktopconnection_rdp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.72.5065.32737
|
||||
///dURL: http://downloads.mremoteng.org/mRemoteNG-Installer-1.72.exe
|
||||
///clURL: http://update.mremoteng.org/changes-1.72.txt
|
||||
///CertificateThumbprint: 1cbd910dbd6e77f26506e7f600736972f700673f
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string update {
|
||||
get {
|
||||
return ResourceManager.GetString("update", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version: 1.75.6170.27478
|
||||
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
///clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
///Checksum: 1C35EA199F58001BC4EBB164D8B3D11C.
|
||||
/// </summary>
|
||||
internal static string update_portable {
|
||||
get {
|
||||
return ResourceManager.GetString("update_portable", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +118,21 @@
|
||||
<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>
|
||||
<data name="confCons_v2_5_fullencryption" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_5_fullencryption.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="confCons_v2_5_passwordis_Password_fullencryption" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_5_passwordis_Password_fullencryption.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="confCons_v2_6" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\confCons_v2_6.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
@@ -136,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>
|
||||
@@ -157,4 +175,10 @@
|
||||
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
<data name="update" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="update_portable" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
</root>
|
||||
5
mRemoteNGTests/Resources/beta-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/beta-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/dev-update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/dev-update.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6164.27544
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: A1E50ACAC4CB8023527E1E7A0E682459
|
||||
5
mRemoteNGTests/Resources/update-portable.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Version: 1.75.6170.27478
|
||||
dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Portable-1.75.6179.28241.zip
|
||||
clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/v1.75Beta3/CHANGELOG.TXT
|
||||
CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
|
||||
Checksum: 1C35EA199F58001BC4EBB164D8B3D11C
|
||||
5
mRemoteNGTests/Resources/update.txt
Normal file
@@ -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
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ExpandNodeClickHandlerTests
|
||||
{
|
||||
private ExpandNodeClickHandler _clickHandler;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_clickHandler = new ExpandNodeClickHandler(_connectionTree);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetedNodeIsExpanded()
|
||||
{
|
||||
var folder = new ContainerInfo();
|
||||
_clickHandler.Execute(folder);
|
||||
_connectionTree.Received().ToggleExpansion(folder);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NothingHappensWhenConnectionInfoProvided()
|
||||
{
|
||||
_clickHandler.Execute(new ConnectionInfo());
|
||||
_connectionTree.DidNotReceiveWithAnyArgs().ToggleExpansion(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownOnConstructorNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new ExpandNodeClickHandler(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class OpenConnectionClickHandlerTests
|
||||
{
|
||||
private OpenConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new OpenConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConnectionOpened()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().OpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new OpenConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SwitchToConnectionClickHandlerTests
|
||||
{
|
||||
private SwitchToConnectionClickHandler _clickHandler;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_clickHandler = new SwitchToConnectionClickHandler(_connectionInitiator);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SwitchesToConnection()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo();
|
||||
_clickHandler.Execute(connectionInfo);
|
||||
_connectionInitiator.Received().SwitchToOpenConnection(connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DoesNothingWhenGivenContainerInfo()
|
||||
{
|
||||
_clickHandler.Execute(new ContainerInfo());
|
||||
_connectionInitiator.DidNotReceiveWithAnyArgs().SwitchToOpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new SwitchToConnectionClickHandler(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class TreeNodeCompositeClickHandlerTests
|
||||
{
|
||||
private TreeNodeCompositeClickHandler _clickHandler;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_clickHandler = new TreeNodeCompositeClickHandler();
|
||||
_connectionInfo = new ConnectionInfo();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExecutesAllItsHandlers()
|
||||
{
|
||||
var handler1 = Substitute.For<ITreeNodeClickHandler>();
|
||||
var handler2 = Substitute.For<ITreeNodeClickHandler>();
|
||||
_clickHandler.ClickHandlers = new[] {handler1, handler2};
|
||||
_clickHandler.Execute(_connectionInfo);
|
||||
handler1.Received().Execute(_connectionInfo);
|
||||
handler2.Received().Execute(_connectionInfo);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowWhenExecuteGivenNullArg()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _clickHandler.Execute(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
51
mRemoteNGTests/Tree/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class ConnectionTreeTests
|
||||
{
|
||||
private ConnectionTree _connectionTree;
|
||||
private ConnectionTreeModel _connectionTreeModel;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeModel = CreateConnectionTreeModel();
|
||||
_connectionTree = new ConnectionTree
|
||||
{
|
||||
PostSetupActions = new IConnectionTreeDelegate[] {new RootNodeExpander()}
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTree.Dispose();
|
||||
}
|
||||
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanDeleteLastFolderInTheTree()
|
||||
{
|
||||
var lastFolder = new ContainerInfo();
|
||||
_connectionTreeModel.RootNodes[0].AddChild(lastFolder);
|
||||
_connectionTree.ConnectionTreeModel = _connectionTreeModel;
|
||||
_connectionTree.SelectObject(lastFolder);
|
||||
_connectionTree.DeleteSelectedNode();
|
||||
Assert.That(_connectionTree.GetRootConnectionNode().HasChildren, Is.False);
|
||||
}
|
||||
|
||||
private ConnectionTreeModel CreateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
connectionTreeModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection));
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
mRemoteNGTests/Tree/PreviousSessionOpenerTests.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviousSessionOpenerTests
|
||||
{
|
||||
private PreviousSessionOpener _previousSessionOpener;
|
||||
private IConnectionInitiator _connectionInitiator;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionInitiator = Substitute.For<IConnectionInitiator>();
|
||||
_previousSessionOpener = new PreviousSessionOpener(_connectionInitiator);
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.GetRootConnectionNode().Returns(BuildTree());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllRequestedSessionsAreReopened()
|
||||
{
|
||||
_previousSessionOpener.Execute(_connectionTree);
|
||||
_connectionInitiator.ReceivedWithAnyArgs(2).OpenConnection(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrownWhenConstructorGivenNullArg()
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Assert.Throws<ArgumentNullException>(() => new PreviousSessionOpener(null));
|
||||
}
|
||||
|
||||
private RootNodeInfo BuildTree()
|
||||
{
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
root.AddChild(new ConnectionInfo());
|
||||
root.AddChild(new ConnectionInfo { PleaseConnect = true });
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
mRemoteNGTests/Tree/PreviouslyOpenedFolderExpanderTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class PreviouslyOpenedFolderExpanderTests
|
||||
{
|
||||
private PreviouslyOpenedFolderExpander _folderExpander;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_folderExpander = new PreviouslyOpenedFolderExpander();
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandsAllFoldersThatAreMarkedForExpansion()
|
||||
{
|
||||
var connectionTreeModel = GenerateConnectionTreeModel();
|
||||
_connectionTree.ConnectionTreeModel.Returns(connectionTreeModel);
|
||||
_connectionTree.GetRootConnectionNode().Returns(connectionTreeModel.RootNodes[0]);
|
||||
_folderExpander.Execute(_connectionTree);
|
||||
Assert.That(_connectionTree.ExpandedObjects, Is.EquivalentTo(connectionTreeModel.GetRecursiveChildList().OfType<ContainerInfo>().Where(info => info.IsExpanded)));
|
||||
}
|
||||
|
||||
private ConnectionTreeModel GenerateConnectionTreeModel()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection) { IsExpanded = true };
|
||||
var folder1 = new ContainerInfo { IsExpanded = true };
|
||||
var folder2 = new ContainerInfo();
|
||||
var con1 = new ConnectionInfo();
|
||||
root.AddChild(folder1);
|
||||
folder1.AddChild(folder2);
|
||||
root.AddChild(con1);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
return connectionTreeModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.Tree
|
||||
{
|
||||
public class SelectedConnectionDeletionConfirmerTests
|
||||
{
|
||||
private SelectedConnectionDeletionConfirmer _deletionConfirmer;
|
||||
private IConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTree = Substitute.For<IConnectionTree>();
|
||||
_connectionTree.SelectedNode.Returns(new ConnectionInfo());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingYesReturnsTrue()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickYes);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClickingNoReturnsFalse()
|
||||
{
|
||||
_deletionConfirmer = new SelectedConnectionDeletionConfirmer(_connectionTree, MockClickNo);
|
||||
Assert.That(_deletionConfirmer.Confirm(), Is.False);
|
||||
}
|
||||
|
||||
private DialogResult MockClickYes(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.Yes;
|
||||
}
|
||||
|
||||
private DialogResult MockClickNo(string promptMessage, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
return DialogResult.No;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
mRemoteNGTests/UI/Window/ConnectionTreeWindowTests.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Threading;
|
||||
using mRemoteNG.UI.Window;
|
||||
using NUnit.Framework;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
|
||||
namespace mRemoteNGTests.UI.Window
|
||||
{
|
||||
public class ConnectionTreeWindowTests
|
||||
{
|
||||
private ConnectionTreeWindow _connectionTreeWindow;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent());
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_connectionTreeWindow.Close();
|
||||
}
|
||||
|
||||
[Test, Apartment(ApartmentState.STA)]
|
||||
public void CanShowWindow()
|
||||
{
|
||||
_connectionTreeWindow.Show();
|
||||
Assert.That(_connectionTreeWindow.Visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -31,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" />
|
||||
@@ -201,6 +213,20 @@
|
||||
<ItemGroup>
|
||||
<None Include="Resources\confCons_v2_6_5k-iterations.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\confCons_v2_5_fullencryption.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\confCons_v2_5_passwordis_Password_fullencryption.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\beta-update-portable.txt" />
|
||||
<Content Include="Resources\beta-update.txt" />
|
||||
<Content Include="Resources\dev-update-portable.txt" />
|
||||
<Content Include="Resources\dev-update.txt" />
|
||||
<Content Include="Resources\update-portable.txt" />
|
||||
<Content Include="Resources\update.txt" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
|
||||
2
mRemoteNGTests/mRemoteNGTests.csproj.DotSettings
Normal file
@@ -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>
|
||||
@@ -8,24 +8,23 @@ using System.Windows.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class CompatibilityChecker
|
||||
public static class CompatibilityChecker
|
||||
{
|
||||
public void CheckCompatibility()
|
||||
public static void CheckCompatibility()
|
||||
{
|
||||
CheckFipsPolicy();
|
||||
CheckLenovoAutoScrollUtility();
|
||||
}
|
||||
|
||||
private void CheckFipsPolicy()
|
||||
private static void CheckFipsPolicy()
|
||||
{
|
||||
if (FipsPolicyEnabledForServer2003() || FipsPolicyEnabledForServer2008AndNewer())
|
||||
{
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
Logger.Instance.InfoFormat("Checking FIPS Policy...");
|
||||
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
|
||||
MessageBox.Show(frmMain.Default, string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName, GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error));
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2003()
|
||||
private static bool FipsPolicyEnabledForServer2003()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa");
|
||||
var fipsPolicy = regKey?.GetValue("FIPSAlgorithmPolicy");
|
||||
@@ -34,7 +33,7 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
private static bool FipsPolicyEnabledForServer2008AndNewer()
|
||||
{
|
||||
var regKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy");
|
||||
var fipsPolicy = regKey?.GetValue("Enabled");
|
||||
@@ -43,12 +42,14 @@ namespace mRemoteNG.App
|
||||
return (int)fipsPolicy != 0;
|
||||
}
|
||||
|
||||
private void CheckLenovoAutoScrollUtility()
|
||||
private static void CheckLenovoAutoScrollUtility()
|
||||
{
|
||||
Logger.Instance.InfoFormat("Checking Lenovo AutoScroll Utility...");
|
||||
|
||||
if (!Settings.Default.CompatibilityWarnLenovoAutoScrollUtility)
|
||||
return;
|
||||
|
||||
Process[] proccesses = new Process[] { };
|
||||
var proccesses = new Process[] { };
|
||||
try
|
||||
{
|
||||
proccesses = Process.GetProcessesByName("virtscrl");
|
||||
@@ -58,12 +59,10 @@ namespace mRemoteNG.App
|
||||
Runtime.MessageCollector.AddExceptionMessage("Error in CheckLenovoAutoScrollUtility", ex);
|
||||
}
|
||||
|
||||
if (proccesses.Length > 0)
|
||||
{
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
if (proccesses.Length <= 0) return;
|
||||
CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, string.Format(Language.strCompatibilityLenovoAutoScrollUtilityDetected, Application.ProductName), "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.Ok, ESysIcons.Warning, ESysIcons.Warning);
|
||||
if (CTaskDialog.VerificationChecked)
|
||||
Settings.Default.CompatibilityWarnLenovoAutoScrollUtility = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
|
||||
if (exportForm.ShowDialog(frmMain.Default) != DialogResult.OK)
|
||||
return ;
|
||||
return;
|
||||
|
||||
ConnectionInfo exportTarget;
|
||||
switch (exportForm.Scope)
|
||||
@@ -76,12 +76,17 @@ namespace mRemoteNG.App
|
||||
var factory = new CryptographyProviderFactory();
|
||||
var cryptographyProvider = factory.CreateAeadCryptographyProvider(mRemoteNG.Settings.Default.EncryptionEngine, mRemoteNG.Settings.Default.EncryptionBlockCipherMode);
|
||||
cryptographyProvider.KeyDerivationIterations = Settings.Default.EncryptionKeyDerivationIterations;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider);
|
||||
((XmlConnectionsSerializer) serializer).SaveFilter = saveFilter;
|
||||
serializer = new XmlConnectionsSerializer(cryptographyProvider)
|
||||
{
|
||||
Export = true,
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
case ConnectionsSaver.Format.mRCSV:
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat();
|
||||
((CsvConnectionsSerializerMremotengFormat)serializer).SaveFilter = saveFilter;
|
||||
serializer = new CsvConnectionsSerializerMremotengFormat
|
||||
{
|
||||
SaveFilter = saveFilter
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(saveFormat), saveFormat, null);
|
||||
|
||||
@@ -11,23 +11,27 @@ namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class GeneralAppInfo
|
||||
{
|
||||
public static readonly string UrlHome = "http://www.mremoteng.org/";
|
||||
public static readonly string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public static readonly string UrlForum = "http://forum.mremoteng.org/";
|
||||
public static readonly string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static readonly string ApplicationVersion = Application.ProductVersion;
|
||||
public const string UrlHome = "http://www.mremoteng.org/";
|
||||
public const string UrlDonate = "http://donate.mremoteng.org/";
|
||||
public const string UrlForum = "http://forum.mremoteng.org/";
|
||||
public const string UrlBugs = "http://bugs.mremoteng.org/";
|
||||
public static string ApplicationVersion = Application.ProductVersion;
|
||||
public static readonly string ProductName = Application.ProductName;
|
||||
public static readonly string Copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCopyrightAttribute), false)).Copyright;
|
||||
public static readonly string HomePath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||
public static string ReportingFilePath = "";
|
||||
//public static string ReportingFilePath = "";
|
||||
public static readonly string PuttyPath = HomePath + "\\PuTTYNG.exe";
|
||||
public static string UserAgent
|
||||
{
|
||||
get
|
||||
{
|
||||
var details = new List<string>();
|
||||
details.Add("compatible");
|
||||
details.Add(OSVersion.Platform == PlatformID.Win32NT ? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}": OSVersion.VersionString);
|
||||
var details = new List<string>
|
||||
{
|
||||
"compatible",
|
||||
OSVersion.Platform == PlatformID.Win32NT
|
||||
? $"Windows NT {OSVersion.Version.Major}.{OSVersion.Version.Minor}"
|
||||
: OSVersion.VersionString
|
||||
};
|
||||
if (Is64BitProcess)
|
||||
{
|
||||
details.Add("WOW64");
|
||||
|
||||
@@ -1,34 +1,72 @@
|
||||
namespace mRemoteNG.App.Info
|
||||
using System;
|
||||
|
||||
namespace mRemoteNG.App.Info
|
||||
{
|
||||
public static class UpdateChannelInfo
|
||||
{
|
||||
public static string FileName
|
||||
public const string STABLE = "Stable";
|
||||
public const string BETA = "Beta";
|
||||
public const string DEV = "Development";
|
||||
|
||||
/* no #if here since they are used for unit tests as well */
|
||||
public const string STABLE_PORTABLE = "update-portable.txt";
|
||||
public const string BETA_PORTABLE = "beta-update-portable.txt";
|
||||
public const string DEV_PORTABLE = "dev-update-portable.txt";
|
||||
|
||||
public const string STABLE_MSI = "update.txt";
|
||||
public const string BETA_MSI = "beta-update.txt";
|
||||
public const string DEV_MSI = "dev-update.txt";
|
||||
|
||||
|
||||
public static Uri GetUpdateChannelInfo()
|
||||
{
|
||||
var channel = IsValidChannel(Settings.Default.UpdateChannel) ? Settings.Default.UpdateChannel : STABLE;
|
||||
return GetUpdateTxtUri(channel);
|
||||
}
|
||||
|
||||
private static string GetChannelFileName(string channel)
|
||||
{
|
||||
#if PORTABLE
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return PORTABLE update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-portable-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-portable-debug.txt" : "update-portable.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_PORTABLE;
|
||||
case BETA:
|
||||
return BETA_PORTABLE;
|
||||
case DEV:
|
||||
return DEV_PORTABLE;
|
||||
default:
|
||||
return STABLE_PORTABLE;
|
||||
}
|
||||
#else //NOT portable
|
||||
get
|
||||
{
|
||||
/* */
|
||||
/* return INSTALLER update files here */
|
||||
/* */
|
||||
#if DEBUG
|
||||
return "update-debug.txt";
|
||||
#else
|
||||
return Settings.Default.UpdateChannel.ToLowerInvariant() == "debug" ? "update-debug.txt" : "update.txt";
|
||||
#endif
|
||||
}
|
||||
switch (channel)
|
||||
{
|
||||
case STABLE:
|
||||
return STABLE_MSI;
|
||||
case BETA:
|
||||
return BETA_MSI;
|
||||
case DEV:
|
||||
return DEV_MSI;
|
||||
default:
|
||||
return STABLE_MSI;
|
||||
}
|
||||
#endif //endif for PORTABLE
|
||||
}
|
||||
|
||||
private static Uri GetUpdateTxtUri(string channel)
|
||||
{
|
||||
return new Uri(new Uri(Settings.Default.UpdateAddress), new Uri(GetChannelFileName(channel), UriKind.Relative));
|
||||
}
|
||||
|
||||
private static bool IsValidChannel(string s)
|
||||
{
|
||||
return s.Equals(STABLE) || s.Equals(BETA) || s.Equals(DEV);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using log4net.Config;
|
||||
using log4net.Repository;
|
||||
#if !PORTABLE
|
||||
using System;
|
||||
#endif
|
||||
@@ -29,12 +28,12 @@ namespace mRemoteNG.App
|
||||
private void Initialize()
|
||||
{
|
||||
XmlConfigurator.Configure();
|
||||
string logFile = BuildLogFilePath();
|
||||
var logFile = BuildLogFilePath();
|
||||
|
||||
ILoggerRepository repository = LogManager.GetRepository();
|
||||
IAppender[] appenders = repository.GetAppenders();
|
||||
var repository = LogManager.GetRepository();
|
||||
var appenders = repository.GetAppenders();
|
||||
|
||||
foreach (IAppender appender in appenders)
|
||||
foreach (var appender in appenders)
|
||||
{
|
||||
var fileAppender = (RollingFileAppender)appender;
|
||||
if (fileAppender == null || fileAppender.Name != "LogFileAppender") continue;
|
||||
@@ -47,12 +46,12 @@ namespace mRemoteNG.App
|
||||
private static string BuildLogFilePath()
|
||||
{
|
||||
#if !PORTABLE
|
||||
string logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.ProductName);
|
||||
var logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.ProductName);
|
||||
#else
|
||||
string logFilePath = Application.StartupPath;
|
||||
var logFilePath = Application.StartupPath;
|
||||
#endif
|
||||
string logFileName = Path.ChangeExtension(Application.ProductName, ".log");
|
||||
string logFile = Path.Combine(logFilePath, logFileName);
|
||||
var logFileName = Path.ChangeExtension(Application.ProductName, ".log");
|
||||
var logFile = Path.Combine(logFilePath, logFileName);
|
||||
return logFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
@@ -437,6 +447,7 @@ namespace mRemoteNG.App
|
||||
public static void SaveConnections()
|
||||
{
|
||||
if (ConnectionTreeModel == null) return;
|
||||
if (!IsConnectionsFileLoaded) return;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -592,7 +603,8 @@ namespace mRemoteNG.App
|
||||
connectionInfo.Protocol = url.StartsWith("https:") ? ProtocolType.HTTPS : ProtocolType.HTTP;
|
||||
connectionInfo.SetDefaultPort();
|
||||
connectionInfo.IsQuickConnect = true;
|
||||
ConnectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
var connectionInitiator = new ConnectionInitiator();
|
||||
connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
|
||||
}
|
||||
|
||||
public static void GoToWebsite()
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
@@ -14,22 +7,26 @@ using System.IO;
|
||||
using System.Management;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.Connections.Multiuser;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
namespace mRemoteNG.App
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private CompatibilityChecker _compatibilityChecker;
|
||||
private AppUpdater _appUpdate;
|
||||
|
||||
public static Startup Instance { get; } = new Startup();
|
||||
|
||||
private Startup()
|
||||
{
|
||||
_compatibilityChecker = new CompatibilityChecker();
|
||||
_appUpdate = new AppUpdater();
|
||||
}
|
||||
|
||||
@@ -41,49 +38,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];
|
||||
|
||||
@@ -6,301 +6,310 @@ using System.Threading;
|
||||
using System.Reflection;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
|
||||
#if PORTABLE
|
||||
using System.Security.Cryptography;
|
||||
using System.Windows.Forms;
|
||||
#else
|
||||
#if !PORTABLE
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
#else
|
||||
using System.Windows.Forms;
|
||||
#endif
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
public class AppUpdater
|
||||
{
|
||||
private UpdateInfo _currentUpdateInfo;
|
||||
private string _changeLog;
|
||||
public class AppUpdater
|
||||
{
|
||||
private WebProxy _webProxy;
|
||||
private Thread _getUpdateInfoThread;
|
||||
private Thread _getChangeLogThread;
|
||||
|
||||
#region Public Properties
|
||||
public UpdateInfo CurrentUpdateInfo => _currentUpdateInfo;
|
||||
#region Public Properties
|
||||
|
||||
public string ChangeLog => _changeLog;
|
||||
public UpdateInfo CurrentUpdateInfo { get; private set; }
|
||||
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
public string ChangeLog { get; private set; }
|
||||
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
public bool IsGetUpdateInfoRunning => _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive;
|
||||
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
private bool IsGetChangeLogRunning => _getChangeLogThread != null && _getChangeLogThread.IsAlive;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
public bool IsDownloadUpdateRunning => _downloadUpdateWebClient != null;
|
||||
|
||||
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;
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public AppUpdater()
|
||||
{
|
||||
SetProxySettings();
|
||||
}
|
||||
|
||||
private void SetProxySettings()
|
||||
{
|
||||
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
|
||||
var proxyAddress = Settings.Default.UpdateProxyAddress;
|
||||
var port = Settings.Default.UpdateProxyPort;
|
||||
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
|
||||
var username = Settings.Default.UpdateProxyAuthUser;
|
||||
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
|
||||
|
||||
SetProxySettings(shouldWeUseProxy, proxyAddress, port, useAuthentication, username, password);
|
||||
}
|
||||
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
}
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (_currentUpdateInfo == null || !_currentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _currentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (_currentUpdateInfo == null || !_currentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (_currentUpdateInfo == null || !_currentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
public void SetProxySettings(bool useProxy, string address, int port, bool useAuthentication, string username, string password)
|
||||
{
|
||||
if (useProxy && !string.IsNullOrEmpty(address))
|
||||
{
|
||||
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
|
||||
|
||||
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_webProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUpdateAvailable()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public void GetUpdateInfoAsync()
|
||||
{
|
||||
if (IsGetUpdateInfoRunning)
|
||||
{
|
||||
_getUpdateInfoThread.Abort();
|
||||
}
|
||||
|
||||
_getUpdateInfoThread = new Thread(GetUpdateInfo);
|
||||
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
|
||||
_getUpdateInfoThread.IsBackground = true;
|
||||
_getUpdateInfoThread.Start();
|
||||
}
|
||||
|
||||
public void GetChangeLogAsync()
|
||||
{
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
|
||||
}
|
||||
|
||||
if (IsGetChangeLogRunning)
|
||||
{
|
||||
_getChangeLogThread.Abort();
|
||||
}
|
||||
|
||||
_getChangeLogThread = new Thread(GetChangeLog);
|
||||
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
|
||||
_getChangeLogThread.IsBackground = true;
|
||||
_getChangeLogThread.Start();
|
||||
}
|
||||
|
||||
public void DownloadUpdateAsync()
|
||||
{
|
||||
if (_downloadUpdateWebClient != null)
|
||||
{
|
||||
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
|
||||
}
|
||||
|
||||
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
|
||||
}
|
||||
#if !PORTABLE
|
||||
_currentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "exe"));
|
||||
CurrentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "msi"));
|
||||
#else
|
||||
var sfd = new SaveFileDialog
|
||||
{
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
|
||||
FileName = _currentUpdateInfo.FileName,
|
||||
FileName = CurrentUpdateInfo.FileName,
|
||||
RestoreDirectory = true
|
||||
};
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
_currentUpdateInfo.UpdateFilePath = sfd.FileName;
|
||||
CurrentUpdateInfo.UpdateFilePath = sfd.FileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
#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};
|
||||
DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, CurrentUpdateInfo.UpdateFilePath);
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
throw (updateAuthenticode.Exception);
|
||||
}
|
||||
|
||||
throw (new Exception(updateAuthenticode.StatusMessage));
|
||||
}
|
||||
#else
|
||||
using (var md5 = MD5.Create())
|
||||
var updateAuthenticode = new Authenticode(CurrentUpdateInfo.UpdateFilePath)
|
||||
{
|
||||
using (var stream = File.OpenRead(_currentUpdateInfo.UpdateFilePath))
|
||||
RequireThumbprintMatch = true,
|
||||
ThumbprintToMatch = CurrentUpdateInfo.CertificateThumbprint
|
||||
};
|
||||
|
||||
if (updateAuthenticode.Verify() != Authenticode.StatusValue.Verified)
|
||||
{
|
||||
if (updateAuthenticode.Status == Authenticode.StatusValue.UnhandledException)
|
||||
{
|
||||
var hash = md5.ComputeHash(stream);
|
||||
var hashString = BitConverter.ToString(hash).Replace("-", "");
|
||||
if (!hashString.Equals(_currentUpdateInfo.CertificateThumbprint))
|
||||
throw new Exception("MD5 Hashes didn't match!");
|
||||
throw updateAuthenticode.Exception;
|
||||
}
|
||||
|
||||
throw new Exception(updateAuthenticode.StatusMessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
using (var cksum = SHA512.Create())
|
||||
{
|
||||
using (var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath))
|
||||
{
|
||||
var hash = cksum.ComputeHash(stream);
|
||||
var hashString = BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
|
||||
if (!hashString.Equals(CurrentUpdateInfo.Checksum))
|
||||
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
|
||||
@@ -314,6 +323,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler GetChangeLogCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler GetChangeLogCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -326,7 +336,8 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
|
||||
|
||||
public event DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEvent
|
||||
{
|
||||
add
|
||||
@@ -340,6 +351,7 @@ namespace mRemoteNG.App.Update
|
||||
}
|
||||
|
||||
private AsyncCompletedEventHandler DownloadUpdateCompletedEventEvent;
|
||||
|
||||
public event AsyncCompletedEventHandler DownloadUpdateCompletedEvent
|
||||
{
|
||||
add
|
||||
@@ -351,6 +363,7 @@ namespace mRemoteNG.App.Update
|
||||
DownloadUpdateCompletedEventEvent = (AsyncCompletedEventHandler)Delegate.Remove(DownloadUpdateCompletedEventEvent, value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -34,23 +34,16 @@ namespace mRemoteNG.App.Update
|
||||
{
|
||||
var trimmedLine = line.Trim();
|
||||
if (trimmedLine.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmedLine.Substring(0, 1).IndexOfAny(commentCharacters) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var parts = trimmedLine.Split(keyValueSeparators, 2);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var key = parts[0].Trim();
|
||||
var value = parts[1].Trim();
|
||||
|
||||
Items.Add(key, value);
|
||||
Items.Add(parts[0].Trim(), parts[1].Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,10 +52,10 @@ namespace mRemoteNG.App.Update
|
||||
private string GetString(string key)
|
||||
{
|
||||
// ReSharper restore MemberCanBePrivate.Local
|
||||
return !Items.ContainsKey(key) ? string.Empty : this.Items[key];
|
||||
return !Items.ContainsKey(key) ? string.Empty : Items[key];
|
||||
}
|
||||
|
||||
public Version GetVersion(string key)
|
||||
public Version GetVersion(string key = "Version")
|
||||
{
|
||||
var value = GetString(key);
|
||||
return string.IsNullOrEmpty(value) ? null : new Version(value);
|
||||
@@ -74,7 +67,7 @@ namespace mRemoteNG.App.Update
|
||||
return string.IsNullOrEmpty(value) ? null : new Uri(value);
|
||||
}
|
||||
|
||||
public string GetThumbprint(string key)
|
||||
public string GetThumbprint(string key = "CertificateThumbprint")
|
||||
{
|
||||
return GetString(key).Replace(" ", "").ToUpperInvariant();
|
||||
}
|
||||
@@ -85,6 +78,11 @@ namespace mRemoteNG.App.Update
|
||||
var sv = value.Split('/');
|
||||
return sv[sv.Length-1];
|
||||
}
|
||||
|
||||
public string GetChecksum(string key = "Checksum")
|
||||
{
|
||||
return GetString(key).Replace(" ", "").ToUpperInvariant();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
|
||||
namespace mRemoteNG.App.Update
|
||||
{
|
||||
@@ -11,8 +12,12 @@ namespace mRemoteNG.App.Update
|
||||
public Uri ChangeLogAddress { get; private set; }
|
||||
public Uri ImageAddress { get; private set; }
|
||||
public Uri ImageLinkAddress { get; private set; }
|
||||
#if !PORTABLE
|
||||
public string CertificateThumbprint { get; private set; }
|
||||
public string FileName { get; private set; }
|
||||
#endif
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public string FileName { get; set; }
|
||||
public string Checksum { get; private set; }
|
||||
|
||||
public static UpdateInfo FromString(string input)
|
||||
{
|
||||
@@ -24,16 +29,48 @@ namespace mRemoteNG.App.Update
|
||||
else
|
||||
{
|
||||
var updateFile = new UpdateFile(input);
|
||||
newInfo.Version = updateFile.GetVersion("Version");
|
||||
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");
|
||||
newInfo.CertificateThumbprint = updateFile.GetThumbprint("CertificateThumbprint");
|
||||
#endif
|
||||
#if !PORTABLE
|
||||
newInfo.CertificateThumbprint = updateFile.GetThumbprint();
|
||||
#endif
|
||||
newInfo.FileName = updateFile.GetFileName();
|
||||
newInfo.IsValid = true;
|
||||
newInfo.Checksum = updateFile.GetChecksum();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using mRemoteNG.UI.Forms;
|
||||
using mRemoteNG.UI.Window;
|
||||
using System;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.UI;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
@@ -116,6 +117,7 @@ namespace mRemoteNG.App
|
||||
}
|
||||
else if (windowType.Equals(WindowType.ComponentsCheck))
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Showing ComponentsCheck window", true);
|
||||
if (_componentscheckForm == null || _componentscheckForm.IsDisposed)
|
||||
{
|
||||
_componentscheckForm = new ComponentsCheckWindow(_componentscheckPanel);
|
||||
|
||||
@@ -23,17 +23,16 @@ 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
|
||||
{
|
||||
var dataProvider = new FileDataProvider(ConnectionFileName);
|
||||
var xmlString = dataProvider.Load();
|
||||
deserializer = new XmlConnectionsDeserializer(xmlString)
|
||||
{
|
||||
AuthenticationRequestor = PromptForPassword
|
||||
};
|
||||
deserializer = new XmlConnectionsDeserializer(xmlString, PromptForPassword);
|
||||
}
|
||||
|
||||
var connectionTreeModel = deserializer.Deserialize();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher != null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -158,7 +158,7 @@ namespace mRemoteNG.Config.Putty
|
||||
|
||||
if (_eventWatcher == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
_eventWatcher.EnableRaisingEvents = false;
|
||||
_eventWatcher.Dispose();
|
||||
@@ -231,7 +231,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_puttyConfFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_puttyConfFile))
|
||||
{
|
||||
@@ -299,7 +299,7 @@ namespace mRemoteNG.Config.Putty
|
||||
{
|
||||
if (!File.Exists(_sessionFile))
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
using (var streamReader = new StreamReader(_sessionFile))
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
// check/continue here so we don't create empty connection objects
|
||||
if(!_importSubOU) continue;
|
||||
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer);
|
||||
ActiveDirectoryImporter.Import(ldapResult.Path, parentContainer, _importSubOU);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Connection.Protocol.Http;
|
||||
@@ -33,6 +34,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
var connectionList = CreateNodesFromTable();
|
||||
var connectionTreeModel = CreateNodeHierarchy(connectionList);
|
||||
Runtime.IsConnectionsFileLoaded = true;
|
||||
return connectionTreeModel;
|
||||
}
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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;
|
||||
|
||||
158
mRemoteV1/Config/Serializers/SqlDatabaseVersionVerifier.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
public class SqlDatabaseVersionVerifier
|
||||
{
|
||||
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
|
||||
|
||||
public SqlDatabaseVersionVerifier(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
if (sqlDatabaseConnector == null)
|
||||
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
|
||||
|
||||
_sqlDatabaseConnector = sqlDatabaseConnector;
|
||||
}
|
||||
|
||||
public bool VerifyDatabaseVersion()
|
||||
{
|
||||
var isVerified = false;
|
||||
try
|
||||
{
|
||||
var databaseVersion = GetDatabaseVersion(_sqlDatabaseConnector);
|
||||
|
||||
if (databaseVersion.Equals(new Version()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 2)) == 0) // 2.2
|
||||
{
|
||||
UpgradeFrom2_2();
|
||||
databaseVersion = new Version(2, 3);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 3)) == 0) // 2.3
|
||||
{
|
||||
UpgradeFrom2_3();
|
||||
databaseVersion = new Version(2, 4);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 4)) == 0) // 2.4
|
||||
{
|
||||
UpgradeFrom2_4();
|
||||
databaseVersion = new Version(2, 5);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 5)) == 0) // 2.5
|
||||
{
|
||||
UpgradeFrom2_5();
|
||||
databaseVersion = new Version(2, 6);
|
||||
}
|
||||
|
||||
if (databaseVersion.CompareTo(new Version(2, 6)) == 0) // 2.6
|
||||
isVerified = true;
|
||||
|
||||
if (isVerified == false)
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg,
|
||||
string.Format(Language.strErrorBadDatabaseVersion, databaseVersion, GeneralAppInfo.ProductName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg,
|
||||
string.Format(Language.strErrorVerifyDatabaseVersionFailed, ex.Message));
|
||||
}
|
||||
return isVerified;
|
||||
}
|
||||
|
||||
private Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
|
||||
{
|
||||
Version databaseVersion;
|
||||
SqlDataReader sqlDataReader = null;
|
||||
try
|
||||
{
|
||||
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||
if (!sqlDatabaseConnector.IsConnected)
|
||||
sqlDatabaseConnector.Connect();
|
||||
sqlDataReader = sqlCommand.ExecuteReader();
|
||||
if (!sqlDataReader.HasRows)
|
||||
return new Version(); // assume new empty database
|
||||
else
|
||||
sqlDataReader.Read();
|
||||
databaseVersion =
|
||||
new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sqlDataReader != null && !sqlDataReader.IsClosed)
|
||||
sqlDataReader.Close();
|
||||
}
|
||||
return databaseVersion;
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_2()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.2 to version 2.3.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD EnableFontSmoothing bit NOT NULL DEFAULT 0,
|
||||
EnableDesktopComposition bit NOT NULL DEFAULT 0,
|
||||
InheritEnableFontSmoothing bit NOT NULL DEFAULT 0,
|
||||
InheritEnableDesktopComposition bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_3()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.3 to version 2.4.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD UseCredSsp bit NOT NULL DEFAULT 1,
|
||||
InheritUseCredSsp bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_4()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.4 to version 2.5.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD LoadBalanceInfo varchar (1024) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
AutomaticResize bit NOT NULL DEFAULT 1,
|
||||
InheritLoadBalanceInfo bit NOT NULL DEFAULT 0,
|
||||
InheritAutomaticResize bit NOT NULL DEFAULT 0;";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void UpgradeFrom2_5()
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Upgrading database from version 2.5 to version 2.6.");
|
||||
const string sqlText = @"
|
||||
ALTER TABLE tblCons
|
||||
ADD RDPMinutesToIdleTimeout int NOT NULL DEFAULT 0,
|
||||
RDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
SoundQuality varchar (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL DEFAULT 'Dynamic',
|
||||
InheritRDPMinutesToIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
InheritRDPAlertIdleTimeout bit NOT NULL DEFAULT 0,
|
||||
InheritSoundQuality bit NOT NULL DEFAULT 0;
|
||||
UPDATE tblRoot
|
||||
SET ConfVersion='2.6'";
|
||||
var sqlCommand = new SqlCommand(sqlText, _sqlDatabaseConnector.SqlConnection);
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Security;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
@@ -13,14 +14,15 @@ namespace mRemoteNG.Config.Serializers
|
||||
private readonly SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter = new SaveFilter();
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
|
||||
{
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
}
|
||||
|
||||
public XmlConnectionNodeSerializer(ICryptographyProvider cryptographyProvider, SecureString encryptionKey, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (encryptionKey == null)
|
||||
throw new ArgumentNullException(nameof(encryptionKey));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_encryptionKey = encryptionKey;
|
||||
_saveFilter = saveFilter;
|
||||
@@ -44,6 +46,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("Descr", connectionInfo.Description));
|
||||
element.Add(new XAttribute("Icon", connectionInfo.Icon));
|
||||
element.Add(new XAttribute("Panel", connectionInfo.Panel));
|
||||
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
|
||||
|
||||
element.Add(_saveFilter.SaveUsername
|
||||
? new XAttribute("Username", connectionInfo.Username)
|
||||
@@ -67,6 +70,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("RenderingEngine", connectionInfo.RenderingEngine));
|
||||
element.Add(new XAttribute("ICAEncryptionStrength", connectionInfo.ICAEncryptionStrength));
|
||||
element.Add(new XAttribute("RDPAuthenticationLevel", connectionInfo.RDPAuthenticationLevel));
|
||||
element.Add(new XAttribute("RDPMinutesToIdleTimeout", connectionInfo.RDPMinutesToIdleTimeout));
|
||||
element.Add(new XAttribute("RDPAlertIdleTimeout", connectionInfo.RDPAlertIdleTimeout));
|
||||
element.Add(new XAttribute("LoadBalanceInfo", connectionInfo.LoadBalanceInfo));
|
||||
element.Add(new XAttribute("Colors", connectionInfo.Colors));
|
||||
element.Add(new XAttribute("Resolution", connectionInfo.Resolution));
|
||||
@@ -159,6 +164,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", connectionInfo.Inheritance.Username.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", connectionInfo.Inheritance.ICAEncryptionStrength.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", connectionInfo.Inheritance.RDPAuthenticationLevel.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", connectionInfo.Inheritance.RDPMinutesToIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", connectionInfo.Inheritance.RDPAlertIdleTimeout.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", connectionInfo.Inheritance.LoadBalanceInfo.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", connectionInfo.Inheritance.PreExtApp.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", connectionInfo.Inheritance.PostExtApp.ToString()));
|
||||
@@ -214,6 +221,8 @@ namespace mRemoteNG.Config.Serializers
|
||||
element.Add(new XAttribute("InheritUsername", false.ToString()));
|
||||
element.Add(new XAttribute("InheritICAEncryptionStrength", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAuthenticationLevel", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", false.ToString()));
|
||||
element.Add(new XAttribute("InheritLoadBalanceInfo", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPreExtApp", false.ToString()));
|
||||
element.Add(new XAttribute("InheritPostExtApp", false.ToString()));
|
||||
|
||||
@@ -29,12 +29,13 @@ namespace mRemoteNG.Config.Serializers
|
||||
//TODO find way to inject data source info
|
||||
private string ConnectionFileName = "";
|
||||
private const double MaxSupportedConfVersion = 2.6;
|
||||
private RootNodeInfo _rootNodeInfo;
|
||||
private RootNodeInfo _rootNodeInfo = new RootNodeInfo(RootNodeType.Connection);
|
||||
|
||||
public Func<SecureString> AuthenticationRequestor { get; set; }
|
||||
|
||||
public XmlConnectionsDeserializer(string xml)
|
||||
public XmlConnectionsDeserializer(string xml, Func<SecureString> authenticationRequestor = null)
|
||||
{
|
||||
AuthenticationRequestor = authenticationRequestor;
|
||||
LoadXmlConnectionData(xml);
|
||||
ValidateConnectionFileVersion();
|
||||
}
|
||||
@@ -91,7 +92,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
Runtime.IsConnectionsFileLoaded = false;
|
||||
|
||||
var rootXmlElement = _xmlDocument.DocumentElement;
|
||||
_rootNodeInfo = InitializeRootNode(rootXmlElement);
|
||||
InitializeRootNode(rootXmlElement);
|
||||
CreateDecryptor(_rootNodeInfo, rootXmlElement);
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
connectionTreeModel.AddRootNode(_rootNodeInfo);
|
||||
@@ -138,14 +139,10 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
}
|
||||
|
||||
private RootNodeInfo InitializeRootNode(XmlElement connectionsRootElement)
|
||||
private void InitializeRootNode(XmlElement connectionsRootElement)
|
||||
{
|
||||
var rootNodeName = connectionsRootElement?.Attributes["Name"].Value.Trim();
|
||||
var rootInfo = new RootNodeInfo(RootNodeType.Connection)
|
||||
{
|
||||
Name = rootNodeName
|
||||
};
|
||||
return rootInfo;
|
||||
_rootNodeInfo.Name = rootNodeName;
|
||||
}
|
||||
|
||||
private void CreateDecryptor(RootNodeInfo rootNodeInfo, XmlElement connectionsRootElement = null)
|
||||
@@ -488,8 +485,13 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
if (_confVersion >= 2.6)
|
||||
{
|
||||
connectionInfo.ConstantID = xmlnode.Attributes["Id"]?.Value ?? connectionInfo.ConstantID;
|
||||
connectionInfo.SoundQuality = (ProtocolRDP.RDPSoundQuality)Tools.MiscTools.StringToEnum(typeof(ProtocolRDP.RDPSoundQuality), Convert.ToString(xmlnode.Attributes["SoundQuality"].Value));
|
||||
connectionInfo.Inheritance.SoundQuality = bool.Parse(xmlnode.Attributes["InheritSoundQuality"].Value);
|
||||
connectionInfo.RDPMinutesToIdleTimeout = Convert.ToInt32(xmlnode.Attributes["RDPMinutesToIdleTimeout"]?.Value ?? "0");
|
||||
connectionInfo.Inheritance.RDPMinutesToIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPMinutesToIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["RDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
connectionInfo.Inheritance.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPAlertIdleTimeout"]?.Value ?? "False");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.Connection;
|
||||
@@ -14,10 +15,17 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private SecureString _encryptionKey;
|
||||
private readonly SaveFilter _saveFilter;
|
||||
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider)
|
||||
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, SaveFilter saveFilter)
|
||||
{
|
||||
if (cryptographyProvider == null)
|
||||
throw new ArgumentNullException(nameof(cryptographyProvider));
|
||||
if (saveFilter == null)
|
||||
throw new ArgumentNullException(nameof(saveFilter));
|
||||
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_saveFilter = saveFilter;
|
||||
}
|
||||
|
||||
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
|
||||
@@ -77,7 +85,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey);
|
||||
var connectionSerializer = new XmlConnectionNodeSerializer(_cryptographyProvider, _encryptionKey, _saveFilter);
|
||||
return connectionSerializer.SerializeConnectionInfo(connectionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
var xml = "";
|
||||
try
|
||||
{
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider);
|
||||
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, SaveFilter);
|
||||
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
|
||||
xml = WriteXmlToString(xmlDocument);
|
||||
}
|
||||
|
||||
@@ -20,47 +20,59 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
public void LoadExternalAppsFromXML()
|
||||
{
|
||||
var oldPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\" + GeneralAppInfo.ProductName + "\\" + SettingsFileInfo.ExtAppsFilesName;
|
||||
var newPath = SettingsFileInfo.SettingsPath + "\\" + SettingsFileInfo.ExtAppsFilesName;
|
||||
#if !PORTABLE
|
||||
var oldPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), GeneralAppInfo.ProductName, SettingsFileInfo.ExtAppsFilesName);
|
||||
#endif
|
||||
var newPath = Path.Combine(SettingsFileInfo.SettingsPath, SettingsFileInfo.ExtAppsFilesName);
|
||||
var xDom = new XmlDocument();
|
||||
if (File.Exists(newPath))
|
||||
{
|
||||
Logger.Instance.Info($"Loading External Apps from: {newPath}");
|
||||
xDom.Load(newPath);
|
||||
}
|
||||
#if !PORTABLE
|
||||
}
|
||||
else if (File.Exists(oldPath))
|
||||
{
|
||||
xDom.Load(oldPath);
|
||||
Logger.Instance.Info($"Loading External Apps from: {oldPath}");
|
||||
xDom.Load(oldPath);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Instance.Warn("Loading External Apps failed: Could not FIND file!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xDom.DocumentElement != null)
|
||||
foreach (XmlElement xEl in xDom.DocumentElement.ChildNodes)
|
||||
if (xDom.DocumentElement == null)
|
||||
{
|
||||
Logger.Instance.Warn("Loading External Apps failed: Could not LOAD file!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XmlElement xEl in xDom.DocumentElement.ChildNodes)
|
||||
{
|
||||
var extA = new ExternalTool
|
||||
{
|
||||
var extA = new ExternalTool
|
||||
{
|
||||
DisplayName = xEl.Attributes["DisplayName"].Value,
|
||||
FileName = xEl.Attributes["FileName"].Value,
|
||||
Arguments = xEl.Attributes["Arguments"].Value
|
||||
};
|
||||
DisplayName = xEl.Attributes["DisplayName"].Value,
|
||||
FileName = xEl.Attributes["FileName"].Value,
|
||||
Arguments = xEl.Attributes["Arguments"].Value
|
||||
};
|
||||
|
||||
if (xEl.HasAttribute("WaitForExit"))
|
||||
{
|
||||
extA.WaitForExit = bool.Parse(xEl.Attributes["WaitForExit"].Value);
|
||||
}
|
||||
|
||||
if (xEl.HasAttribute("TryToIntegrate"))
|
||||
{
|
||||
extA.TryIntegrate = bool.Parse(xEl.Attributes["TryToIntegrate"].Value);
|
||||
}
|
||||
|
||||
Runtime.ExternalTools.Add(extA);
|
||||
if (xEl.HasAttribute("WaitForExit"))
|
||||
{
|
||||
extA.WaitForExit = bool.Parse(xEl.Attributes["WaitForExit"].Value);
|
||||
}
|
||||
|
||||
if (xEl.HasAttribute("TryToIntegrate"))
|
||||
{
|
||||
extA.TryIntegrate = bool.Parse(xEl.Attributes["TryToIntegrate"].Value);
|
||||
}
|
||||
|
||||
Logger.Instance.Info($"Adding External App: {extA.DisplayName} {extA.FileName} {extA.Arguments}");
|
||||
Runtime.ExternalTools.Add(extA);
|
||||
}
|
||||
|
||||
_MainForm.SwitchToolBarText(Convert.ToBoolean(mRemoteNG.Settings.Default.ExtAppsTBShowText));
|
||||
|
||||
frmMain.Default.AddExternalToolsToToolBar();
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace mRemoteNG.Config.Settings
|
||||
}
|
||||
else
|
||||
{
|
||||
Startup.Instance.SetDefaultLayout();
|
||||
frmMain.Default.SetDefaultLayout();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -9,6 +9,7 @@ using mRemoteNG.Themes;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
|
||||
@@ -16,22 +17,17 @@ namespace mRemoteNG.Config.Settings
|
||||
{
|
||||
public class SettingsLoader
|
||||
{
|
||||
private frmMain _mainForm;
|
||||
private readonly LayoutSettingsLoader _layoutSettingsLoader;
|
||||
private readonly LayoutSettingsLoader _layoutSettingsLoader;
|
||||
private readonly ExternalAppsLoader _externalAppsLoader;
|
||||
|
||||
public frmMain MainForm
|
||||
private frmMain MainForm { get; set; }
|
||||
|
||||
|
||||
public SettingsLoader(frmMain mainForm)
|
||||
{
|
||||
get { return _mainForm; }
|
||||
set { _mainForm = value; }
|
||||
}
|
||||
|
||||
|
||||
public SettingsLoader(frmMain mainForm)
|
||||
{
|
||||
_mainForm = mainForm;
|
||||
_layoutSettingsLoader = new LayoutSettingsLoader(_mainForm);
|
||||
_externalAppsLoader = new ExternalAppsLoader(_mainForm);
|
||||
MainForm = mainForm;
|
||||
_layoutSettingsLoader = new LayoutSettingsLoader(MainForm);
|
||||
_externalAppsLoader = new ExternalAppsLoader(MainForm);
|
||||
}
|
||||
|
||||
#region Public Methods
|
||||
@@ -85,41 +81,40 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
private static void SetSupportedCulture()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.OverrideUICulture != "" && SupportedCultures.IsNameSupported(mRemoteNG.Settings.Default.OverrideUICulture))
|
||||
{
|
||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(mRemoteNG.Settings.Default.OverrideUICulture);
|
||||
Logger.Instance.InfoFormat("Override Culture: {0}/{1}", Thread.CurrentThread.CurrentUICulture.Name, Thread.CurrentThread.CurrentUICulture.NativeName);
|
||||
}
|
||||
if (mRemoteNG.Settings.Default.OverrideUICulture == "" ||
|
||||
!SupportedCultures.IsNameSupported(mRemoteNG.Settings.Default.OverrideUICulture)) return;
|
||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(mRemoteNG.Settings.Default.OverrideUICulture);
|
||||
Logger.Instance.InfoFormat("Override Culture: {0}/{1}", Thread.CurrentThread.CurrentUICulture.Name, Thread.CurrentThread.CurrentUICulture.NativeName);
|
||||
}
|
||||
|
||||
private void SetApplicationWindowPositionAndSize()
|
||||
{
|
||||
_mainForm.WindowState = FormWindowState.Normal;
|
||||
MainForm.WindowState = FormWindowState.Normal;
|
||||
if (mRemoteNG.Settings.Default.MainFormState == FormWindowState.Normal)
|
||||
{
|
||||
if (!mRemoteNG.Settings.Default.MainFormLocation.IsEmpty)
|
||||
_mainForm.Location = mRemoteNG.Settings.Default.MainFormLocation;
|
||||
MainForm.Location = mRemoteNG.Settings.Default.MainFormLocation;
|
||||
if (!mRemoteNG.Settings.Default.MainFormSize.IsEmpty)
|
||||
_mainForm.Size = mRemoteNG.Settings.Default.MainFormSize;
|
||||
MainForm.Size = mRemoteNG.Settings.Default.MainFormSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mRemoteNG.Settings.Default.MainFormRestoreLocation.IsEmpty)
|
||||
_mainForm.Location = mRemoteNG.Settings.Default.MainFormRestoreLocation;
|
||||
MainForm.Location = mRemoteNG.Settings.Default.MainFormRestoreLocation;
|
||||
if (!mRemoteNG.Settings.Default.MainFormRestoreSize.IsEmpty)
|
||||
_mainForm.Size = mRemoteNG.Settings.Default.MainFormRestoreSize;
|
||||
MainForm.Size = mRemoteNG.Settings.Default.MainFormRestoreSize;
|
||||
}
|
||||
|
||||
if (mRemoteNG.Settings.Default.MainFormState == FormWindowState.Maximized)
|
||||
{
|
||||
_mainForm.WindowState = FormWindowState.Maximized;
|
||||
MainForm.WindowState = FormWindowState.Maximized;
|
||||
}
|
||||
|
||||
// Make sure the form is visible on the screen
|
||||
const int minHorizontal = 300;
|
||||
const int minVertical = 150;
|
||||
var screenBounds = Screen.FromHandle(_mainForm.Handle).Bounds;
|
||||
var newBounds = _mainForm.Bounds;
|
||||
var screenBounds = Screen.FromHandle(MainForm.Handle).Bounds;
|
||||
var newBounds = MainForm.Bounds;
|
||||
|
||||
if (newBounds.Right < screenBounds.Left + minHorizontal)
|
||||
newBounds.X = screenBounds.Left + minHorizontal - newBounds.Width;
|
||||
@@ -130,39 +125,32 @@ namespace mRemoteNG.Config.Settings
|
||||
if (newBounds.Top > screenBounds.Bottom - minVertical)
|
||||
newBounds.Y = screenBounds.Bottom - minVertical;
|
||||
|
||||
_mainForm.Location = newBounds.Location;
|
||||
MainForm.Location = newBounds.Location;
|
||||
}
|
||||
|
||||
private void SetAutoSave()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.AutoSaveEveryMinutes > 0)
|
||||
{
|
||||
_mainForm.tmrAutoSave.Interval = Convert.ToInt32(mRemoteNG.Settings.Default.AutoSaveEveryMinutes * 60000);
|
||||
_mainForm.tmrAutoSave.Enabled = true;
|
||||
}
|
||||
if (mRemoteNG.Settings.Default.AutoSaveEveryMinutes <= 0) return;
|
||||
MainForm.tmrAutoSave.Interval = Convert.ToInt32(mRemoteNG.Settings.Default.AutoSaveEveryMinutes * 60000);
|
||||
MainForm.tmrAutoSave.Enabled = true;
|
||||
}
|
||||
|
||||
private void SetKioskMode()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.MainFormKiosk)
|
||||
{
|
||||
_mainForm.Fullscreen.Value = true;
|
||||
_mainForm.mMenViewFullscreen.Checked = true;
|
||||
}
|
||||
if (!mRemoteNG.Settings.Default.MainFormKiosk) return;
|
||||
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()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.UseCustomPuttyPath)
|
||||
PuttyBase.PuttyPath = Convert.ToString(mRemoteNG.Settings.Default.CustomPuttyPath);
|
||||
else
|
||||
PuttyBase.PuttyPath = GeneralAppInfo.PuttyPath;
|
||||
PuttyBase.PuttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? Convert.ToString(mRemoteNG.Settings.Default.CustomPuttyPath) : GeneralAppInfo.PuttyPath;
|
||||
}
|
||||
|
||||
private static void EnsureSettingsAreSavedInNewestVersion()
|
||||
@@ -187,16 +175,16 @@ namespace mRemoteNG.Config.Settings
|
||||
// needs to be cleared here because we know that we just updated.
|
||||
mRemoteNG.Settings.Default.UpdatePending = false;
|
||||
}
|
||||
|
||||
public void SetToolbarsDefault()
|
||||
|
||||
private void SetToolbarsDefault()
|
||||
{
|
||||
ToolStripPanelFromString("top").Join(MainForm.tsQuickConnect, new Point(300, 0));
|
||||
MainForm.tsQuickConnect.Visible = true;
|
||||
ToolStripPanelFromString("bottom").Join(MainForm.tsExternalTools, new Point(3, 0));
|
||||
MainForm.tsExternalTools.Visible = false;
|
||||
}
|
||||
|
||||
public void LoadToolbarsFromSettings()
|
||||
|
||||
private void LoadToolbarsFromSettings()
|
||||
{
|
||||
if (mRemoteNG.Settings.Default.QuickyTBLocation.X > mRemoteNG.Settings.Default.ExtAppsTBLocation.X)
|
||||
{
|
||||
@@ -238,13 +226,13 @@ namespace mRemoteNG.Config.Settings
|
||||
return MainForm.tsContainer.TopToolStripPanel;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadPanelsFromXml()
|
||||
|
||||
private void LoadPanelsFromXml()
|
||||
{
|
||||
_layoutSettingsLoader.LoadPanelsFromXml();
|
||||
}
|
||||
|
||||
public void LoadExternalAppsFromXml()
|
||||
|
||||
private void LoadExternalAppsFromXml()
|
||||
{
|
||||
_externalAppsLoader.LoadExternalAppsFromXML();
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace mRemoteNG.Config.Settings
|
||||
|
||||
mRemoteNG.Settings.Default.MainFormState = with1.WindowState;
|
||||
|
||||
if (with1.Fullscreen != null)
|
||||
if (with1._fullscreen != null)
|
||||
{
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1.Fullscreen.Value;
|
||||
mRemoteNG.Settings.Default.MainFormKiosk = with1._fullscreen.Value;
|
||||
}
|
||||
|
||||
mRemoteNG.Settings.Default.FirstStart = false;
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace mRemoteNG.Connection
|
||||
private ProtocolICA.EncryptionStrength _icaEncryption;
|
||||
private bool _useConsoleSession;
|
||||
private ProtocolRDP.AuthenticationLevel _rdpAuthenticationLevel;
|
||||
private int _rdpMinutesToIdleTimeout;
|
||||
private bool _rdpAlertIdleTimeout;
|
||||
private string _loadBalanceInfo;
|
||||
private HTTPBase.RenderingEngine _renderingEngine;
|
||||
private bool _useCredSsp;
|
||||
@@ -225,6 +227,30 @@ namespace mRemoteNG.Connection
|
||||
set { SetField(ref _rdpAuthenticationLevel, value, "RDPAuthenticationLevel"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout")]
|
||||
public virtual int RDPMinutesToIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout); }
|
||||
set {
|
||||
if(value < 0) {
|
||||
value = 0;
|
||||
} else if(value > 240) {
|
||||
value = 240;
|
||||
}
|
||||
SetField(ref _rdpMinutesToIdleTimeout, value, "RDPMinutesToIdleTimeout");
|
||||
}
|
||||
}
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout")]
|
||||
public bool RDPAlertIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout); }
|
||||
set { SetField(ref _rdpAlertIdleTimeout, value, "RDPAlertIdleTimeout"); }
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo")]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -83,9 +83,19 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameAuthenticationLevel"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionAuthenticationLevel"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set;}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPAuthenticationLevel {get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPMinutesToIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPMinutesToIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RDPMinutesToIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRDPAlertIdleTimeout"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRDPAlertIdleTimeout"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))] public bool RDPAlertIdleTimeout { get; set; }
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 4),
|
||||
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameLoadBalanceInfo"),
|
||||
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionLoadBalanceInfo"),
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool LoadBalanceInfo {get; set;}
|
||||
|
||||
@@ -12,14 +12,52 @@ using TabPage = Crownwood.Magic.Controls.TabPage;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public static class ConnectionInitiator
|
||||
public class ConnectionInitiator : IConnectionInitiator
|
||||
{
|
||||
public static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
public void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
|
||||
{
|
||||
OpenConnection(containerInfo, force, null);
|
||||
}
|
||||
|
||||
private static void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
public void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SwitchToOpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
var interfaceControl = FindConnectionContainer(connectionInfo);
|
||||
if (interfaceControl == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)interfaceControl.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)interfaceControl.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)interfaceControl.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Private
|
||||
private void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
var children = containerInfo.Children;
|
||||
if (children.Count == 0) return;
|
||||
@@ -33,31 +71,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, ConnectionInfo.Force.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenConnection(connectionInfo, force, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
private void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force, Form conForm)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -104,7 +118,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionOpenFailed + Environment.NewLine + ex.Message);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionOpenFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,19 +129,6 @@ namespace mRemoteNG.Connection
|
||||
extA?.Start(connectionInfo);
|
||||
}
|
||||
|
||||
public static bool SwitchToOpenConnection(ConnectionInfo nCi)
|
||||
{
|
||||
var IC = FindConnectionContainer(nCi);
|
||||
if (IC == null) return false;
|
||||
var connectionWindow = (ConnectionWindow)IC.FindForm();
|
||||
connectionWindow?.Focus();
|
||||
var findForm = (ConnectionWindow)IC.FindForm();
|
||||
findForm?.Show(frmMain.Default.pnlDock);
|
||||
var tabPage = (TabPage)IC.Parent;
|
||||
tabPage.Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static InterfaceControl FindConnectionContainer(ConnectionInfo connectionInfo)
|
||||
{
|
||||
if (connectionInfo.OpenConnections.Count <= 0) return null;
|
||||
@@ -185,11 +186,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
Control connectionContainer = ((ConnectionWindow)connectionForm).AddConnectionTab(connectionInfo);
|
||||
|
||||
if (connectionInfo.Protocol == ProtocolType.IntApp)
|
||||
{
|
||||
if (Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon != null)
|
||||
((TabPage)connectionContainer).Icon = Runtime.GetExtAppByName(connectionInfo.ExtApp).Icon;
|
||||
}
|
||||
if (connectionInfo.Protocol != ProtocolType.IntApp) return connectionContainer;
|
||||
|
||||
var extT = Runtime.GetExtAppByName(connectionInfo.ExtApp);
|
||||
|
||||
if(extT == null) return connectionContainer;
|
||||
|
||||
if (extT.Icon != null)
|
||||
((TabPage)connectionContainer).Icon = extT.Icon;
|
||||
|
||||
return connectionContainer;
|
||||
}
|
||||
|
||||
@@ -210,10 +215,9 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
newProtocol.InterfaceControl = new InterfaceControl(connectionContainer, newProtocol, connectionInfo);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Event handlers
|
||||
private static void Prot_Event_Disconnected(object sender, string disconnectedMessage)
|
||||
{
|
||||
try
|
||||
@@ -230,7 +234,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, string.Format(Language.strProtocolEventDisconnectFailed, ex.Message), true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strProtocolEventDisconnectFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +244,15 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
var Prot = (ProtocolBase)sender;
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strConnenctionCloseEvent, true);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, Prot.InterfaceControl.Info.Hostname, Prot.InterfaceControl.Info.Protocol.ToString(), Environment.UserName));
|
||||
string connDetail;
|
||||
if (Prot.InterfaceControl.Info.Hostname == "" && Prot.InterfaceControl.Info.Protocol == ProtocolType.IntApp)
|
||||
connDetail = Prot.InterfaceControl.Info.ExtApp;
|
||||
else if (Prot.InterfaceControl.Info.Hostname != "")
|
||||
connDetail = Prot.InterfaceControl.Info.Hostname;
|
||||
else
|
||||
connDetail = "UNKNOWN";
|
||||
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ReportMsg, string.Format(Language.strConnenctionClosedByUser, connDetail, Prot.InterfaceControl.Info.Protocol, Environment.UserName));
|
||||
Prot.InterfaceControl.Info.OpenConnections.Remove(Prot);
|
||||
|
||||
if (Prot.InterfaceControl.Info.PostExtApp == "") return;
|
||||
@@ -249,7 +261,7 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnenctionCloseEventFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnenctionCloseEventFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,8 +285,9 @@ namespace mRemoteNG.Connection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strConnectionEventConnectionFailed + Environment.NewLine + ex.Message, true);
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strConnectionEventConnectionFailed, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using mRemoteNG.App;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
mRemoteV1/Connection/IConnectionInitiator.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using mRemoteNG.Container;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
{
|
||||
public interface IConnectionInitiator
|
||||
{
|
||||
void OpenConnection(ConnectionInfo connectionInfo);
|
||||
|
||||
void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None);
|
||||
|
||||
void OpenConnection(ConnectionInfo connectionInfo, ConnectionInfo.Force force);
|
||||
|
||||
bool SwitchToOpenConnection(ConnectionInfo connectionInfo);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ namespace mRemoteNG.Connection.Protocol.Http
|
||||
WebBrowser objWebBrowser = wBrowser as WebBrowser;
|
||||
if (objWebBrowser == null)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
// This can only be set once the WebBrowser control is shown, it will throw a COM exception otherwise.
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace mRemoteNG.Connection.Protocol.ICA
|
||||
{
|
||||
if (((int)Force & (int)ConnectionInfo.Force.NoCredentials) == (int)ConnectionInfo.Force.NoCredentials)
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
string _user = _Info.Username;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Messages;
|
||||
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
@@ -20,41 +21,52 @@ namespace mRemoteNG.Connection.Protocol
|
||||
#region Public Methods
|
||||
public override bool Initialize()
|
||||
{
|
||||
if (InterfaceControl.Info != null)
|
||||
{
|
||||
_externalTool = Runtime.GetExtAppByName(Convert.ToString(InterfaceControl.Info.ExtApp));
|
||||
_externalTool.ConnectionInfo = InterfaceControl.Info;
|
||||
}
|
||||
|
||||
return base.Initialize();
|
||||
if (InterfaceControl.Info == null) return base.Initialize();
|
||||
|
||||
_externalTool = Runtime.GetExtAppByName(InterfaceControl.Info.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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace mRemoteNG.Connection
|
||||
var puttyProcess = new PuttyProcessController();
|
||||
if (!puttyProcess.Start())
|
||||
{
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
if (puttyProcess.SelectListBoxItem(PuttySession))
|
||||
{
|
||||
|
||||
@@ -5,30 +5,26 @@ using mRemoteNG.UI.Window;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using Timer = System.Windows.Forms.Timer;
|
||||
|
||||
namespace mRemoteNG.Messages
|
||||
{
|
||||
public class MessageCollector
|
||||
{
|
||||
private Timer _ECTimer;
|
||||
private ErrorAndInfoWindow _MCForm;
|
||||
|
||||
public ErrorAndInfoWindow MCForm
|
||||
{
|
||||
get { return _MCForm; }
|
||||
set { _MCForm = value; }
|
||||
}
|
||||
private ErrorAndInfoWindow MCForm { get; set; }
|
||||
|
||||
public MessageCollector(ErrorAndInfoWindow MessageCollectorForm)
|
||||
{
|
||||
_MCForm = MessageCollectorForm;
|
||||
MCForm = MessageCollectorForm;
|
||||
CreateTimer();
|
||||
}
|
||||
|
||||
#region Public Methods
|
||||
public void AddMessage(MessageClass MsgClass, string MsgText, bool OnlyLog = false)
|
||||
{
|
||||
Message nMsg = new Message(MsgClass, MsgText, DateTime.Now);
|
||||
var nMsg = new Message(MsgClass, MsgText, DateTime.Now);
|
||||
|
||||
if (nMsg.MsgClass == MessageClass.ReportMsg)
|
||||
{
|
||||
@@ -78,25 +74,25 @@ namespace mRemoteNG.Messages
|
||||
else
|
||||
ShowMessageBox(nMsg);
|
||||
|
||||
ListViewItem lvItem = BuildListViewItem(nMsg);
|
||||
var lvItem = BuildListViewItem(nMsg);
|
||||
AddToList(lvItem);
|
||||
}
|
||||
|
||||
private void AddInfoMessage(Message nMsg)
|
||||
private static void AddInfoMessage(Message nMsg)
|
||||
{
|
||||
Debug.Print("Info: " + nMsg.MsgText);
|
||||
if (Settings.Default.WriteLogFile)
|
||||
Logger.Instance.Info(nMsg.MsgText);
|
||||
}
|
||||
|
||||
private void AddWarningMessage(Message nMsg)
|
||||
private static void AddWarningMessage(Message nMsg)
|
||||
{
|
||||
Debug.Print("Warning: " + nMsg.MsgText);
|
||||
if (Settings.Default.WriteLogFile)
|
||||
Logger.Instance.Warn(nMsg.MsgText);
|
||||
}
|
||||
|
||||
private void AddErrorMessage(Message nMsg)
|
||||
private static void AddErrorMessage(Message nMsg)
|
||||
{
|
||||
Debug.Print("Error: " + nMsg.MsgText);
|
||||
Logger.Instance.Error(nMsg.MsgText);
|
||||
@@ -111,7 +107,7 @@ namespace mRemoteNG.Messages
|
||||
|
||||
private static ListViewItem BuildListViewItem(Message nMsg)
|
||||
{
|
||||
ListViewItem lvItem = new ListViewItem
|
||||
var lvItem = new ListViewItem
|
||||
{
|
||||
ImageIndex = Convert.ToInt32(nMsg.MsgClass),
|
||||
Text = nMsg.MsgText.Replace(Environment.NewLine, " "),
|
||||
@@ -120,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);
|
||||
}
|
||||
@@ -150,12 +146,12 @@ namespace mRemoteNG.Messages
|
||||
|
||||
private void SwitchToMessage()
|
||||
{
|
||||
_MCForm.PreviousActiveForm = (DockContent)frmMain.Default.pnlDock.ActiveContent;
|
||||
MCForm.PreviousActiveForm = (DockContent)frmMain.Default.pnlDock.ActiveContent;
|
||||
ShowMCForm();
|
||||
_MCForm.lvErrorCollector.Focus();
|
||||
_MCForm.lvErrorCollector.SelectedItems.Clear();
|
||||
_MCForm.lvErrorCollector.Items[0].Selected = true;
|
||||
_MCForm.lvErrorCollector.FocusedItem = _MCForm.lvErrorCollector.Items[0];
|
||||
MCForm.lvErrorCollector.Focus();
|
||||
MCForm.lvErrorCollector.SelectedItems.Clear();
|
||||
MCForm.lvErrorCollector.Items[0].Selected = true;
|
||||
MCForm.lvErrorCollector.FocusedItem = MCForm.lvErrorCollector.Items[0];
|
||||
}
|
||||
|
||||
private static void ShowMessageBox(Message Msg)
|
||||
@@ -181,26 +177,26 @@ namespace mRemoteNG.Messages
|
||||
{
|
||||
if (frmMain.Default.pnlDock.InvokeRequired)
|
||||
{
|
||||
ShowMCFormCB d = new ShowMCFormCB(ShowMCForm);
|
||||
var d = new ShowMCFormCB(ShowMCForm);
|
||||
frmMain.Default.pnlDock.Invoke(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
_MCForm.Show(frmMain.Default.pnlDock);
|
||||
MCForm.Show(frmMain.Default.pnlDock);
|
||||
}
|
||||
}
|
||||
|
||||
delegate void AddToListCB(ListViewItem lvItem);
|
||||
private delegate void AddToListCB(ListViewItem lvItem);
|
||||
private void AddToList(ListViewItem lvItem)
|
||||
{
|
||||
if (_MCForm.lvErrorCollector.InvokeRequired)
|
||||
if (MCForm.lvErrorCollector.InvokeRequired)
|
||||
{
|
||||
AddToListCB d = new AddToListCB(AddToList);
|
||||
_MCForm.lvErrorCollector.Invoke(d, new object[] { lvItem });
|
||||
var d = new AddToListCB(AddToList);
|
||||
MCForm.lvErrorCollector.Invoke(d, new object[] { lvItem });
|
||||
}
|
||||
else
|
||||
{
|
||||
_MCForm.lvErrorCollector.Items.Insert(0, lvItem);
|
||||
MCForm.lvErrorCollector.Items.Insert(0, lvItem);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -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")]
|
||||
|
||||
|
||||
56
mRemoteV1/Properties/Settings.Designer.cs
generated
@@ -1873,7 +1873,8 @@ namespace mRemoteNG {
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("de,el,en,en-US,es-AR,es,fr,hu,it,ja-JP,nb-NO,nl,pt,pt-BR,pl,ru,uk,zh-CN,zh-TW")]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("de,el,en,en-US,es-AR,es,fr,hu,it,ja-JP,nb-NO,nl,pt,pt-BR,pl,ru,uk,tr-TR,zh-CN,zh-" +
|
||||
"TW")]
|
||||
public string SupportedUICultures {
|
||||
get {
|
||||
return ((string)(this["SupportedUICultures"]));
|
||||
@@ -2098,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()]
|
||||
@@ -2346,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="SupportedUICultures" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">de,el,en,en-US,es-AR,es,fr,hu,it,ja-JP,nb-NO,nl,pt,pt-BR,pl,ru,uk,zh-CN,zh-TW</Value>
|
||||
<Value Profile="(Default)">de,el,en,en-US,es-AR,es,fr,hu,it,ja-JP,nb-NO,nl,pt,pt-BR,pl,ru,uk,tr-TR,zh-CN,zh-TW</Value>
|
||||
</Setting>
|
||||
<Setting Name="ConDefaultRDGatewayHostname" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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 ,
|
||||
|
||||
@@ -1,13 +1,78 @@
|
||||
<!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>SSH File Transfer</title>
|
||||
<link href="Main.css" rel="stylesheet" type="text/css" />
|
||||
<title>SSH File Transfer</title>
|
||||
<link href="Main.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>
|
||||
Sorry, not yet...</p>
|
||||
<p class="heading1">
|
||||
Introduction to SSH File Transfer
|
||||
</p>
|
||||
<p>
|
||||
SSH File Transfer functionality allows you to securely transfer files to a remote host over an encrypted tunnel using either SFTP or SCP.
|
||||
</p>
|
||||
|
||||
<p class="heading1">
|
||||
Use Cases
|
||||
</p>
|
||||
<p>
|
||||
The primary use case is to upload individual files, such as configuration files, to a remote host.
|
||||
</p>
|
||||
|
||||
<p class="heading1">Prerequisites</p>
|
||||
<ul>
|
||||
<li>SSH File Transfer requires an SSH service to listen on an available network port (default 22) on a remote host.</li>
|
||||
<li>A username and password must be supplied to connect with the remote host.</li>
|
||||
<li>The remote host must have a writeable folder on its filesystem to place the transferred files.</li>
|
||||
</ul>
|
||||
|
||||
<p class="heading1">Configuration Options</p>
|
||||
<ul>
|
||||
<li><b>Host</b> - The remote host you connect to. Can be DNS name or IP address.</li>
|
||||
<li><b>Port</b> - Remote network port listening for SSH/SFTP/SCP traffic.</li>
|
||||
<li><b>User</b> - Username for account to log on to remote host.</li>
|
||||
<li><b>Password</b> - Password for account to log on to remote host.</li>
|
||||
<li><b>Protocol</b> - Choice of SCP or SFTP protocol used for communication.</li>
|
||||
<li><b>Local File</b> - Path of file to transfer from local host.</li>
|
||||
<li><b>Remote File</b> - Path where file will be transferred on remote host.<br />
|
||||
Example: /home/John/Documents</li>
|
||||
</ul>
|
||||
|
||||
<p class="heading1">Using SSH File Transfer</p>
|
||||
<p>
|
||||
To begin, select <b>Tools</b> and then <b>SSH File Transfer</b>. The tool will fill the window and allow you to input the configuration options. Each piece of information is needed for a successful transfer.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To populate the <b>Local File</b> option, select the <b>Browse</b> button and navigate to the desired file on the local filesystem. To populate the <b>Remote File</b> option, manually type desired filesystem path, including the desired file name.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once all options are populated, select <b>Transfer</b> and the progress bar at the bottom of the window will show the progress.
|
||||
</p>
|
||||
|
||||
<p class="heading1">Troubleshooting SSH File Transfer</p>
|
||||
<p>
|
||||
To troubleshoot issues with SSH File Transfer, consult the log under %AppData%\mRemoteNG\mRemoteNG.log. This log provides verbose information about successful and failed connections.
|
||||
<br />
|
||||
<br />
|
||||
<span class="heading2">
|
||||
Common Issues
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<b>ERROR- Please fill all fields</b><br />
|
||||
This issue was likely encountered because you did not provide all information needed to establish the connection.
|
||||
<br />
|
||||
<br />
|
||||
<b>System.Net.Sockets.SocketException (0x80004005): No connection could be made because the target machine actively refused it</b><br />
|
||||
This issue was likely encountered because the local host could not contact the remote host specified on the remote port specified.<br />
|
||||
The issue may be caused by improperly configured firewall rules or a SSH service not listening properly on the remote host.
|
||||
<br />
|
||||
<br />
|
||||
<b>[14] ERROR- SSH background transfer failed!</b><br />
|
||||
This issue was likely encountered due to a permissions issue. Ensure you have appropriate access to write to the specified Remote File.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/01.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/02.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quick Connect/03.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/01.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/02.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
mRemoteV1/Resources/Help/Screenshots/Quickconnect/03.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
36
mRemoteV1/Resources/Language/Language.Designer.cs
generated
@@ -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>
|
||||
|
||||
@@ -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>
|
||||