Compare commits

...

898 Commits

Author SHA1 Message Date
Dimitrij
3a2576384b Merge pull request #3151 from mRemoteNG/renovate/nunit-4.x
Update dependency NUnit to 4.5.0
2026-02-18 20:24:06 +00:00
renovate[bot]
6d35121a85 Update dependency NUnit to 4.5.0 2026-02-18 19:07:42 +00:00
Dimitrij
44651c9d4c Merge pull request #3148 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.76
2026-02-17 22:33:15 +00:00
renovate[bot]
1222c87760 Update dependency AWSSDK.EC2 to 4.0.76 2026-02-17 22:18:37 +00:00
Dimitrij
acfb035027 Merge pull request #3147 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.75.1
2026-02-17 22:17:41 +00:00
renovate[bot]
93f6d017e6 Update dependency AWSSDK.EC2 to 4.0.75.1 2026-02-17 01:48:38 +00:00
Dimitrij
455d897b9f Merge pull request #3146 from mRemoteNG/renovate/microsoft.web.webview2-1.x
Update dependency Microsoft.Web.WebView2 to 1.0.3800.47
2026-02-16 12:13:11 +00:00
renovate[bot]
3d4d1136f0 Update dependency Microsoft.Web.WebView2 to 1.0.3800.47 2026-02-16 10:47:26 +00:00
Dimitrij
598136f089 Update MSBuild version to '18.0' 2026-02-15 14:45:44 +00:00
Dimitrij
865bddfb04 Merge pull request #3145 from mRemoteNG/renovate/coverlet.collector-8.x
Update dependency coverlet.collector to v8
2026-02-15 14:40:49 +00:00
Dimitrij
3b2bc028cc Merge pull request #3144 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.75
2026-02-15 14:40:29 +00:00
Dimitrij
71c746f801 Update MSBuild version range in workflow
vsVersion: 18.0
2026-02-15 14:38:43 +00:00
renovate[bot]
079814751e Update dependency coverlet.collector to v8 2026-02-14 23:51:10 +00:00
Dimitrij
1de9ce6ef5 Merge pull request #3143 from jcefoli/v1.78.2-dev
AlwaysShowPanelTabs Setting Not Respected at Application…
2026-02-14 23:50:44 +00:00
renovate[bot]
01df0e295e Update dependency AWSSDK.EC2 to 4.0.75 2026-02-14 00:58:14 +00:00
Joe Cefoli
2631926eda Fixes #3142: AlwaysShowPanelTabs Setting Not Respected at Application Launch 2026-02-13 13:54:13 -05:00
Dimitrij
db1496d4a2 Merge pull request #3140 from mRemoteNG/renovate/actions-setup-dotnet-5.x
Update actions/setup-dotnet action to v5
2026-02-13 10:29:59 +00:00
renovate[bot]
a8b12c9ba1 Update actions/setup-dotnet action to v5 2026-02-12 23:12:53 +00:00
Dimitrij
a2b408e537 Update Build_mR-NB.yml
add .net 10 install
2026-02-12 23:12:17 +00:00
Dimitrij
a871624ab7 Update MSBuild version range in workflow
set ver for lower
2026-02-12 23:03:10 +00:00
Dimitrij
e40a800bc4 Update Build_mR-NB.yml
fix build tools ver
2026-02-12 22:58:46 +00:00
Dimitrij
48cb1ce770 Merge pull request #3139 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.74
2026-02-12 22:56:04 +00:00
Kvarkas
6733d758aa upd action 2026-02-12 22:55:25 +00:00
Dimitrij
f78b9bf51c Refactor self-contained build process in workflow
fix msbuild
2026-02-12 21:53:24 +00:00
renovate[bot]
213ea6a4d3 Update dependency AWSSDK.EC2 to 4.0.74 2026-02-12 21:17:33 +00:00
Kvarkas
ac3d7e6366 added new option - build Self-Contained, this allow to run mR without installing .NET 2026-02-12 21:16:31 +00:00
Dimitrij
9fae2e066e Merge pull request #3138 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2026-02-12 10:30:06 +00:00
renovate[bot]
cf66e84d31 Update aws-sdk-net monorepo 2026-02-11 22:12:21 +00:00
Dimitrij
f7326aff62 Merge pull request #3137 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.Core to 4.0.3.13
2026-02-11 09:22:09 +00:00
Kvarkas
d4bca6b03d small fixes 2026-02-10 22:03:02 +00:00
renovate[bot]
1d86015f9d Update dependency AWSSDK.Core to 4.0.3.13 2026-02-10 21:19:54 +00:00
Dimitrij
5efcc653eb Merge pull request #3038 from mRemoteNG/copilot/fix-command-injection-vulnerability
Fix command injection vulnerabilities in Process.Start calls
2026-02-10 21:18:59 +00:00
Kvarkas
333588e101 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2026-02-10 21:18:29 +00:00
Kvarkas
4046681fc5 remove dependency what are now included with .Net 10
small fixes
2026-02-10 21:18:17 +00:00
Dimitrij
91c7df22b2 Update mRemoteNGTests/Connection/Protocol/ProtocolAnydeskTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:10:35 +00:00
Dimitrij
173b208eb1 Update mRemoteNG/UI/Forms/FrmAbout.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:10:12 +00:00
Dimitrij
50de37c3a4 Update mRemoteNG/UI/Forms/OptionsPages/NotificationsPage.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:09:56 +00:00
Dimitrij
380e91de07 Update mRemoteNG/Connection/Protocol/AnyDesk/ProtocolAnyDesk.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:09:06 +00:00
Dimitrij
ba97933f33 Update mRemoteNG/UI/Forms/OptionsPages/NotificationsPage.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:08:46 +00:00
Dimitrij
539b761199 Merge pull request #3136 from mRemoteNG/renovate/major-github-artifact-actions
Update GitHub Artifact Actions (major)
2026-02-10 19:58:22 +00:00
renovate[bot]
aaff6e4548 Update GitHub Artifact Actions 2026-02-10 18:31:58 +00:00
Kvarkas
a1e3b34580 do release 2026-02-10 18:30:52 +00:00
Kvarkas
276585e379 upgrade so release include self contained version 2026-02-10 18:27:03 +00:00
Dimitrij
9242dc0faf Merge pull request #3135 from mRemoteNG/renovate/dotnet-monorepo
Update dotnet monorepo to 10.0.3
2026-02-10 18:13:22 +00:00
renovate[bot]
14d08d8d62 Update dotnet monorepo to 10.0.3 2026-02-10 17:56:13 +00:00
Dimitrij
421d8eb581 Merge pull request #3132 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.72
2026-02-10 11:37:36 +00:00
renovate[bot]
aed0006f1d Update dependency AWSSDK.EC2 to 4.0.72 2026-02-10 01:15:15 +00:00
Dimitrij
86d986a633 Merge pull request #3101 from mRemoteNG/copilot/fix-new-connection-error
Show error popup when connecting without hostname/IP
2026-02-01 20:18:51 +00:00
Dimitrij
5163aeb4d2 Change error message to warning for blank hostname 2026-02-01 20:18:11 +00:00
copilot-swe-agent[bot]
a103939c64 Address code review: fix typos, improve test robustness, use Language resources
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2026-02-01 19:59:39 +00:00
copilot-swe-agent[bot]
bcb8e05698 Update documentation for new popup error default setting
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2026-02-01 19:58:03 +00:00
copilot-swe-agent[bot]
2e74313f07 Change hostname validation to ErrorMsg and enable popup errors by default
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2026-02-01 19:56:53 +00:00
copilot-swe-agent[bot]
c9791454ec Initial plan 2026-02-01 19:52:25 +00:00
Dimitrij
b1c1696acb Merge pull request #3099 from jafin/fix/frmInputBox-autosize
Fix FrmInputBox to use dynamic sizing instead of fixed dimensions
2026-02-01 19:24:31 +00:00
Dimitrij
ab668ac677 Merge pull request #3097 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-144.x
Update dependency chromiumembeddedframework.runtime.win-x64 to v144
2026-02-01 19:23:58 +00:00
Dimitrij
1777c4840a Merge pull request #3096 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-144.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to v144
2026-02-01 19:23:44 +00:00
Dimitrij
90fcd672d8 Merge pull request #3095 from mRemoteNG/renovate/protobuf-monorepo
Update dependency Google.Protobuf to 3.33.5
2026-02-01 19:23:27 +00:00
Dimitrij
4226396cbf Merge pull request #3094 from mRemoteNG/renovate/microsoft.web.webview2-1.x
Update dependency Microsoft.Web.WebView2 to 1.0.3719.77
2026-02-01 19:23:11 +00:00
Dimitrij
3591ca0f4c Merge pull request #3093 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2026-02-01 19:22:55 +00:00
Jason Finch
09cbcccf30 Fix FrmInputBox to use dynamic sizing instead of fixed dimensions 2026-02-01 13:32:00 +10:00
renovate[bot]
4e36b5666e Update dependency chromiumembeddedframework.runtime.win-x64 to v144 2026-01-31 05:48:20 +00:00
renovate[bot]
308253a325 Update dependency chromiumembeddedframework.runtime.win-arm64 to v144 2026-01-31 05:48:13 +00:00
renovate[bot]
30bb4016b4 Update dependency Google.Protobuf to 3.33.5 2026-01-30 00:59:36 +00:00
renovate[bot]
e616ae16e1 Update aws-sdk-net monorepo 2026-01-30 00:59:30 +00:00
renovate[bot]
469528a07a Update dependency Microsoft.Web.WebView2 to 1.0.3719.77 2026-01-27 12:45:38 +00:00
Dimitrij
c7f831e9f9 Merge pull request #3089 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.67
2026-01-26 12:51:28 +00:00
Dimitrij
dd9922be45 Merge pull request #3087 from mRemoteNG/renovate/mysql.data-9.x
Update dependency MySql.Data to 9.6.0
2026-01-26 12:51:11 +00:00
Dimitrij
d0a468c22b Merge pull request #3090 from mRemoteNG/renovate/cucumber.messages-32.x
Update dependency Cucumber.Messages to v32
2026-01-26 12:50:56 +00:00
Dimitrij
ff5dbc88fe Merge pull request #3091 from mRemoteNG/renovate/gherkin-38.x
Update dependency Gherkin to v38
2026-01-26 12:50:42 +00:00
renovate[bot]
3a4ae9b098 Update dependency Cucumber.Messages to v32 2026-01-25 13:44:37 +00:00
renovate[bot]
2de24e534c Update dependency AWSSDK.EC2 to 4.0.67 2026-01-22 21:05:19 +00:00
renovate[bot]
59412a65e1 Update dependency Gherkin to v38 2026-01-22 02:30:57 +00:00
renovate[bot]
adedb6962f Update dependency MySql.Data to 9.6.0 2026-01-21 10:47:43 +00:00
Dimitrij
d3fa608ae9 Merge pull request #3086 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2026-01-21 10:47:03 +00:00
renovate[bot]
3159903875 Update aws-sdk-net monorepo 2026-01-21 01:59:43 +00:00
Dimitrij
31c28c4917 Merge pull request #3084 from mRemoteNG/renovate/microsoft.data.sqlclient-6.x
Update dependency Microsoft.Data.SqlClient to 6.1.4
2026-01-16 09:59:33 +00:00
Dimitrij
2c13f7c3a7 Merge pull request #3085 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2026-01-16 09:59:18 +00:00
renovate[bot]
725ee92147 Update aws-sdk-net monorepo 2026-01-16 01:27:24 +00:00
renovate[bot]
14406f79a2 Update dependency Microsoft.Data.SqlClient to 6.1.4 2026-01-15 18:42:41 +00:00
Kvarkas
3e202c3a19 lib update 2026-01-14 10:26:47 +00:00
Dimitrij
412c727e4c Merge pull request #3081 from mRemoteNG/renovate/dotnet-monorepo
Update dotnet monorepo to 10.0.2
2026-01-13 19:19:31 +00:00
renovate[bot]
31e7b9e443 Update dotnet monorepo to 10.0.2 2026-01-13 18:40:14 +00:00
Dimitrij
a18e292765 Merge pull request #3078 from mRemoteNG/renovate/protobuf-monorepo
Update dependency Google.Protobuf to 3.33.4
2026-01-13 11:23:46 +00:00
Dimitrij
258ea87f90 Merge pull request #3079 from mRemoteNG/renovate/cucumber.messages-31.x
Update dependency Cucumber.Messages to 31.2.0
2026-01-13 10:38:07 +00:00
renovate[bot]
fd9eabe1e6 Update dependency Google.Protobuf to 3.33.4 2026-01-12 21:55:32 +00:00
renovate[bot]
a9dd06df45 Update dependency Cucumber.Messages to 31.2.0 2026-01-12 00:24:29 +00:00
Dimitrij
dfc24b0cb2 Merge pull request #3076 from mRemoteNG/renovate/nunit3testadapter-6.x
Update dependency NUnit3TestAdapter to 6.1.0
2026-01-08 09:46:33 +00:00
Dimitrij
63f5325f29 Merge pull request #3075 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2026-01-08 09:46:04 +00:00
renovate[bot]
6f7949214b Update dependency NUnit3TestAdapter to 6.1.0 2026-01-07 21:23:22 +00:00
renovate[bot]
6cfec060a0 Update aws-sdk-net monorepo 2026-01-07 21:23:16 +00:00
Dimitrij
db733424ca Merge pull request #3074 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.65.1
2026-01-06 10:49:59 +00:00
renovate[bot]
49eab4d377 Update dependency AWSSDK.EC2 to 4.0.65.1 2026-01-06 01:42:04 +00:00
Dimitrij
53e5396031 Merge pull request #3073 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.Core to 4.0.3.7
2026-01-05 21:17:14 +00:00
renovate[bot]
99d01130bf Update dependency AWSSDK.Core to 4.0.3.7 2026-01-05 21:04:09 +00:00
Dimitrij
62ce6cd6e7 Merge pull request #3071 from mRemoteNG/renovate/nunit.consolerunner-3.x
Update dependency NUnit.ConsoleRunner to 3.22.0
2026-01-04 17:53:30 +00:00
renovate[bot]
35c66b0e4a Update dependency NUnit.ConsoleRunner to 3.22.0 2026-01-04 17:53:20 +00:00
Dimitrij
dafc05dc42 Merge pull request #3072 from mRemoteNG/renovate/zstdsharp.port-0.x
Update dependency ZstdSharp.Port to 0.8.7
2026-01-04 17:53:13 +00:00
Dimitrij
458a05ea5f Merge pull request #3070 from mRemoteNG/renovate/nunit.console-3.x
Update dependency NUnit.Console to 3.22.0
2026-01-04 17:52:43 +00:00
renovate[bot]
38acc1e960 Update dependency ZstdSharp.Port to 0.8.7 2026-01-03 17:58:37 +00:00
renovate[bot]
f83209a2b9 Update dependency NUnit.Console to 3.22.0 2026-01-03 01:59:37 +00:00
Dimitrij
9d1546c8b7 Merge pull request #3068 from mRemoteNG/copilot/fix-sql-injection-issue
Fix WQL injection vulnerability in InstalledWindowsUpdateChecker
2025-12-30 12:30:53 +00:00
copilot-swe-agent[bot]
dca2517cf0 Normalize digit-only KB IDs to include KB prefix
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-30 12:19:35 +00:00
copilot-swe-agent[bot]
ff54ca9015 Fix inaccurate comment in SanitizeKbId method
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-30 12:17:52 +00:00
copilot-swe-agent[bot]
76cb0a1e0b Address code review feedback - optimize regex and use Array.Empty
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-30 12:16:52 +00:00
copilot-swe-agent[bot]
c683854678 Add WQL injection prevention via KB ID sanitization
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-30 12:15:31 +00:00
copilot-swe-agent[bot]
e9d0a8aa69 Initial plan 2025-12-30 12:11:00 +00:00
Dimitrij
30cb1de711 Merge pull request #3064 from mRemoteNG/copilot/fix-ldap-query-injection
Fix LDAP injection vulnerability in Active Directory integration
2025-12-30 12:06:35 +00:00
Dimitrij
699b93e175 Merge pull request #3066 from mRemoteNG/copilot/setup-copilot-instructions
Add GitHub Copilot instructions for repository
2025-12-30 12:05:30 +00:00
copilot-swe-agent[bot]
c7df6f3715 Add comprehensive GitHub Copilot instructions
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-29 13:17:42 +00:00
copilot-swe-agent[bot]
f1d1a19779 Initial plan 2025-12-29 13:13:24 +00:00
copilot-swe-agent[bot]
1c2b5fadc4 Fix code review feedback: consistent hex formatting and test names
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-29 10:06:39 +00:00
copilot-swe-agent[bot]
97f5daa13d Add LDAP injection protection with sanitization utility
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-29 10:04:43 +00:00
copilot-swe-agent[bot]
63e100c233 Initial plan 2025-12-29 09:59:26 +00:00
Dimitrij
92a710e72a Merge pull request #3061 from koen-lee/make-1password-integration-more-tolerant
Make 1password integration more tolerant
2025-12-29 09:57:47 +00:00
Koen van Leeuwen
fe82146f47 server type items have username id fields by default which may have localized labels 2025-12-24 21:40:54 +01:00
Koen van Leeuwen
64b0496ef7 Add (self) documentation 2025-12-24 21:21:27 +01:00
Koen van Leeuwen
7d21b3de9e Fall back to a username/password by label 2025-12-24 20:48:51 +01:00
Dimitrij
68a8caea34 Merge pull request #3059 from mRemoteNG/renovate/gherkin-37.x
Update dependency Gherkin to 37.0.1
2025-12-24 10:18:21 +00:00
Dimitrij
aee18bae3b Merge pull request #3058 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.65
2025-12-24 10:18:09 +00:00
Dimitrij
ff58cae677 Merge pull request #3060 from mRemoteNG/renovate/cucumber.messages-31.x
Update dependency Cucumber.Messages to 31.1.0
2025-12-24 10:17:54 +00:00
renovate[bot]
548f938757 Update dependency Cucumber.Messages to 31.1.0 2025-12-23 00:55:31 +00:00
renovate[bot]
b9c2e82af1 Update dependency Gherkin to 37.0.1 2025-12-22 21:56:51 +00:00
renovate[bot]
23bb5ec7be Update dependency AWSSDK.EC2 to 4.0.65 2025-12-22 21:56:45 +00:00
Dimitrij
0b7b87d84a Merge pull request #3057 from mRemoteNG/renovate/nunit3testadapter-6.x
Update dependency NUnit3TestAdapter to 6.0.1
2025-12-20 15:44:58 +00:00
Dimitrij
b84a49e99c Merge pull request #3056 from mRemoteNG/renovate/nunit.consolerunner-3.x
Update dependency NUnit.ConsoleRunner to 3.21.1
2025-12-20 15:40:31 +00:00
renovate[bot]
327cc46c8d Update dependency NUnit3TestAdapter to 6.0.1 2025-12-20 15:28:10 +00:00
renovate[bot]
8540434594 Update dependency NUnit.ConsoleRunner to 3.21.1 2025-12-20 15:28:07 +00:00
Dimitrij
41536ba971 Merge pull request #3055 from mRemoteNG/renovate/nunit.console-3.x
Update dependency NUnit.Console to 3.21.1
2025-12-20 15:27:25 +00:00
renovate[bot]
8ddaf024ff Update dependency NUnit.Console to 3.21.1 2025-12-20 04:34:08 +00:00
Dimitrij
7e8f647f54 Merge pull request #3053 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.64
2025-12-19 10:15:21 +00:00
renovate[bot]
9a32a7c68c Update dependency AWSSDK.EC2 to 4.0.64 2025-12-19 01:41:58 +00:00
Dimitrij
280a930792 Merge pull request #3052 from mRemoteNG/renovate/cucumber.messages-31.x
Update dependency Cucumber.Messages to 31.0.1
2025-12-18 20:41:57 +00:00
renovate[bot]
2540d39dd8 Update dependency Cucumber.Messages to 31.0.1 2025-12-18 18:41:46 +00:00
Dimitrij
2b00fa0ad9 Merge pull request #3050 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.63
2025-12-17 22:34:25 +00:00
renovate[bot]
810aad90ed Update dependency AWSSDK.EC2 to 4.0.63 2025-12-15 22:25:49 +00:00
Dimitrij
59c8968d8a Merge pull request #3048 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-12-13 21:03:19 +00:00
renovate[bot]
4bfed87d81 Update aws-sdk-net monorepo 2025-12-12 22:00:10 +00:00
Dimitrij
5c36477b1f Merge pull request #3047 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-143.x
Update dependency chromiumembeddedframework.runtime.win-x64 to v143
2025-12-12 11:42:19 +00:00
Dimitrij
a529b978e1 Merge pull request #3045 from mRemoteNG/renovate/actions-cache-5.x
Update actions/cache action to v5
2025-12-12 11:42:01 +00:00
Dimitrij
eae83eadab Merge pull request #3042 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-12-12 11:41:49 +00:00
Dimitrij
297260af9a Merge pull request #3046 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-143.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to v143
2025-12-12 11:41:32 +00:00
renovate[bot]
f5d38c282f Update dependency chromiumembeddedframework.runtime.win-x64 to v143 2025-12-12 11:13:59 +00:00
renovate[bot]
493e5eda6a Update dependency chromiumembeddedframework.runtime.win-arm64 to v143 2025-12-12 11:13:54 +00:00
renovate[bot]
88b8201384 Update actions/cache action to v5 2025-12-12 04:11:47 +00:00
renovate[bot]
b88204c261 Update aws-sdk-net monorepo 2025-12-10 22:42:33 +00:00
Dimitrij
d39fb10b47 Merge pull request #3041 from mRemoteNG/renovate/dotnet-monorepo
Update dotnet monorepo to 10.0.1
2025-12-09 23:04:07 +00:00
Dimitrij
96e7313b69 Merge pull request #3040 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.62
2025-12-09 23:03:43 +00:00
Dimitrij
02be546c5b Merge pull request #3039 from mRemoteNG/renovate/microsoft.web.webview2-1.x
Update dependency Microsoft.Web.WebView2 to 1.0.3650.58
2025-12-09 23:02:57 +00:00
renovate[bot]
c5b98c6cc8 Update dotnet monorepo to 10.0.1 2025-12-09 19:55:45 +00:00
renovate[bot]
687a4088ab Update dependency AWSSDK.EC2 to 4.0.62 2025-12-09 03:37:36 +00:00
renovate[bot]
8c63843c22 Update dependency Microsoft.Web.WebView2 to 1.0.3650.58 2025-12-08 14:52:30 +00:00
copilot-swe-agent[bot]
469ca48592 Fix compilation issues and improve code review feedback
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-08 13:12:15 +00:00
copilot-swe-agent[bot]
208ce663b2 Address code review feedback - improve security validations
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-08 13:08:50 +00:00
copilot-swe-agent[bot]
843243c75e Add comprehensive tests for AnyDesk ID validation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-08 13:06:16 +00:00
copilot-swe-agent[bot]
b7ed5a300d Fix command injection vulnerabilities in Process.Start calls
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-12-08 13:03:54 +00:00
copilot-swe-agent[bot]
415a649a76 Initial plan 2025-12-08 12:55:04 +00:00
Dimitrij
462d9c39af Merge pull request #3035 from mRemoteNG/renovate/nunit.console-3.x
Update dependency NUnit.Console to 3.21.0
2025-12-08 12:15:46 +00:00
Dimitrij
d52d79dd69 Merge pull request #3034 from mRemoteNG/renovate/protobuf-monorepo
Update dependency Google.Protobuf to 3.33.2
2025-12-08 12:15:25 +00:00
Dimitrij
5dbc6e74e0 Merge pull request #3033 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-12-08 12:15:02 +00:00
renovate[bot]
986b0084bf Update dependency NUnit.Console to 3.21.0 2025-12-08 12:14:52 +00:00
Dimitrij
78bdf02c14 Merge pull request #3036 from mRemoteNG/renovate/nunit.consolerunner-3.x
Update dependency NUnit.ConsoleRunner to 3.21.0
2025-12-08 12:14:31 +00:00
Dimitrij
b4ea8f00ad Merge pull request #3037 from mRemoteNG/renovate/nunit3testadapter-6.x
Update dependency NUnit3TestAdapter to v6
2025-12-08 12:14:16 +00:00
renovate[bot]
7fd992e9f1 Update dependency NUnit3TestAdapter to v6 2025-12-06 21:14:25 +00:00
renovate[bot]
76e739cdc1 Update dependency NUnit.ConsoleRunner to 3.21.0 2025-12-06 18:10:34 +00:00
renovate[bot]
0e0cc1c884 Update dependency Google.Protobuf to 3.33.2 2025-12-06 03:05:36 +00:00
renovate[bot]
21fba7f371 Update aws-sdk-net monorepo 2025-12-05 21:29:40 +00:00
Dimitrij
3f3a0c3c21 Merge pull request #3032 from mRemoteNG/renovate/reportgenerator-5.x
Update dependency ReportGenerator to 5.5.1
2025-12-04 10:24:31 +00:00
Kvarkas
1db87b18de update links to vc++ 2025-12-03 21:59:40 +00:00
renovate[bot]
44b01bca96 Update dependency ReportGenerator to 5.5.1 2025-12-03 21:35:59 +00:00
Dimitrij
441b13bed6 Merge pull request #3029 from mRemoteNG/renovate/softprops-action-gh-release-digest
Update softprops/action-gh-release digest to a06a81a
2025-12-03 17:10:28 +00:00
renovate[bot]
dd72e9edb7 Update softprops/action-gh-release digest to a06a81a 2025-12-01 09:07:48 +00:00
Kvarkas
8bbcc9b877 update to .net 10 2025-11-26 09:21:53 +00:00
Dimitrij
98580a8dc6 Merge pull request #3026 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.61
2025-11-26 09:21:00 +00:00
renovate[bot]
3600905a39 Update dependency AWSSDK.EC2 to 4.0.61 2025-11-25 21:38:27 +00:00
Dimitrij
c207685b91 Merge pull request #3025 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-24 10:28:24 +00:00
renovate[bot]
683f3bcb80 Update aws-sdk-net monorepo 2025-11-22 02:26:25 +00:00
Dimitrij
23f964ba28 Merge pull request #3023 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.59
2025-11-21 10:10:26 +00:00
renovate[bot]
56271ba346 Update dependency AWSSDK.EC2 to 4.0.59 2025-11-21 01:24:18 +00:00
Dimitrij
252a402f4f Merge pull request #3022 from mRemoteNG/renovate/actions-checkout-6.x
Update actions/checkout action to v6
2025-11-20 19:08:30 +00:00
renovate[bot]
d2d0722ac2 Update actions/checkout action to v6 2025-11-20 16:57:14 +00:00
Dimitrij
ce9bdccc4d Merge pull request #3019 from mRemoteNG/renovate/cucumber.messages-31.x
Update dependency Cucumber.Messages to v31
2025-11-20 14:52:12 +00:00
Dimitrij
2a992aa1d8 Merge pull request #3016 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-20 14:51:54 +00:00
Dimitrij
f73729bbe8 Merge pull request #3021 from mRemoteNG/renovate/gherkin-37.x
Update dependency Gherkin to v37
2025-11-20 14:51:31 +00:00
renovate[bot]
8634edbd8c Update aws-sdk-net monorepo 2025-11-20 00:30:33 +00:00
renovate[bot]
cc3ead0799 Update dependency Gherkin to v37 2025-11-19 20:43:09 +00:00
renovate[bot]
566cd26e73 Update dependency Cucumber.Messages to v31 2025-11-19 00:41:03 +00:00
Dimitrij
2354d5a8a4 Merge pull request #3015 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.54
2025-11-14 22:24:43 +00:00
renovate[bot]
778067a590 Update dependency AWSSDK.EC2 to 4.0.54 2025-11-13 22:56:16 +00:00
Dimitrij
d8d9c844d1 Merge pull request #3014 from mRemoteNG/renovate/protobuf-monorepo
Update dependency Google.Protobuf to 3.33.1
2025-11-13 22:55:42 +00:00
renovate[bot]
dc6655514a Update dependency Google.Protobuf to 3.33.1 2025-11-13 20:38:21 +00:00
Dimitrij
feb3b72fd0 Merge pull request #3011 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-13 10:58:16 +00:00
Dimitrij
479e18b204 Merge pull request #3012 from mRemoteNG/renovate/microsoft.data.sqlclient-6.x
Update dependency Microsoft.Data.SqlClient to 6.1.3
2025-11-13 10:57:59 +00:00
renovate[bot]
b1c169d0b8 Update dependency Microsoft.Data.SqlClient to 6.1.3 2025-11-13 00:43:12 +00:00
renovate[bot]
7f75fadb31 Update aws-sdk-net monorepo 2025-11-13 00:43:07 +00:00
Dimitrij
6af70543ea Merge pull request #3010 from mRemoteNG/renovate/reportgenerator-5.x
Update dependency ReportGenerator to 5.5.0
2025-11-12 09:28:27 +00:00
Dimitrij
59d5d575ad Merge pull request #3009 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.52
2025-11-12 09:26:54 +00:00
renovate[bot]
05f2b84cf5 Update dependency ReportGenerator to 5.5.0 2025-11-11 22:41:56 +00:00
renovate[bot]
a39d4a3063 Update dependency AWSSDK.EC2 to 4.0.52 2025-11-11 22:41:50 +00:00
Dimitrij
1da019575e Merge pull request #3008 from mRemoteNG/renovate/major-dotnet-monorepo
Update dotnet monorepo to v10 (major)
2025-11-11 18:37:15 +00:00
renovate[bot]
195c4be4e2 Update dotnet monorepo to v10 2025-11-11 18:36:53 +00:00
Dimitrij
4dd672e600 Merge pull request #3006 from mRemoteNG/renovate/vstest-monorepo
Update dependency Microsoft.NET.Test.Sdk to 18.0.1
2025-11-11 18:36:17 +00:00
renovate[bot]
f3a14c5ede Update dependency Microsoft.NET.Test.Sdk to 18.0.1 2025-11-11 18:36:04 +00:00
Dimitrij
af696a96aa Merge pull request #3007 from mRemoteNG/renovate/dotnet-monorepo
Update dotnet monorepo to 9.0.11
2025-11-11 18:35:29 +00:00
renovate[bot]
d7de52fb4c Update dotnet monorepo to 9.0.11 2025-11-11 16:53:18 +00:00
Dimitrij
ae66a8fcfc Merge pull request #3004 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.51
2025-11-11 09:11:25 +00:00
renovate[bot]
56d18774a8 Update dependency AWSSDK.EC2 to 4.0.51 2025-11-11 03:41:19 +00:00
Dimitrij
7ba22c5555 Merge pull request #2995 from joubertdj/fix/issue-2960-panel-tab-visibility
Fix panel tab header visibility issue when single panel is docked
2025-11-09 18:39:55 +00:00
Dimitrij
dab7715eb7 Merge pull request #3002 from mRemoteNG/renovate/softprops-action-gh-release-digest
Update softprops/action-gh-release digest to 5be0e66
2025-11-09 18:39:28 +00:00
Dimitrij
ec8bac933d Merge pull request #2999 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-09 18:38:46 +00:00
renovate[bot]
958ec65b17 Update softprops/action-gh-release digest to 5be0e66 2025-11-08 21:58:44 +00:00
renovate[bot]
e775acc209 Update aws-sdk-net monorepo 2025-11-07 23:29:42 +00:00
Dimitrij
d23631faef Merge pull request #2996 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.49
2025-11-07 09:14:03 +00:00
renovate[bot]
518401b2c4 Update dependency AWSSDK.EC2 to 4.0.49 2025-11-06 22:05:23 +00:00
Dawie Joubert
20c3ebd662 Fix panel tab header visibility issue when single panel is docked
Changed DockPanel DocumentStyle from DockingSdi to DockingWindow to ensure
panel tab headers remain visible even when only one panel exists in a dock area.

This resolves the issue where users could not access panel controls (close button,
pin/auto-hide, dropdown menu) after moving panels to new locations, as the tab
strip was completely hidden with DockingSdi when only one panel was present.

With DockingWindow style:
- Panel name/title always visible
- Close button (X) always accessible
- Pin/auto-hide button always available
- Dropdown menu always accessible
- No more "lost" panels requiring layout reset

Fixes #2960

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 16:40:29 +02:00
Dimitrij
8d0d03e152 Merge pull request #2990 from joubertdj/fix/rdp-automatic-resize-issue-2971
Fix RDP automatic resize not working when manually dragging window edges (maximize/minimize/etc)
2025-11-06 12:10:22 +00:00
Dimitrij
632cfca71f Update mRemoteNGTests/Connection/Protocol/RdpProtocol8ResizeTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-06 12:09:27 +00:00
Dimitrij
221ff38a66 Merge pull request #2991 from joubertdj/fix/issue-2907-options-panel-fixes
Fix issue #2907: Options panel freezing, disposal, and performance is…
2025-11-06 12:08:18 +00:00
Dimitrij
3ac7365c9b Update mRemoteNGTests/UI/Forms/OptionsFormTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-06 12:06:36 +00:00
Dimitrij
be53755010 Update mRemoteNG/UI/Forms/frmOptions.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-06 12:06:18 +00:00
Dimitrij
30eafa3efa Update mRemoteNG/UI/Window/OptionsWindow.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-06 12:06:10 +00:00
Dimitrij
7c0a6a51d4 Merge pull request #2992 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-06 11:59:51 +00:00
Dimitrij
181f96823e Merge pull request #2993 from mRemoteNG/renovate/gherkin-36.x
Update dependency Gherkin to 36.1.0
2025-11-06 11:59:33 +00:00
renovate[bot]
7b4e9781ac Update dependency Gherkin to 36.1.0 2025-11-05 22:29:32 +00:00
renovate[bot]
7a4ff98ba8 Update aws-sdk-net monorepo 2025-11-05 22:29:26 +00:00
Dawie Joubert
100c2e3078 Fix issue #2907: Options panel freezing, disposal, and performance issues
This commit resolves multiple related issues with the Options dialog that caused freezing, crashes, and slow performance:

**Problem 1: Infinite Recursive Loop**
- Symptom: Options dialog would freeze when navigating between pages
- Cause: LstOptionPages_SelectedIndexChanged event handler triggering itself infinitely
- Fix: Added _isHandlingSelectionChange guard flag to prevent recursive calls

**Problem 2: Disposed Object Exception**
- Symptom: "Cannot access a disposed object" error after SSH connection workflow
- Cause: Static FrmOptions instance was disposed but still referenced
- Fix: Enhanced OptionsWindow.LoadOptionsForm() to detect disposal before use
- Fix: Added FrmMain.RecreateOptionsForm() to recreate disposed forms transparently

**Problem 3: Index Out of Range**
- Symptom: "index must be less than 0" when accessing empty lstOptionPages
- Cause: SetActivatedPage() tried to access Items[0] when collection was empty
- Fix: Added bounds checking before accessing lstOptionPages.Items

**Problem 4: NullReferenceException in OptionsPages**
- Symptom: NullReferenceException in LoadRegistrySettings() across all pages
- Cause: pageRegSettingsInstance was null when registry settings didn't exist
- Fix: Added null checks and default instance creation in 8 OptionsPages

**Problem 5: Slow Page Loading on Recreation**
- Symptom: Second Options dialog open showed staggered page loading (~2.2 seconds)
- Cause: Application.Idle async pattern loaded pages one-by-one
- Fix: Replaced async loading with synchronous batch loading using BeginUpdate/EndUpdate

**Files Modified:**
- mRemoteNG/UI/Forms/frmOptions.cs
- mRemoteNG/UI/Window/OptionsWindow.cs
- mRemoteNG/UI/Forms/frmMain.cs
- mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs
- mRemoteNG/UI/Forms/OptionsPages/NotificationsPage.cs
- mRemoteNG/UI/Forms/OptionsPages/AppearancePage.cs
- mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs
- mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs
- mRemoteNG/UI/Forms/OptionsPages/CredentialsPage.cs
- mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs
- mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs

**Additional Changes:**
- Replaced all Debug.WriteLine with Logger.Instance.Log for consistent logging
- Added comprehensive debug logging throughout Options form lifecycle
- Improved defensive programming with guard flags and validation checks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 19:49:56 +02:00
Dawie Joubert
cc6f07d943 Fix RDP automatic resize not working when manually dragging window edges
Fixes #2971

This fix addresses the issue where RDP connections with "Automatic resize"
enabled weren't resizing the remote desktop when users manually dragged
window edges - only when changing window states (Maximize/Restore).

Changes:
- RdpProtocol8.cs: Fixed resize logic to use InterfaceControl.Size instead
  of Control.Size, added 300ms debounce to reduce flickering, and registered
  ResizeEnd event handler
- RdpProtocol9.cs: Added null safety checks in UpdateSessionDisplaySettings
- NotificationPanelMessageWriter.cs: Added exception handling for shutdown
  scenarios to prevent InvalidAsynchronousStateException
- RdpProtocol8ResizeTests.cs: Added 12 comprehensive unit tests covering
  all resize scenarios including debounce mechanism
- TabColorConverterTests.cs: Added missing System namespace import

The fix works for all RDP versions (8, 9, 10, 11) through inheritance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 17:34:45 +02:00
Dimitrij
cc3a9c3a00 Merge pull request #2985 from mRemoteNG/copilot/fix-vnc-connection-issue
Fix VNC connection failure due to TCP client resource leak
2025-11-03 22:49:06 +00:00
Dimitrij
ce1d82c730 Merge pull request #2986 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.47
2025-11-03 22:42:17 +00:00
renovate[bot]
ec3a01de70 Update dependency AWSSDK.EC2 to 4.0.47 2025-11-03 22:13:04 +00:00
Dimitrij
af894964fc Update mRemoteNG/Connection/Protocol/VNC/Connection.Protocol.VNC.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-03 21:39:58 +00:00
copilot-swe-agent[bot]
5cebc4d418 Reset socket exception before other operations for safety
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-11-03 21:25:15 +00:00
copilot-swe-agent[bot]
04e0144004 Preserve exception stack trace using ExceptionDispatchInfo
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-11-03 21:23:55 +00:00
copilot-swe-agent[bot]
c33c9814c2 Address code review feedback: improve comment and add thread safety
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-11-03 21:22:07 +00:00
copilot-swe-agent[bot]
3a946e5810 Fix VNC connection TCP client resource leak
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-11-03 21:18:50 +00:00
copilot-swe-agent[bot]
6a6a894a1c Initial plan 2025-11-03 21:14:03 +00:00
Dimitrij
e1ffb9262d Merge pull request #2977 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-11-03 11:48:00 +00:00
Dimitrij
b3eb6904f9 Merge pull request #2983 from mRemoteNG/renovate/microsoft.web.webview2-1.x
Update dependency Microsoft.Web.WebView2 to 1.0.3595.46
2025-11-03 11:47:37 +00:00
Dimitrij
72cbade402 Merge pull request #2979 from MaxPlap/feature/VaultOpenbao-Connector
Feature/vault openbao connector
2025-11-03 11:10:12 +00:00
Dimitrij
6fd008c2e8 Merge pull request #2978 from mRemoteNG/renovate/ssh.net-2025.x
Update dependency SSH.NET to 2025.1.0
2025-11-03 11:09:54 +00:00
renovate[bot]
25f26f08de Update dependency Microsoft.Web.WebView2 to 1.0.3595.46 2025-11-03 10:00:32 +00:00
renovate[bot]
7ebc62d8e3 Update aws-sdk-net monorepo 2025-10-31 20:57:59 +00:00
massimo.antonello
e04ba4f9e0 removed debug log 2025-10-28 15:46:38 +01:00
massimo.antonello
0d4324b009 Read OTP SSH 2025-10-28 15:12:32 +01:00
massimo.antonello
6404956a62 new option 2025-10-28 14:45:26 +01:00
renovate[bot]
769db78ee8 Update dependency SSH.NET to 2025.1.0 2025-10-27 23:27:13 +00:00
Dimitrij
8bb8d52b1d Merge pull request #2974 from mRemoteNG/renovate/reportgenerator-5.x
Update dependency ReportGenerator to 5.4.18
2025-10-26 13:20:05 +00:00
Dimitrij
e990659d05 Merge pull request #2975 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-141.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to v141
2025-10-26 13:19:45 +00:00
Dimitrij
0fcef353ae Merge pull request #2976 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-141.x
Update dependency chromiumembeddedframework.runtime.win-x64 to v141
2025-10-26 13:18:40 +00:00
renovate[bot]
bf91a8a709 Update dependency chromiumembeddedframework.runtime.win-x64 to v141 2025-10-26 00:55:06 +00:00
renovate[bot]
d81a608b3a Update dependency chromiumembeddedframework.runtime.win-arm64 to v141 2025-10-26 00:55:02 +00:00
renovate[bot]
8413ee77d4 Update dependency ReportGenerator to 5.4.18 2025-10-25 16:48:20 +00:00
Dimitrij
4d92a30089 Merge pull request #2970 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-10-24 09:16:23 +01:00
renovate[bot]
57f7e09bb6 Update aws-sdk-net monorepo 2025-10-24 01:12:48 +00:00
Dimitrij
19fdccc540 Merge pull request #2969 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.44
2025-10-23 17:44:02 +01:00
renovate[bot]
83c2f2a7a8 Update dependency AWSSDK.EC2 to 4.0.44 2025-10-23 02:53:43 +00:00
Dimitrij
9dcea7ed6e Merge pull request #2968 from mRemoteNG/renovate/mysql.data-9.x
Update dependency MySql.Data to 9.5.0
2025-10-22 10:29:24 +01:00
renovate[bot]
6ad3de91e9 Update dependency MySql.Data to 9.5.0 2025-10-22 08:26:36 +00:00
Dimitrij
2bbbd166f9 Merge pull request #2967 from mRemoteNG/copilot/fix-command-injection-vulnerability
Fix command injection vulnerabilities in Process.Start calls
2025-10-22 09:25:51 +01:00
copilot-swe-agent[bot]
327ba3f4e1 Add path validation to PuttyBase, IntegratedProgram, and AnyDesk protocols
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-22 08:21:20 +00:00
copilot-swe-agent[bot]
c9b77b6616 Add comprehensive security tests for path validation and command injection prevention
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-22 08:17:58 +00:00
copilot-swe-agent[bot]
a94e58c83e Add path validation to prevent command injection in Process.Start calls
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-22 08:16:25 +00:00
copilot-swe-agent[bot]
d40794d7a0 Initial plan 2025-10-22 08:10:43 +00:00
Dimitrij
7dd916dd80 Merge pull request #2966 from mRemoteNG/copilot/fix-option-panel-issue
Fix options panel hanging on second open
2025-10-22 00:51:38 +01:00
copilot-swe-agent[bot]
d16d76d0fa Improve fix to avoid interfering with initial load
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-21 23:41:25 +00:00
copilot-swe-agent[bot]
a896949752 Fix options panel not opening on second call
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-21 23:40:06 +00:00
copilot-swe-agent[bot]
f63186a7a6 Initial plan 2025-10-21 23:35:44 +00:00
Dimitrij
ee88e835ed in additional to #2963 logic fixes 2025-10-22 00:16:26 +01:00
Dimitrij
1288a274f3 code tidy up 2025-10-21 22:19:22 +01:00
Dimitrij
facc523aae Merge pull request #2963 from mRemoteNG/copilot/add-bind-connections-config
Add option to bind Connections and Config panels together when auto-hidden
2025-10-21 21:00:15 +01:00
Dimitrij
11dfdd797d Merge pull request #2962 from mRemoteNG/copilot/fix-remote-code-execution
Remove insecure BinaryFormatter deserialization code to prevent RCE vulnerabilities
2025-10-21 20:58:55 +01:00
copilot-swe-agent[bot]
3dc37d0359 Refine PanelBinder implementation and add documentation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-21 17:33:38 +00:00
copilot-swe-agent[bot]
b00185e1dc Add panel binding feature with UI option
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-21 17:31:29 +00:00
copilot-swe-agent[bot]
44c65775ad Remove insecure BinaryFormatter code and imports
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-21 17:24:50 +00:00
copilot-swe-agent[bot]
9c31ee28b6 Initial plan 2025-10-21 17:20:45 +00:00
copilot-swe-agent[bot]
5868f91d2d Initial plan 2025-10-21 17:17:46 +00:00
Dimitrij
ee3735904d Merge pull request #2957 from mRemoteNG/copilot/add-anydesk-connection-plugin
Add native AnyDesk protocol support to mRemoteNG
2025-10-20 22:35:51 +01:00
Dimitrij
2b39dde523 Update mRemoteNG/Connection/Protocol/AnyDesk/ProtocolAnyDesk.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-20 22:34:26 +01:00
Dimitrij
611fdcebe9 Update mRemoteNG/Connection/Protocol/AnyDesk/ProtocolAnyDesk.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-20 22:34:06 +01:00
Dimitrij
b6c21bb21f Update mRemoteNG/Connection/Protocol/AnyDesk/ProtocolAnyDesk.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-20 22:31:42 +01:00
copilot-swe-agent[bot]
ed2fee3195 Add AnyDesk documentation and improve implementation comments
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-20 17:39:05 +00:00
copilot-swe-agent[bot]
2d7a897a4d Improve AnyDesk protocol implementation - better window handling and cleanup
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-20 17:36:21 +00:00
copilot-swe-agent[bot]
4f14c78b58 Add AnyDesk protocol support - initial implementation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-20 17:33:56 +00:00
copilot-swe-agent[bot]
8b8c1d919e Initial plan 2025-10-20 17:27:45 +00:00
Dimitrij
e960353de6 Merge pull request #2955 from mRemoteNG/fix/aikido-security-sast-8911151-ato3
[Aikido] AI Fix for Path traversal attack possible
2025-10-20 10:02:10 +01:00
aikido-autofix[bot]
e563a4c319 fix(security): autofix Path traversal attack possible 2025-10-20 09:01:19 +00:00
Dimitrij
131aef7069 Merge pull request #2954 from mRemoteNG/copilot/add-wsl-connection-protocol
Add WSL protocol support with installation check
2025-10-19 21:55:47 +01:00
Dimitrij
73c3e078d1 Merge branch 'v1.78.2-dev' into copilot/add-wsl-connection-protocol 2025-10-19 21:55:39 +01:00
Dimitrij
8858d55970 Merge pull request #2952 from mRemoteNG/copilot/add-protocol-to-connect-terminal
Add Terminal protocol to connect to command prompt
2025-10-19 21:53:24 +01:00
copilot-swe-agent[bot]
f983f5de02 Improve timeout handling and error messaging in Terminal protocol
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:40:22 +00:00
copilot-swe-agent[bot]
a8efba1ed4 Fix handle creation wait loop in Terminal protocol
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:38:36 +00:00
copilot-swe-agent[bot]
8fc3682cc9 Address code review feedback - improve Terminal protocol implementation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:36:52 +00:00
copilot-swe-agent[bot]
4ade871aba Add WSL translations to language resource files
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:34:40 +00:00
copilot-swe-agent[bot]
0a381e0a44 Improve Terminal protocol to use cmd.exe instead of wt.exe
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:34:22 +00:00
copilot-swe-agent[bot]
895e16d4cb Add Terminal language entries to all language files
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:33:20 +00:00
copilot-swe-agent[bot]
6657fa3ad0 Update attributes and tests for WSL protocol
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:32:40 +00:00
copilot-swe-agent[bot]
f5fcc7c206 Add WSL protocol support with installation check
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:30:48 +00:00
copilot-swe-agent[bot]
435e6f46c1 Add Terminal protocol support to mRemoteNG
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 20:29:42 +00:00
copilot-swe-agent[bot]
9ef81e6e72 Initial plan 2025-10-19 20:23:35 +00:00
copilot-swe-agent[bot]
e4b4400aa5 Initial plan 2025-10-19 20:22:29 +00:00
Dimitrij
1d9e082a4a Merge pull request #2950 from mRemoteNG/copilot/fix-log4net-not-found
Fix unhandled exception during startup: log4net assembly not found
2025-10-19 20:34:43 +01:00
copilot-swe-agent[bot]
43d11a5de2 Remove log4net assembly-level attribute causing startup crash
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-19 19:21:14 +00:00
copilot-swe-agent[bot]
94db6caa2c Initial plan 2025-10-19 19:16:54 +00:00
Dimitrij
11366e5d8d upd 2025-10-19 00:43:44 +01:00
Dimitrij
a2967fa999 Merge pull request #2946 from mRemoteNG/copilot/add-margin-to-connection-frame
Fix connection frame color visibility by adding padding to prevent content overlap
2025-10-19 00:36:04 +01:00
copilot-swe-agent[bot]
12920bc6c6 Update IntegratedProgram and PowerShell protocols to respect connection frame padding
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 23:20:09 +00:00
copilot-swe-agent[bot]
55fec45b58 Add padding to InterfaceControl to make connection frame color visible
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 23:18:15 +00:00
copilot-swe-agent[bot]
045aa631e4 Initial plan 2025-10-18 23:12:37 +00:00
Dimitrij
3cf3a70fc7 fix 2025-10-19 00:01:59 +01:00
Dimitrij
290dab29f1 Merge pull request #2944 from mRemoteNG/copilot/add-attribute-to-store-tags
Add EnvironmentTags attribute to store environment categorization tags
2025-10-18 23:57:05 +01:00
copilot-swe-agent[bot]
79b252f839 Add EnvironmentTags to test helper
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 22:51:46 +00:00
copilot-swe-agent[bot]
49bd76f197 Add EnvironmentTags property to connection info
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 22:50:02 +00:00
copilot-swe-agent[bot]
54492bedfb Initial plan 2025-10-18 22:39:41 +00:00
Dimitrij
2d1c2df2cb Merge pull request #2941 from mRemoteNG/copilot/add-ctrl-tab-tab-switching
Add Ctrl+Tab keyboard shortcuts for tab navigation
2025-10-18 22:41:54 +01:00
Dimitrij
1187e1c95e Merge pull request #2942 from mRemoteNG/copilot/add-production-color-frame
Add Connection Frame Color feature to visually distinguish production and other environments
2025-10-18 22:41:23 +01:00
copilot-swe-agent[bot]
664a63211e Add visual examples for ConnectionFrameColor feature
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:35:35 +00:00
copilot-swe-agent[bot]
b7df1e80c8 Add implementation notes and summary for ConnectionFrameColor feature
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:34:43 +00:00
copilot-swe-agent[bot]
2d6563022e Add documentation for ConnectionFrameColor feature
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:33:31 +00:00
copilot-swe-agent[bot]
5423c84eed Update CSV serializer to include ConnectionFrameColor field
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:31:51 +00:00
copilot-swe-agent[bot]
d263fb1b80 Add ConnectionFrameColor feature for visual environment distinction
- Added ConnectionFrameColor enum with None, Red, Yellow, Green, Blue, Purple options
- Added ConnectionFrameColor property to AbstractConnectionRecord with inheritance support
- Updated XML serialization to save/load ConnectionFrameColor
- Added language resources for ConnectionFrameColor
- Implemented visual border rendering in InterfaceControl based on ConnectionFrameColor

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:29:59 +00:00
copilot-swe-agent[bot]
c72bd2a107 Consolidate debug log messages to single line
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:29:29 +00:00
copilot-swe-agent[bot]
8e4627c872 Add debug logging for edge case in tab navigation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:27:56 +00:00
copilot-swe-agent[bot]
ccbe99f828 Add edge case handling for tab navigation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:25:57 +00:00
copilot-swe-agent[bot]
ee483e3b2b Add Ctrl+Tab keyboard shortcuts for tab navigation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 21:25:20 +00:00
copilot-swe-agent[bot]
5b4b13828b Initial plan 2025-10-18 21:23:39 +00:00
copilot-swe-agent[bot]
4b0bc71fb0 Initial plan 2025-10-18 21:18:55 +00:00
Dimitrij
c28ae335b2 Merge pull request #2939 from mRemoteNG/copilot/fix-sql-injection-issue
Fix SQL injection vulnerabilities via parameterized queries
2025-10-18 22:11:18 +01:00
copilot-swe-agent[bot]
2d3830b747 Clarify comment about database-specific datetime types
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 20:38:22 +00:00
copilot-swe-agent[bot]
fe4e205772 Add clarifying comment about datetime parameter usage
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 20:36:32 +00:00
copilot-swe-agent[bot]
5e2fc8b0dc Fix SQL injection in SqlConnectionsSaver UpdateUpdatesTable method
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 20:33:47 +00:00
copilot-swe-agent[bot]
6403573e36 Fix SQL injection vulnerabilities using parameterized queries
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-18 20:32:21 +00:00
Dimitrij
39b863b57e Merge pull request #2940 from mRemoteNG/fix/aikido-security-sast-8815714-tnsC
[Aikido] AI Fix for Possible command injection via Process.Start
2025-10-18 21:31:15 +01:00
aikido-autofix[bot]
8e5cdcb6e5 fix(security): autofix Possible command injection via Process.Start 2025-10-18 20:29:05 +00:00
copilot-swe-agent[bot]
f5b7cd6fb1 Initial plan 2025-10-18 20:27:45 +00:00
Dimitrij
493ddc1f1f Merge pull request #2932 from mRemoteNG/copilot/fix-https-login-issue
Fix HTTP/HTTPS protocol to support multiple concurrent connections
2025-10-18 21:13:16 +01:00
Dimitrij
5ad338bdcc Merge pull request #2937 from mRemoteNG/renovate/nunit.console-3.x
Update dependency NUnit.Console to 3.20.2
2025-10-18 14:29:58 +01:00
renovate[bot]
d1a1adb994 Update dependency NUnit.Console to 3.20.2 2025-10-18 13:28:59 +00:00
Dimitrij
c879b030ad Merge pull request #2936 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.43.2
2025-10-18 14:28:40 +01:00
Dimitrij
8d1d55c38e Merge pull request #2938 from mRemoteNG/renovate/nunit.consolerunner-3.x
Update dependency NUnit.ConsoleRunner to 3.20.2
2025-10-18 14:28:21 +01:00
renovate[bot]
aef576d290 Update dependency NUnit.ConsoleRunner to 3.20.2 2025-10-18 05:11:19 +00:00
renovate[bot]
e34b0fded3 Update dependency AWSSDK.EC2 to 4.0.43.2 2025-10-18 02:13:16 +00:00
copilot-swe-agent[bot]
14e5e6a715 Add proper thread marshalling and improve cleanup safety
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-17 17:57:51 +00:00
copilot-swe-agent[bot]
0579273964 Fix async deadlock issues and improve error handling
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-17 17:56:04 +00:00
copilot-swe-agent[bot]
5839a836c8 Address code review feedback - improve async handling and safety
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-17 17:54:16 +00:00
copilot-swe-agent[bot]
236fff8014 Fix HTTP/HTTPS protocol to support multiple concurrent connections
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-17 17:51:36 +00:00
copilot-swe-agent[bot]
c1efefae81 Initial plan 2025-10-17 17:46:16 +00:00
Dimitrij
1e5bd44332 Merge pull request #2931 from MaxPlap/feature/VaultOpenbao-Connector
Feature/vault openbao connector
2025-10-17 16:59:18 +01:00
massimo.antonello
7478537f3e Revert RootNode Properties 2025-10-17 16:18:57 +02:00
massimo.antonello
b0f50b825f used winform window for credentials like other connectors 2025-10-17 16:14:06 +02:00
massimo.antonello
7509fcda52 Merge remote-tracking branch 'origin/v1.78.2-dev' into feature/VaultOpenbao-Connector
# Conflicts:
#	mRemoteNG/Language/Language.resx
2025-10-17 14:58:16 +02:00
massimo.antonello
0991cf74ef Secret Engine Property 2025-10-17 14:53:01 +02:00
massimo.antonello
61dd2ec8db started working 2025-10-17 11:49:17 +02:00
massimo.antonello
77643848b6 new properties 2025-10-17 11:48:40 +02:00
Dimitrij
21ab172041 fix 2025-10-17 09:12:57 +01:00
Dimitrij
d6c2c2158a Merge pull request #2930 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.43.1
2025-10-16 23:26:54 +01:00
renovate[bot]
0c50e2d78e Update dependency AWSSDK.EC2 to 4.0.43.1 2025-10-16 21:33:36 +00:00
Dimitrij
64183e8e7d Merge pull request #2929 from mRemoteNG/copilot/fix-panel-visibility-issue
Fix panel visibility issue when opening first connection
2025-10-16 22:32:56 +01:00
copilot-swe-agent[bot]
b9595d1650 Fix panel visibility check to use DockState
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 21:28:45 +00:00
copilot-swe-agent[bot]
fa3be420b8 Initial plan 2025-10-16 21:21:53 +00:00
Dimitrij
e2d1929553 Merge pull request #2925 from mRemoteNG/copilot/fix-options-panel-display
Fix Options panel corruption when toggling "Always show panel tabs"
2025-10-16 22:12:01 +01:00
Dimitrij
4f05e8dbe9 Merge pull request #2927 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.Core to 4.0.1.1
2025-10-16 22:11:38 +01:00
renovate[bot]
ea9e79d930 Update dependency AWSSDK.Core to 4.0.1.1 2025-10-16 21:08:10 +00:00
Dimitrij
e1a8d60cd7 Merge pull request #2926 from mRemoteNG/copilot/fix-empty-space-in-tabs
[WIP] Fix empty space issue between settings in Tabs & Panels
2025-10-16 22:07:31 +01:00
copilot-swe-agent[bot]
4e20049ea3 Fix Options panel corruption when toggling 'Always show panel tabs'
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 21:05:51 +00:00
copilot-swe-agent[bot]
89ccd33fd1 Fix empty space in Tabs & Panels settings by adjusting control positions
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 21:04:59 +00:00
copilot-swe-agent[bot]
4668104e36 Initial plan 2025-10-16 21:01:20 +00:00
copilot-swe-agent[bot]
b4aa30de23 Initial plan 2025-10-16 20:55:28 +00:00
Dimitrij
526cb1fb47 small fixes 2025-10-16 21:50:59 +01:00
Dimitrij
03b395ee15 Merge pull request #2924 from mRemoteNG/copilot/fix-first-connection-panel-issue
Fix connection panel visibility issue on first connection
2025-10-16 21:45:50 +01:00
copilot-swe-agent[bot]
4125344254 Fix panel visibility issue when opening first connection
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:40:36 +00:00
copilot-swe-agent[bot]
531e117731 Initial plan 2025-10-16 20:31:42 +00:00
Dimitrij
588fdca4d7 Merge pull request #2922 from mRemoteNG/copilot/add-options-dialog-prompt
Add confirmation prompt when closing Options dialog with unsaved changes
2025-10-16 21:24:59 +01:00
Dimitrij
285ca46c18 Merge branch 'v1.78.2-dev' into copilot/add-options-dialog-prompt 2025-10-16 21:24:41 +01:00
Dimitrij
8bdb83eb73 Merge pull request #2919 from mRemoteNG/copilot/fix-empty-option-panel
Fix empty Options panel when Theme is canceled
2025-10-16 21:21:52 +01:00
Dimitrij
d38b71d5ea Merge branch 'v1.78.2-dev' into copilot/fix-empty-option-panel 2025-10-16 21:21:06 +01:00
copilot-swe-agent[bot]
687f06937d Fix change tracking to ignore initial loading and add tests
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:20:00 +00:00
copilot-swe-agent[bot]
e0799a6772 Add change tracking and prompt for unsaved options
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:18:11 +00:00
Dimitrij
4943dce1a8 Merge pull request #2921 from mRemoteNG/copilot/fix-options-freezing-issue
[WIP] Fix freezing issue when opening and closing Options
2025-10-16 21:16:33 +01:00
copilot-swe-agent[bot]
8dee5c0d3c Also fix event handler accumulation in OptionsWindow
- Add _isInitialized flag to OptionsWindow to prevent multiple ThemeChanged subscriptions
- Ensures ThemeChanged event is only subscribed once

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:14:34 +00:00
Dimitrij
018b07299e Merge pull request #2920 from mRemoteNG/copilot/fix-rdp-settings-alignment
Fix RDP settings fields alignment in Connections options page
2025-10-16 21:13:21 +01:00
copilot-swe-agent[bot]
6f52b82a6d Fix Options dialog freezing when opening/closing multiple times
- Add _isInitialized flag to prevent multiple event subscriptions
- Skip re-initialization in FrmOptions_Load when form is reused
- Properly clean up Application.Idle handler in FormClosing
- Add test to verify form can be shown/hidden multiple times

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:13:01 +00:00
copilot-swe-agent[bot]
e1ee905286 Initial plan 2025-10-16 20:12:40 +00:00
copilot-swe-agent[bot]
6853b158ce Fix empty Options panel when Theme is canceled
- Call RevertSettings() on all option pages when Cancel is clicked
- Enhanced ThemePage.RevertSettings() to properly revert theme changes:
  - Store original active theme in LoadSettings
  - Clear modifiedThemes list on cancel
  - Restore original theme selection
- Add VisibleChanged handler to ensure panel is populated when form is shown
- Fixes issue where Options panel was empty after canceling theme selection

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:09:02 +00:00
copilot-swe-agent[bot]
d705b8a45d Fix RDP settings fields alignment in Connections options page
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 20:08:58 +00:00
copilot-swe-agent[bot]
cfb707d20f Initial plan 2025-10-16 20:07:55 +00:00
copilot-swe-agent[bot]
3aedc938cb Initial plan 2025-10-16 20:05:10 +00:00
copilot-swe-agent[bot]
c70e4c66e6 Initial plan 2025-10-16 20:02:27 +00:00
Dimitrij
b727dbd604 Merge pull request #2918 from mRemoteNG/copilot/fix-connection-options-setting
[WIP] Fix connection options displaying incorrect value
2025-10-16 20:54:27 +01:00
copilot-swe-agent[bot]
cd7f237920 Add Settings.Default.Save() to ConnectionContextMenu disconnect
Found another location where ConfirmCloseConnection is changed without immediately saving.
This ensures all four code paths that change this setting persist it immediately.

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 19:52:57 +00:00
Dimitrij
a1db763060 Merge pull request #2915 from mRemoteNG/copilot/fix-password-visibility-issue
Fix password with special characters not passed correctly to External Tools
2025-10-16 20:52:35 +01:00
copilot-swe-agent[bot]
01e22740ce Fix Options page not showing correct ConfirmCloseConnection value
- Add VisibleChanged event handler to ConnectionsPage to reload settings when page becomes visible
- Save settings immediately when user checks "Don't show this message again" checkbox during connection close
- Ensures Options dialog always displays current setting value, even if changed outside the dialog

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 19:51:02 +00:00
copilot-swe-agent[bot]
6b52b6b062 Initial plan 2025-10-16 19:43:33 +00:00
Dimitrij
6781fd57af Merge pull request #2916 from mRemoteNG/copilot/fix-connection-warning-option
Fix: Set ConfirmCloseConnection to Never when "Do not show this dialog again" is checked
2025-10-16 19:38:33 +01:00
copilot-swe-agent[bot]
8b22c7812d Fix: Set ConfirmCloseConnection to Never instead of decrementing
When user checks "Do not show this dialog again" while closing a connection,
the ConfirmCloseConnection setting should be set to Never (1) instead of being
decremented. The decrement approach was incorrectly changing All (4) to Multiple (3)
instead of Never (1), which didn't match user expectations.

Fixed in:
- ConnectionTab.cs
- ConnectionWindow.cs (2 occurrences)
- ConnectionContextMenu.cs
- frmMain.cs

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 18:27:54 +00:00
copilot-swe-agent[bot]
80c1391361 Fix password passing issue in External Tools
- Changed SetProcessProperties to use Arguments property instead of splitting by space and using ArgumentList
- Added tests to verify passwords with special characters like '=' are passed correctly
- This fixes the issue where passwords like 'Z-3=Wv99/Aq' were being split incorrectly

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 18:26:41 +00:00
copilot-swe-agent[bot]
c77e6b8616 Initial plan 2025-10-16 18:22:19 +00:00
copilot-swe-agent[bot]
e04ace4820 Initial plan 2025-10-16 18:20:37 +00:00
Dimitrij
d89ea96b34 Merge pull request #2904 from mRemoteNG/copilot/fix-encryption-issue-windows-11
Fix connection file encryption failure when password protection is enabled
2025-10-16 19:19:33 +01:00
massimo.antonello
0e83e525fe Properties 2025-10-16 15:06:16 +02:00
copilot-swe-agent[bot]
d5d9a8bf03 Fix PasswordString getter to never return empty password
Added defensive check in PasswordString getter to ensure it returns the default password when _customPassword is empty, even if Password property is true. This prevents encryption failures when Password is set inconsistently.

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 04:12:08 +00:00
copilot-swe-agent[bot]
ecb935868d Add tests for Password property edge cases
Added tests to verify that full file encryption works correctly when Password property is set directly without setting PasswordString, ensuring the fix prevents encryption failures.

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 04:08:46 +00:00
copilot-swe-agent[bot]
d736d3c388 Fix connection file encryption with password protection
Changed CreateProtectedAttribute to use PasswordString as source of truth instead of Password property. This prevents encryption failures when Password property is true but _customPassword is empty.

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 04:07:26 +00:00
copilot-swe-agent[bot]
2520ccd6be Initial plan 2025-10-16 03:57:26 +00:00
Dimitrij
4307dd043e Merge pull request #2903 from mRemoteNG/copilot/fix-about-tab-close-dialog
Fix About tab showing connection close dialog when closed
2025-10-16 04:54:20 +01:00
copilot-swe-agent[bot]
4ae8e4252b Convert frmAbout from Form to BaseWindow to prevent connection close dialog
- Changed frmAbout to inherit from BaseWindow instead of Form
- Updated HelpMenu to show About window in DockPanel
- Removed Form-specific properties (TopMost, StartPosition, FormBorderStyle, etc.)
- Removed Hide() behavior in OnFormClosing to allow proper tab closure
- Added TabText property for proper tab display

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-16 03:49:45 +00:00
copilot-swe-agent[bot]
995f03d03e Initial plan 2025-10-16 03:38:46 +00:00
Dimitrij
2965f598ac Merge pull request #2902 from mRemoteNG/renovate/protobuf-monorepo
Update dependency Google.Protobuf to 3.33.0
2025-10-16 04:29:48 +01:00
Dimitrij
0ad6f5aea1 Merge pull request #2901 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.43
2025-10-16 04:29:35 +01:00
renovate[bot]
c6fe8ff1f1 Update dependency Google.Protobuf to 3.33.0 2025-10-15 21:36:14 +00:00
renovate[bot]
a3a6917bf8 Update dependency AWSSDK.EC2 to 4.0.43 2025-10-15 21:36:08 +00:00
Dimitrij
1d8484957e fix menu issues and add translations 2025-10-15 19:04:42 +01:00
massimo.antonello
0fc3fb4a58 Merge remote-tracking branch 'origin/v1.78.2-dev' into feature/VaultOpenbao-Connector
# Conflicts:
#	mRemoteNG/Language/Language.de.resx
#	mRemoteNG/Language/Language.el.resx
#	mRemoteNG/Language/Language.es.resx
#	mRemoteNG/Language/Language.fi-FI.resx
#	mRemoteNG/Language/Language.fr.resx
#	mRemoteNG/Language/Language.hu.resx
#	mRemoteNG/Language/Language.it.resx
#	mRemoteNG/Language/Language.ja-JP.resx
#	mRemoteNG/Language/Language.ko-KR.resx
#	mRemoteNG/Language/Language.lt.resx
#	mRemoteNG/Language/Language.nb-NO.resx
#	mRemoteNG/Language/Language.nl.resx
#	mRemoteNG/Language/Language.pl.resx
#	mRemoteNG/Language/Language.pt-BR.resx
#	mRemoteNG/Language/Language.pt.resx
#	mRemoteNG/Language/Language.resx
#	mRemoteNG/Language/Language.sv-SE.resx
#	mRemoteNG/Language/Language.ta.resx
#	mRemoteNG/Language/Language.tr-TR.resx
#	mRemoteNG/Language/Language.uk.resx
#	mRemoteNG/Language/Language.zh-CN.resx
#	mRemoteNG/Language/Language.zh-TW.resx
2025-10-15 14:52:58 +02:00
Dimitrij
6ab67ee844 Merge pull request #2900 from mRemoteNG/copilot/fix-report-bug-link
Add "Report a Bug" menu item to Help menu and update bug report URL to GitHub issues
2025-10-15 11:11:33 +01:00
copilot-swe-agent[bot]
11fa059b1b Add Report a Bug menu item and update bug URL to GitHub issues
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-15 10:01:51 +00:00
copilot-swe-agent[bot]
847115abd6 Initial plan 2025-10-15 09:56:41 +00:00
Dimitrij
a5a0a310ce Update CREDITS.md
upd
2025-10-14 22:33:36 +01:00
Dimitrij
a72582b10f Merge pull request #2898 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.42
2025-10-14 22:06:24 +01:00
Dimitrij
929e22dc5a Merge pull request #2897 from mRemoteNG/renovate/dotnet-monorepo
Update dependency Microsoft.Extensions.DependencyModel to 9.0.10
2025-10-14 22:06:12 +01:00
renovate[bot]
ec4bca9bc0 Update dependency Microsoft.Extensions.DependencyModel to 9.0.10 2025-10-14 21:05:25 +00:00
Dimitrij
0648541ce1 lib update 2025-10-14 22:04:45 +01:00
renovate[bot]
77529f29f5 Update dependency AWSSDK.EC2 to 4.0.42 2025-10-14 20:49:17 +00:00
Dimitrij
02cf1739c0 Fix language msgs 2025-10-14 19:51:16 +01:00
massimo.antonello
903a5f5799 begin 2025-10-14 17:57:05 +02:00
Dimitrij
ccd955ca7e Merge pull request #2895 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update dependency AWSSDK.EC2 to 4.0.41
2025-10-14 08:12:08 +01:00
renovate[bot]
1af3b03fa8 Update dependency AWSSDK.EC2 to 4.0.41 2025-10-13 21:01:18 +00:00
Dimitrij
cc28186f73 Merge pull request #2894 from mRemoteNG/copilot/fix-options-panel-reopening
Fix Options panel not reopening after closing by clicking X on tab
2025-10-13 10:20:53 +01:00
Dimitrij
103bc8bd8b Update README.md
upd
2025-10-12 18:41:13 +01:00
copilot-swe-agent[bot]
9bcf7af467 Fix Options panel not reopening after closing
Set HideOnClose = true for OptionsWindow to prevent disposal when closed, and ensure embedded form is shown when window becomes visible again.

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-12 17:02:36 +00:00
copilot-swe-agent[bot]
8d10980875 Initial plan 2025-10-12 16:55:17 +00:00
Dimitrij
57d4945d71 Merge pull request #2890 from mRemoteNG/renovate/softprops-action-gh-release-digest
Update softprops/action-gh-release digest to 6da8fa9
2025-10-11 18:53:18 +01:00
renovate[bot]
11febb93bd Update softprops/action-gh-release digest to 6da8fa9 2025-10-11 17:51:41 +00:00
Dimitrij
cc9b83b0f8 Merge pull request #2889 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-10-10 21:49:40 +01:00
renovate[bot]
54386924d7 Update aws-sdk-net monorepo 2025-10-10 20:47:56 +00:00
Dimitrij
35417bc05d Merge pull request #2888 from mRemoteNG/renovate/aws-sdk-net-monorepo
Update aws-sdk-net monorepo
2025-10-10 09:04:39 +01:00
renovate[bot]
8b212dd87f Update aws-sdk-net monorepo 2025-10-09 23:04:22 +00:00
Dimitrij
488035e124 Merge pull request #2887 from mRemoteNG/copilot/add-warning-for-disconnect-option
Add confirmation dialog when disconnecting connections from context menu
2025-10-09 19:27:33 +01:00
copilot-swe-agent[bot]
9129edb725 Add confirmation dialog for disconnect operation from context menu
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-09 17:57:17 +00:00
copilot-swe-agent[bot]
6f3882e0ca Initial plan 2025-10-09 17:51:26 +00:00
Dimitrij
f810f6aa85 Merge pull request #2885 from mRemoteNG/copilot/add-dependency-check-texts
Add dependency check texts to language pack for internationalization
2025-10-09 11:15:37 +01:00
Dimitrij
6f13111c4c Merge pull request #2886 from mRemoteNG/copilot/add-reenable-checkbox-option
[WIP] Add option to reenable 'Do not show this message again' checkbox
2025-10-09 11:13:43 +01:00
copilot-swe-agent[bot]
fcca1a1fa3 Add dependency check texts to language pack
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-09 10:12:02 +00:00
copilot-swe-agent[bot]
ac0aa9e33b Enable ConfirmCloseConnection setting in Options dialog
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-09 10:10:50 +00:00
copilot-swe-agent[bot]
6109ff7783 Initial plan 2025-10-09 10:05:22 +00:00
copilot-swe-agent[bot]
4d2d24efb3 Initial plan 2025-10-09 10:04:47 +00:00
Dimitrij
e2b7081b9e Merge pull request #2883 from heing/v1.78.2-dev
Improve 1Password logging
2025-10-09 10:47:55 +01:00
Dimitrij
6ba7fedc18 Merge pull request #2882 from mRemoteNG/renovate/gherkin-36.x
Update dependency Gherkin to v36
2025-10-09 10:47:40 +01:00
Hein Gustavsen
3973fae8ef Improve 1Password logging 2025-10-09 09:44:08 +02:00
renovate[bot]
77752f494f Update dependency Gherkin to v36 2025-10-09 05:26:22 +00:00
Simon Monai
71574b62cb Update README.md - Minimum Requirements
Update Minimum Requirements download links and formatting to match results of #2870. 

Additionally fixed one typo.
2025-10-08 23:06:49 +02:00
Dimitrij
546ba16366 Merge pull request #2875 from mRemoteNG/renovate/cucumber.messages-30.x
Update dependency Cucumber.Messages to 30.1.0
2025-10-08 16:57:47 +01:00
renovate[bot]
f61ca2ad17 Update dependency Cucumber.Messages to 30.1.0 2025-10-08 15:55:24 +00:00
Dimitrij
781afd1c3b Merge pull request #2874 from heing/v1.78.2-dev
Add 1Password integration
2025-10-08 16:54:47 +01:00
Hein Gustavsen
2bfd8495ab Fix formatting in CHANGELOG.md
Removed an empty line in the Added section.
2025-10-08 16:02:28 +02:00
Hein Gustavsen
094fa65ad6 Update CHANGELOG, add 1Password integration 2025-10-08 16:01:01 +02:00
Hein Gustavsen
ec2a652d74 Add missing ECPOnePassword in Language.Designer.cs 2025-10-08 14:21:00 +02:00
Hein Gustavsen
1b55645b81 Add 1Password integration 2025-10-08 13:56:25 +02:00
Dimitrij
5c02581c81 Merge pull request #2872 from mRemoteNG/renovate/microsoft.data.sqlclient-6.x
Update dependency Microsoft.Data.SqlClient to 6.1.2
2025-10-08 07:54:42 +01:00
renovate[bot]
62cc4780ca Update dependency Microsoft.Data.SqlClient to 6.1.2 2025-10-08 05:57:32 +00:00
Dimitrij
8f26d57f40 NB release 2025-10-08 00:01:23 +01:00
Dimitrij
3bd2fe889a upd to for check x64 vc++ 2025-10-07 23:56:48 +01:00
Dimitrij
492a2629c2 Replace to x64 version 2025-10-07 23:32:21 +01:00
Dimitrij
b64ddf32ff fix 2025-10-07 23:31:28 +01:00
Dimitrij
e86a550985 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-10-07 23:31:12 +01:00
Dimitrij
fcccdacb99 Remove to update 2025-10-07 23:31:05 +01:00
Dimitrij
487de4c29b Merge pull request #2871 from simonai1254/v1.78.2-dev
Update README.md featuring Icon Project
2025-10-07 22:36:13 +01:00
Dimitrij
d36c6cb067 Merge pull request #2869 from mRemoteNG/copilot/fix-color-selection-for-panel-tabs
Fix Color property converter and add missing Display category attributes for TabColor
2025-10-07 22:31:30 +01:00
Simon Monai
a4b704252b Update README.md
Include Link to Fancy Icon Collection of @bearlikelion
2025-10-07 23:29:12 +02:00
Dimitrij
93e8d26a75 Merge branch 'v1.78.2-dev' into copilot/fix-color-selection-for-panel-tabs 2025-10-07 22:26:04 +01:00
copilot-swe-agent[bot]
0a3ecaac64 Fix Color property converter and add missing category attributes
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 21:17:26 +00:00
Simon Monai
ea6b762021 Update README.md
Add Visual C++ Dependency back in
2025-10-07 23:16:12 +02:00
Dimitrij
265a43e31c fix 2025-10-07 22:12:15 +01:00
copilot-swe-agent[bot]
6d156586ac Initial plan 2025-10-07 21:11:51 +00:00
Simon Monai
68e3f607a3 Update README.md
Fix Formatting Issue with Dependency Link
2025-10-07 22:40:48 +02:00
Dimitrij
0b240a3902 Merge pull request #2864 from mRemoteNG/copilot/add-color-support-for-connection-folders
Add Color property to connections and folders with inheritance support
2025-10-07 21:25:20 +01:00
Dimitrij
4082761606 Merge branch 'v1.78.2-dev' into copilot/add-color-support-for-connection-folders 2025-10-07 21:24:50 +01:00
Dimitrij
e68c42ba64 Merge pull request #2867 from mRemoteNG/copilot/fix-tab-color-selection-error
[WIP] Fix tab color dropdown selection error
2025-10-07 21:17:04 +01:00
copilot-swe-agent[bot]
347546ee0e Add TabColorConverter to fix Color to String conversion issue
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 20:15:32 +00:00
Dimitrij
ca717d6b80 Merge pull request #2863 from mRemoteNG/copilot/add-ard-connection-support
Add ARD (Apple Remote Desktop) protocol support for macOS connections
2025-10-07 21:12:17 +01:00
copilot-swe-agent[bot]
5d623d80eb Initial plan 2025-10-07 20:10:54 +00:00
Dimitrij
a2edbd9934 Merge pull request #2865 from mRemoteNG/copilot/add-connection-tab-colors
Add configurable connection tab colors to distinguish environments
2025-10-07 21:02:05 +01:00
copilot-swe-agent[bot]
5830f39d50 Add documentation for Tab Color feature
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:51:26 +00:00
copilot-swe-agent[bot]
0aa0b59635 Add documentation for Color property in folders and inheritance
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:50:10 +00:00
copilot-swe-agent[bot]
3c6a485647 Add TabColor property to connection info and implement tab coloring
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:49:32 +00:00
copilot-swe-agent[bot]
bbe1fa8416 Add Color property to Language.Designer.cs and add inheritance tests
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:49:21 +00:00
copilot-swe-agent[bot]
ac4469bb4a Add ARD protocol support to UI, port scanning, and tests
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:48:57 +00:00
copilot-swe-agent[bot]
9e61e8eafa Add Color property to connections and folders with inheritance support
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:47:07 +00:00
copilot-swe-agent[bot]
b193199268 Add ARD protocol to VNC property attributes and default port handling
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:45:38 +00:00
copilot-swe-agent[bot]
f8b7d37af1 Add ARD (Apple Remote Desktop) protocol support
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:42:31 +00:00
Dimitrij
b3e9202d72 Merge pull request #2862 from mRemoteNG/copilot/fix-unhandled-exception-panel-closure
Fix unhandled exception when closing panel with active connections
2025-10-07 20:40:35 +01:00
copilot-swe-agent[bot]
0f819ade56 Initial plan 2025-10-07 19:39:14 +00:00
copilot-swe-agent[bot]
d682afcde2 Initial plan 2025-10-07 19:39:03 +00:00
copilot-swe-agent[bot]
e67754ee9f Fix unhandled exception when closing panel with connections
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:35:18 +00:00
copilot-swe-agent[bot]
4897771fbf Initial plan 2025-10-07 19:35:06 +00:00
copilot-swe-agent[bot]
4128f3404a Initial plan 2025-10-07 19:31:35 +00:00
Dimitrij
7bc25ceb38 Merge pull request #2861 from mRemoteNG/copilot/add-autofocus-to-password-field
[WIP] Add autofocus to password field on startup
2025-10-07 20:29:40 +01:00
Dimitrij
f77f0f5e04 Merge pull request #2859 from mRemoteNG/copilot/fix-username-field-visibility
Fix Username field visibility for External Tool protocol
2025-10-07 20:28:48 +01:00
copilot-swe-agent[bot]
0e666efaad Add autofocus to password field in FrmPassword form
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:26:14 +00:00
copilot-swe-agent[bot]
e2893b9516 Add IntApp to Username property supported protocols
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 19:24:01 +00:00
copilot-swe-agent[bot]
fb86b13948 Initial plan 2025-10-07 19:22:15 +00:00
copilot-swe-agent[bot]
e22cc6921d Initial plan 2025-10-07 19:19:17 +00:00
Dimitrij
42fdd91206 Merge pull request #2857 from mRemoteNG/copilot/fix-default-panel-opening
Fix Update panel auto-loading on startup
2025-10-07 20:14:21 +01:00
copilot-swe-agent[bot]
2329d95002 Remove automatic Update panel display at startup
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 16:49:36 +00:00
copilot-swe-agent[bot]
8dda6ba13f Fix Update panel auto-checking on load
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 16:47:29 +00:00
copilot-swe-agent[bot]
156e2b8056 Initial plan 2025-10-07 16:41:34 +00:00
Dimitrij
aa48324b6d NB release 2025-10-07 17:10:32 +01:00
Dimitrij
d2b05ef7c3 renaming of folder to better represent its purpose 2025-10-07 17:01:48 +01:00
Dimitrij
75545e60b3 Merge pull request #2855 from mRemoteNG/copilot/fix-login-name-display-issue
Fix missing Username field for HTTP and HTTPS protocols
2025-10-07 17:00:27 +01:00
Dimitrij
b3d0b30b56 Merge pull request #2854 from mRemoteNG/copilot/refactor-settings-popup-to-panel
Refactor settings dialog to dockable panel for consistency
2025-10-07 16:54:54 +01:00
Dimitrij
3ed3729fc2 Merge pull request #2852 from mRemoteNG/copilot/fix-object-deserialization-vulnerability
Fix XML External Entity (XXE) vulnerability in XML deserialization
2025-10-07 16:51:36 +01:00
copilot-swe-agent[bot]
cb7ba46be6 Add comprehensive security tests for SecureXmlHelper
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:24:35 +00:00
copilot-swe-agent[bot]
933b21598e Add Username field support for HTTP and HTTPS protocols
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:23:46 +00:00
copilot-swe-agent[bot]
7a8442d9ea Handle FrmOptions visibility and window lifecycle
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:23:39 +00:00
copilot-swe-agent[bot]
c405186533 Update test files to use SecureXmlHelper for consistency
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:23:39 +00:00
copilot-swe-agent[bot]
5d150115a8 Create OptionsWindow for docked settings panel
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:22:20 +00:00
copilot-swe-agent[bot]
26bc38cf8c Add SecureXmlHelper and update all XML deserialization to prevent XXE attacks
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 15:20:14 +00:00
copilot-swe-agent[bot]
8f769cdda3 Initial plan 2025-10-07 15:16:42 +00:00
copilot-swe-agent[bot]
6b35cd3aee Initial plan 2025-10-07 15:16:03 +00:00
copilot-swe-agent[bot]
4ae1281a3a Initial plan 2025-10-07 15:06:32 +00:00
Dimitrij
9984d4bc8f Merge pull request #2850 from mRemoteNG/copilot/fix-d3d20276-2cee-4d8f-af65-24f3320db36a
Fix password dialog appearing behind splash screen on startup
2025-10-07 16:05:53 +01:00
Dimitrij
c987ee9fd3 Merge pull request #2851 from mRemoteNG/copilot/fix-3efd67f4-15e3-43e9-9b58-50941b183621
Fix path traversal vulnerability in file operations
2025-10-07 16:04:10 +01:00
copilot-swe-agent[bot]
a031e6f5f7 Add path validation to prevent path traversal attacks
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 14:04:00 +00:00
copilot-swe-agent[bot]
da386c3119 Close splash screen before loading connections to fix password dialog z-order
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-10-07 14:02:00 +00:00
copilot-swe-agent[bot]
bfd29fc0fc Initial plan 2025-10-07 13:57:18 +00:00
copilot-swe-agent[bot]
9617776be1 Initial plan 2025-10-07 13:55:19 +00:00
Dimitrij
765f2abc40 Merge pull request #2848 from mRemoteNG/renovate/softprops-action-gh-release-digest
chore(deps): update softprops/action-gh-release digest to aec2ec5
2025-10-07 08:12:44 +01:00
Dimitrij
519bc42e0a Merge pull request #2847 from mRemoteNG/renovate/nunit3testadapter-5.x
chore(deps): update dependency nunit3testadapter to 5.2.0
2025-10-07 08:12:03 +01:00
Dimitrij
6537e6bce6 Merge pull request #2846 from mRemoteNG/renovate/reportgenerator-5.x
chore(deps): update dependency reportgenerator to 5.4.17
2025-10-07 08:11:47 +01:00
renovate[bot]
494aff1bd3 chore(deps): update softprops/action-gh-release digest to aec2ec5 2025-10-07 04:37:18 +00:00
renovate[bot]
927527b888 chore(deps): update dependency nunit3testadapter to 5.2.0 2025-10-06 22:40:49 +00:00
renovate[bot]
08054e4873 chore(deps): update dependency reportgenerator to 5.4.17 2025-10-06 22:40:43 +00:00
Dimitrij
a092fef575 Merge pull request #2845 from mRemoteNG/renovate/microsoft.web.webview2-1.x
chore(deps): update dependency microsoft.web.webview2 to 1.0.3537.50
2025-10-06 17:35:02 +01:00
renovate[bot]
2808b3d3da chore(deps): update dependency microsoft.web.webview2 to 1.0.3537.50 2025-10-06 16:28:54 +00:00
Dimitrij
ef3b236d73 fix element placement for #2842 2025-10-06 17:27:25 +01:00
Dimitrij
26f0365026 Upd translation 2025-10-06 13:51:34 +01:00
Dimitrij
25ebfee6e2 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-10-06 13:51:16 +01:00
Dimitrij
c1ada03db1 Fix for #2841 - verify if vc++ distributed x86 installed 2025-10-06 13:51:08 +01:00
Dimitrij
0b17360346 Update README.md
upd
2025-10-06 11:54:40 +01:00
Dimitrij
da18b37a54 Fix markdown formatting for Nightly release badge
upd
2025-10-06 11:52:36 +01:00
Dimitrij
4cf040c01e Update README.md
upd
2025-10-06 11:50:38 +01:00
Dimitrij
95b77515dc Update Nightly build link and download badge
upd
2025-10-06 11:47:59 +01:00
Dimitrij
65bbd8ca05 Update README.md
upd
2025-10-06 11:44:36 +01:00
Dimitrij
dbba954522 small fixes 2025-10-03 22:19:39 +01:00
Dimitrij
26d46be243 dependencies are deprecated 2025-10-03 22:18:08 +01:00
Dimitrij
135f8290ec Merge pull request #2839 from mRemoteNG/fix/aikido-security-sast-8173389-4nsd
[Aikido] AI Fix for Possible command injection via Process.Start
2025-10-03 22:00:36 +01:00
Dimitrij
a8b4e1178d Merge pull request #2837 from mRemoteNG/renovate/cucumber.messages-30.x
chore(deps): update dependency cucumber.messages to v30
2025-10-03 22:00:14 +01:00
Dimitrij
8bdf66ef02 Merge pull request #2838 from mRemoteNG/fix/aikido-security-sast-8173368-kjEd
[Aikido] AI Fix for Potential SQL injection via string-based query concatenation
2025-10-03 21:59:48 +01:00
aikido-autofix[bot]
5209b08709 fix(security): autofix Possible command injection via Process.Start 2025-10-03 20:58:27 +00:00
aikido-autofix[bot]
933247dc2f fix(security): autofix Potential SQL injection via string-based query concatenation 2025-10-03 20:57:07 +00:00
renovate[bot]
4e43bf9d8f chore(deps): update dependency cucumber.messages to v30 2025-10-03 16:58:47 +00:00
Dimitrij
0f6a5816db Merge pull request #2835 from mRemoteNG/renovate/aws-sdk-net-monorepo
chore(deps): update aws-sdk-net monorepo
2025-10-02 22:31:54 +01:00
Dimitrij
8021678995 Merge pull request #2836 from mRemoteNG/renovate/major-vstest-monorepo
chore(deps): update dependency microsoft.net.test.sdk to v18
2025-10-02 22:24:41 +01:00
renovate[bot]
147b5edec4 chore(deps): update dependency microsoft.net.test.sdk to v18 2025-10-02 11:24:09 +00:00
renovate[bot]
2edbf3222e chore(deps): update aws-sdk-net monorepo 2025-10-01 22:05:23 +00:00
Dimitrij
f6bf8c229c Merge pull request #2834 from mRemoteNG/renovate/aws-sdk-net-monorepo
chore(deps): update aws-sdk-net monorepo
2025-09-30 10:16:42 +01:00
renovate[bot]
c30b90af44 chore(deps): update aws-sdk-net monorepo 2025-09-29 21:07:53 +00:00
Dimitrij
3b72e7af3d Merge pull request #2832 from mRemoteNG/renovate/aws-sdk-net-monorepo
chore(deps): update dependency awssdk.ec2 to 4.0.40.1
2025-09-29 22:07:17 +01:00
renovate[bot]
37004647eb chore(deps): update dependency awssdk.ec2 to 4.0.40.1 2025-09-29 16:46:13 +00:00
Dimitrij
c85cb84e31 Merge pull request #2829 from mRemoteNG/renovate/configure
chore: Configure Renovate
2025-09-29 17:45:28 +01:00
renovate[bot]
d504143d7e Add renovate.json 2025-09-26 18:08:44 +00:00
Dimitrij
db1c7b9708 Merge pull request #2827 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-140.x
chore(deps): update dependency chromiumembeddedframework.runtime.win-arm64 to v140
2025-09-25 09:36:29 +01:00
Dimitrij
064cb34705 Merge pull request #2828 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-140.x
chore(deps): update dependency chromiumembeddedframework.runtime.win-x64 to v140
2025-09-25 09:36:09 +01:00
Dimitrij
02c442ef99 Merge pull request #2825 from mRemoteNG/renovate/reportgenerator-5.x
chore(deps): update dependency reportgenerator to 5.4.16
2025-09-25 09:35:54 +01:00
renovate[bot]
e358cafb3f chore(deps): update dependency reportgenerator to 5.4.16 2025-09-24 20:44:07 +00:00
renovate[bot]
40e447bc05 chore(deps): update dependency chromiumembeddedframework.runtime.win-x64 to v140 2025-09-24 15:31:30 +00:00
renovate[bot]
f0bac9ee78 chore(deps): update dependency chromiumembeddedframework.runtime.win-arm64 to v140 2025-09-24 15:31:22 +00:00
Dimitrij
a75fbad0ea Merge pull request #2823 from mRemoteNG/renovate/awssdk.core-4.x
chore(deps): update dependency awssdk.core to 4.0.0.29
2025-09-23 23:57:32 +01:00
renovate[bot]
ae5a919421 chore(deps): update dependency awssdk.core to 4.0.0.29 2025-09-23 22:57:10 +00:00
Dimitrij
749cb7578a Merge pull request #2824 from mRemoteNG/renovate/awssdk.ec2-4.x
chore(deps): update dependency awssdk.ec2 to 4.0.40
2025-09-23 23:56:38 +01:00
renovate[bot]
622ea20819 chore(deps): update dependency awssdk.ec2 to 4.0.40 2025-09-23 22:08:58 +00:00
Dimitrij
a9374a5eb1 Merge pull request #2822 from mRemoteNG/copilot/fix-3abc8ac6-985e-4856-8afb-a91a0dca6d12
Remove insecure pull_request_target trigger from add_PR_2_chlog.yml workflow
2025-09-23 16:25:10 +01:00
copilot-swe-agent[bot]
1b78b68e33 Remove insecure pull_request_target trigger from workflow
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2025-09-23 09:30:17 +00:00
copilot-swe-agent[bot]
3e97fe0490 Initial plan 2025-09-23 09:26:03 +00:00
Dimitrij
2bb34607cc Merge pull request #2813 from mRemoteNG/renovate/gherkin-35.x
chore(deps): update dependency gherkin to 35.1.0
2025-09-21 22:08:02 +01:00
Dimitrij
fe7fca180e Merge pull request #2814 from mRemoteNG/renovate/reportgenerator-5.x
chore(deps): update dependency reportgenerator to 5.4.14
2025-09-21 22:07:49 +01:00
renovate[bot]
0a86b45d59 chore(deps): update dependency reportgenerator to 5.4.14 2025-09-21 13:56:20 +00:00
Dimitrij
62e0dd365b Merge pull request #2788 from mRemoteNG/renovate/reportgenerator-5.x
chore(deps): update dependency reportgenerator to 5.4.14
2025-09-21 14:55:49 +01:00
renovate[bot]
b39c561b72 chore(deps): update dependency gherkin to 35.1.0 2025-09-20 13:43:33 +00:00
Dimitrij
02d099629f Merge pull request #2812 from ciis0/cschulz/fix-refocus
Fix RDP refocus issues
2025-09-19 18:12:15 +01:00
Dimitrij
0f55cd2395 Update mRemoteNG/Connection/Protocol/RDP/RdpProtocol.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-19 11:39:23 +01:00
Christoph Schulz
119451e4f6 Fix RDP refocus issues
Fixes #1535
2025-09-19 09:25:40 +02:00
Dimitrij
0f6d4e5760 Merge pull request #2811 from mRemoteNG/renovate/awssdk.ec2-4.x
chore(deps): update dependency awssdk.ec2 to 4.0.39
2025-09-18 23:43:55 +01:00
renovate[bot]
452ed6a754 chore(deps): update dependency awssdk.ec2 to 4.0.39 2025-09-18 22:07:33 +00:00
Dimitrij
40928b8ab0 Merge pull request #2808 from mRemoteNG/renovate/awssdk.ec2-4.x
chore(deps): update dependency awssdk.ec2 to 4.0.38
2025-09-17 21:46:43 +01:00
renovate[bot]
f1ed380b42 chore(deps): update dependency awssdk.ec2 to 4.0.38 2025-09-17 20:34:27 +00:00
Dimitrij
e28ae8f2ba Merge pull request #2805 from mRemoteNG/renovate/awssdk.core-4.x
chore(deps): update dependency awssdk.core to 4.0.0.28
2025-09-17 10:57:26 +01:00
renovate[bot]
d8c6d9d558 chore(deps): update dependency awssdk.core to 4.0.0.28 2025-09-17 09:56:31 +00:00
Dimitrij
607123f0be Merge pull request #2806 from mRemoteNG/renovate/awssdk.ec2-4.x
chore(deps): update dependency awssdk.ec2 to 4.0.37.1
2025-09-17 10:56:00 +01:00
Dimitrij
0ff72ae665 Merge pull request #2807 from Greenie0701/arm64_dotnet
Add ARM64 support for .NET runtime detection
2025-09-17 10:55:37 +01:00
Dimitrij
552cee1c24 Update mRemoteNG/App/Update/DotNetRuntimeCheck.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-17 10:55:28 +01:00
MS-GITS
44f05a2968 Add ARM64 support for .NET runtime detection 2025-09-17 14:52:54 +05:30
MS-GITS
244fbf56d1 Add ARM64 support for .NET runtime detection 2025-09-17 14:50:41 +05:30
renovate[bot]
24845039f1 chore(deps): update dependency awssdk.ec2 to 4.0.37.1 2025-09-16 21:07:05 +00:00
Dimitrij
2e5be847ce Merge pull request #2804 from mRemoteNG/fix/aikido-security-sast--7464421-c51u
[Aikido] AI Fix for Path traversal attack possible
2025-09-16 20:44:12 +01:00
Dimitrij
9e947f7a36 Merge pull request #2803 from mRemoteNG/fix/aikido-security-sast--7464399-kZ9j
[Aikido] AI Fix for Path traversal attack possible
2025-09-16 20:43:59 +01:00
Dimitrij
87a3c60330 Merge pull request #2802 from mRemoteNG/fix/aikido-security-sast--7464375-mF7U
[Aikido] AI Fix for Path traversal attack possible
2025-09-16 20:43:47 +01:00
Dimitrij
0d460d543b Merge pull request #2801 from mRemoteNG/fix/aikido-security-sast--7464275-6ovw
[Aikido] AI Fix for Path traversal attack possible
2025-09-16 20:43:33 +01:00
Dimitrij
eb535cad2c Merge pull request #2800 from mRemoteNG/fix/aikido-security-sast--7464234-hobo
[Aikido] AI Fix for Path traversal attack possible
2025-09-16 20:43:01 +01:00
Dimitrij
eff00033b0 Merge pull request #2799 from mRemoteNG/fix/aikido-security-sast--7464163-cUFL
[Aikido] AI Fix for 3rd party Github Actions should be pinned
2025-09-16 20:42:19 +01:00
aikido-autofix[bot]
b591f97297 fix(security): autofix Path traversal attack possible 2025-09-16 16:09:27 +00:00
aikido-autofix[bot]
9501bb4428 fix(security): autofix Path traversal attack possible 2025-09-16 16:09:01 +00:00
aikido-autofix[bot]
4e9757c743 fix(security): autofix Path traversal attack possible 2025-09-16 16:08:34 +00:00
aikido-autofix[bot]
8f35b2ef71 fix(security): autofix Path traversal attack possible 2025-09-16 16:05:48 +00:00
aikido-autofix[bot]
3782eeeaf1 fix(security): autofix Path traversal attack possible 2025-09-16 16:04:39 +00:00
aikido-autofix[bot]
ec78de7a74 fix(security): autofix 3rd party Github Actions should be pinned 2025-09-16 16:02:43 +00:00
Dimitrij
bd1f311d09 CET compatibility
NB release
2025-09-16 12:03:15 +01:00
Dimitrij
31bf36db89 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-09-16 11:09:45 +01:00
Dimitrij
a96d344c22 adding missed தமிழ் (ta) Translation update #2690 from 1.77.3 branch 2025-09-16 11:09:37 +01:00
Dimitrij
dac4988514 Merge pull request #2797 from mRemoteNG/renovate/newtonsoft.json-13.x
chore(deps): update dependency newtonsoft.json to 13.0.4
2025-09-16 10:33:04 +01:00
renovate[bot]
a1f50f152c chore(deps): update dependency newtonsoft.json to 13.0.4 2025-09-16 08:54:55 +00:00
Dimitrij
06a47f4a06 Merge pull request #2795 from simonai1254/patch-1
Update minimum requirements
2025-09-16 09:40:32 +01:00
Simon Monai
f7aa9f7b92 Update README.md - Minimum Requirements
Update minimum Requirements to properly show .Net 9.0 and clarify Terminal Service Client requirements
2025-09-16 02:11:41 +02:00
Simon Monai
894b11704c Update README.md
Update .NET Runtime Requirements (9.0) for new version and remove Visual C++ Redistributables as the appear to no longer be necessary
2025-09-16 02:04:51 +02:00
Dimitrij
5b1b6ddc73 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-09-15 23:40:21 +01:00
Dimitrij
baa5abab2e clenup 2025-09-15 23:40:13 +01:00
Dimitrij
1b2ae29f4a Merge pull request #2793 from mRemoteNG/renovate/gherkin-35.x
chore(deps): update dependency gherkin to v35
2025-09-15 23:34:18 +01:00
Dimitrij
99a2b968d5 Merge pull request #2792 from mRemoteNG/renovate/actions-checkout-5.x
chore(deps): update actions/checkout action to v5
2025-09-15 23:34:04 +01:00
Dimitrij
029672a907 lib update, NB release 2025-09-15 23:32:42 +01:00
Dimitrij
31ecbaa977 .Net version detection fix
optimization
2025-09-15 23:32:06 +01:00
Dimitrij
6580e1b6db Enhance Build_mR-NB.yml with workflow_dispatch
Add manual dispatch option with release flag to workflow
2025-09-15 21:14:20 +01:00
renovate[bot]
16bbe4ccc0 chore(deps): update dependency gherkin to v35 2025-09-14 09:57:40 +00:00
renovate[bot]
6ea3642700 chore(deps): update actions/checkout action to v5 2025-09-14 09:57:36 +00:00
renovate[bot]
b8270d2264 chore(deps): update dependency reportgenerator to 5.4.13 2025-09-13 21:15:42 +00:00
Dimitrij
7b7fe1b062 Merge pull request #2787 from mRemoteNG/renovate/google.protobuf-3.x
chore(deps): update dependency google.protobuf to 3.32.1
2025-09-13 21:44:52 +01:00
Dimitrij
e67c97cc21 Update workflow to trigger on specific branch 2025-09-13 21:40:37 +01:00
Dimitrij
1033214658 Merge pull request #2786 from mRemoteNG/renovate/awssdk.core-4.x
chore(deps): update dependency awssdk.core to 4.0.0.27
2025-09-13 21:38:16 +01:00
Dimitrij
55552ad118 Update workflow to handle default branch and PR merges 2025-09-13 21:32:40 +01:00
renovate[bot]
552c53b15d chore(deps): update dependency google.protobuf to 3.32.1 2025-09-13 19:30:23 +00:00
renovate[bot]
278fc30ae8 chore(deps): update dependency awssdk.core to 4.0.0.27 2025-09-13 19:30:19 +00:00
Dimitrij
80fb676763 Merge pull request #2779 from mRemoteNG/renovate/system.io.pipelines-9.x
chore(deps): update dependency system.io.pipelines to 9.0.9
2025-09-13 15:31:41 +01:00
Dimitrij
c511fd1895 Merge branch 'v1.78.2-dev' into renovate/system.io.pipelines-9.x 2025-09-13 15:31:35 +01:00
Dimitrij
e43a644eb0 Merge pull request #2777 from mRemoteNG/renovate/system.drawing.common-9.x
chore(deps): update dependency system.drawing.common to 9.0.9
2025-09-13 15:30:57 +01:00
Dimitrij
70c16caf6b Merge branch 'v1.78.2-dev' into renovate/system.drawing.common-9.x 2025-09-13 15:30:50 +01:00
Dimitrij
21dcfc9435 Merge pull request #2775 from mRemoteNG/renovate/system.diagnostics.eventlog-9.x
chore(deps): update dependency system.diagnostics.eventlog to 9.0.9
2025-09-13 15:29:45 +01:00
Dimitrij
56ff019185 Merge branch 'v1.78.2-dev' into renovate/system.diagnostics.eventlog-9.x 2025-09-13 15:29:39 +01:00
Dimitrij
44a6cb31aa Merge pull request #2780 from mRemoteNG/renovate/system.management-9.x
chore(deps): update dependency system.management to 9.0.9
2025-09-13 15:28:14 +01:00
Dimitrij
a01ebdaa9d Merge pull request #2781 from mRemoteNG/renovate/system.reflection.metadata-9.x
chore(deps): update dependency system.reflection.metadata to 9.0.9
2025-09-13 15:27:57 +01:00
Dimitrij
651b742cc2 Merge pull request #2778 from mRemoteNG/renovate/system.formats.asn1-9.x
chore(deps): update dependency system.formats.asn1 to 9.0.9
2025-09-13 15:27:46 +01:00
Dimitrij
e2b1eb6e4a Merge pull request #2783 from mRemoteNG/renovate/system.security.cryptography.protecteddata-9.x
chore(deps): update dependency system.security.cryptography.protecteddata to 9.0.9
2025-09-13 15:27:25 +01:00
Dimitrij
2546620c8d Merge pull request #2784 from mRemoteNG/renovate/system.security.permissions-9.x
chore(deps): update dependency system.security.permissions to 9.0.9
2025-09-13 15:26:46 +01:00
Dimitrij
826f75348c Merge pull request #2776 from mRemoteNG/renovate/system.directoryservices-9.x
chore(deps): update dependency system.directoryservices to 9.0.9
2025-09-13 15:26:33 +01:00
Dimitrij
b27462da05 Merge pull request #2774 from mRemoteNG/renovate/system.diagnostics.diagnosticsource-9.x
chore(deps): update dependency system.diagnostics.diagnosticsource to 9.0.9
2025-09-13 15:26:04 +01:00
renovate[bot]
ad0ade5dd4 chore(deps): update dependency system.security.permissions to 9.0.9 2025-09-10 12:52:32 +00:00
renovate[bot]
6e3cf4630e chore(deps): update dependency system.security.cryptography.protecteddata to 9.0.9 2025-09-10 12:52:28 +00:00
renovate[bot]
6f3768db4b chore(deps): update dependency system.reflection.metadata to 9.0.9 2025-09-10 09:01:05 +00:00
renovate[bot]
98220ccf93 chore(deps): update dependency system.management to 9.0.9 2025-09-10 09:01:01 +00:00
renovate[bot]
52688d7145 chore(deps): update dependency system.io.pipelines to 9.0.9 2025-09-10 06:31:41 +00:00
renovate[bot]
b24edae66b chore(deps): update dependency system.formats.asn1 to 9.0.9 2025-09-10 06:31:37 +00:00
renovate[bot]
ac39ce26ee chore(deps): update dependency system.drawing.common to 9.0.9 2025-09-10 03:14:02 +00:00
renovate[bot]
cf041c661b chore(deps): update dependency system.directoryservices to 9.0.9 2025-09-10 03:13:59 +00:00
Dimitrij
9d173d0bdc Refactor GitHub Actions workflow for changelog updates 2025-09-10 00:07:43 +01:00
Dimitrij
aafb608149 Update GitHub Actions workflow for Renovate PRs 2025-09-09 23:27:09 +01:00
renovate[bot]
04dd125ee6 chore(deps): update dependency system.diagnostics.eventlog to 9.0.9 2025-09-09 22:25:19 +00:00
renovate[bot]
e501235b2e chore(deps): update dependency system.diagnostics.diagnosticsource to 9.0.9 2025-09-09 22:25:15 +00:00
Dimitrij
7c6a322787 Refactor GitHub Actions workflow for changelog updates 2025-09-09 23:16:32 +01:00
Dimitrij
eed729181b Update workflow for changelog generation 2025-09-09 22:48:02 +01:00
Dimitrij
ce9d42d304 Merge pull request #2773 from mRemoteNG/renovate/system.configuration.configurationmanager-9.x
chore(deps): update dependency system.configuration.configurationmanager to 9.0.9
2025-09-09 22:30:13 +01:00
Dimitrij
733e31e54b Merge branch 'v1.78.2-dev' into renovate/system.configuration.configurationmanager-9.x 2025-09-09 22:30:02 +01:00
Dimitrij
f1714f3228 Update workflow to modify changelog after PR merge 2025-09-09 21:17:05 +01:00
Dimitrij
44c90f0de4 Fix variable interpolation in changelog update
upd
2025-09-09 21:01:48 +01:00
Dimitrij
8268310685 added new section 2025-09-09 20:58:56 +01:00
Dimitrij
d64eaf6234 Refactor PR title extraction and changelog update
upd
2025-09-09 20:57:26 +01:00
Dimitrij
4d0b848676 Update workflow to handle Renovate PRs on push
upd
2025-09-09 20:53:23 +01:00
Dimitrij
d508ca33c8 Merge pull request #2772 from mRemoteNG/renovate/system.collections.immutable-9.x
chore(deps): update dependency system.collections.immutable to 9.0.9
2025-09-09 20:29:34 +01:00
renovate[bot]
86fdea129b chore(deps): update dependency system.configuration.configurationmanager to 9.0.9 2025-09-09 18:30:04 +00:00
renovate[bot]
79af98845a chore(deps): update dependency system.collections.immutable to 9.0.9 2025-09-09 18:29:59 +00:00
Dimitrij
2c15c6b0ed Merge pull request #2771 from mRemoteNG/renovate/microsoft.extensions.dependencymodel-9.x
chore(deps): update dependency microsoft.extensions.dependencymodel to 9.0.9
2025-09-09 18:18:31 +01:00
Dimitrij
52ee10efda Merge branch 'v1.78.2-dev' into renovate/microsoft.extensions.dependencymodel-9.x 2025-09-09 18:18:19 +01:00
Dimitrij
2da7d02a2c Update GitHub Actions workflow for PRs
update
2025-09-09 17:50:38 +01:00
Dimitrij
7af4ba27f3 Merge pull request #2770 from mRemoteNG/renovate/microsoft.extensions.configuration.usersecrets-9.x
chore(deps): update dependency microsoft.extensions.configuration.usersecrets to 9.0.9
2025-09-09 17:42:16 +01:00
Dimitrij
46cd974a58 Update changelog update workflow
Fix sed command to append entries in CHANGELOG.md
2025-09-09 17:35:32 +01:00
renovate[bot]
3d791b7f78 chore(deps): update dependency microsoft.extensions.dependencymodel to 9.0.9 2025-09-09 14:33:54 +00:00
renovate[bot]
29e27c1283 chore(deps): update dependency microsoft.extensions.configuration.usersecrets to 9.0.9 2025-09-09 14:33:49 +00:00
Dimitrij
8434ab460c Merge pull request #2768 from mRemoteNG/renovate/cucumber.messages-29.x
chore(deps): update dependency cucumber.messages to v29
2025-09-08 18:02:21 +01:00
Dimitrij
561d073bba Merge pull request #2767 from mRemoteNG/renovate/microsoft.web.webview2-1.x
chore(deps): update dependency microsoft.web.webview2 to 1.0.3485.44
2025-09-08 18:02:09 +01:00
renovate[bot]
d46d37acb9 chore(deps): update dependency cucumber.messages to v29 2025-09-08 14:50:37 +00:00
renovate[bot]
4f4d841137 chore(deps): update dependency microsoft.web.webview2 to 1.0.3485.44 2025-09-08 14:50:33 +00:00
Dimitrij
b7e80ceee9 Merge pull request #2766 from Greenie0701/fix_win_ci
ci: fix T4 template transform by adding EnvDTE & Interop references
2025-09-08 09:20:00 +01:00
Wise Man
8a3112c71f ci: fix T4 template transform by adding EnvDTE & Interop references 2025-09-07 09:28:45 +05:30
Dimitrij
4276b1439b Merge pull request #2765 from mRemoteNG/renovate/awssdk.ec2-4.x
Update dependency AWSSDK.EC2 to 4.0.37
2025-09-05 10:38:42 +01:00
renovate[bot]
3f626149f4 Update dependency AWSSDK.EC2 to 4.0.37 2025-09-04 20:57:09 +00:00
Dimitrij
30b674f8f5 .net check 2025-08-31 01:12:03 +01:00
Dimitrij
fe3fb46e94 undo 2025-08-28 18:15:07 +01:00
Dimitrij
99c524c7b6 fix? 2025-08-28 18:08:26 +01:00
Dimitrij
5da7a582bf Fix indentation and formatting in Build_mR-NB.yml
try to fix
2025-08-28 18:07:27 +01:00
Dimitrij
229c46a0c1 temporary disable Platform variable 2025-08-28 17:17:15 +01:00
Dimitrij
78d347889b Merge pull request #2762 from mRemoteNG/renovate/awssdk.ec2-4.x
Update dependency AWSSDK.EC2 to 4.0.33
2025-08-27 10:01:59 +01:00
renovate[bot]
244741ba15 Update dependency AWSSDK.EC2 to 4.0.33 2025-08-26 22:45:48 +00:00
Dimitrij
015fa601a3 Merge pull request #2761 from mRemoteNG/renovate/awssdk.ec2-4.x
Update dependency AWSSDK.EC2 to 4.0.32
2025-08-26 08:48:27 +01:00
renovate[bot]
1bd9e44ecb Update dependency AWSSDK.EC2 to 4.0.32 2025-08-25 22:33:55 +00:00
Dimitrij
dc7cfdb762 Merge pull request #2759 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-139.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to v139
2025-08-25 00:09:27 +01:00
Dimitrij
36afbae5af Merge pull request #2760 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-139.x
Update dependency chromiumembeddedframework.runtime.win-x64 to v139
2025-08-25 00:09:05 +01:00
Dimitrij
89d56a10f0 Merge pull request #2758 from mRemoteNG/renovate/log4net-3.x
Update dependency log4net to 3.2.0
2025-08-25 00:08:51 +01:00
Dimitrij
8dcc6031e6 Merge pull request #2757 from mRemoteNG/renovate/awssdk.core-4.x
Update dependency AWSSDK.Core to 4.0.0.25
2025-08-25 00:08:37 +01:00
renovate[bot]
b524a5424a Update dependency chromiumembeddedframework.runtime.win-x64 to v139 2025-08-23 08:58:53 +00:00
renovate[bot]
f06ad99658 Update dependency chromiumembeddedframework.runtime.win-arm64 to v139 2025-08-23 08:58:48 +00:00
renovate[bot]
f4ad61a41b Update dependency log4net to 3.2.0 2025-08-22 23:46:53 +00:00
renovate[bot]
3c948aca96 Update dependency AWSSDK.Core to 4.0.0.25 2025-08-22 23:46:49 +00:00
Dimitrij
57ee792198 Merge pull request #2755 from mRemoteNG/renovate/awssdk.ec2-4.x
Update dependency AWSSDK.EC2 to 4.0.31.1
2025-08-22 00:51:18 +01:00
renovate[bot]
6d84364cec Update dependency AWSSDK.EC2 to 4.0.31.1 2025-08-21 23:51:10 +00:00
Dimitrij
d74fc16cfd Merge pull request #2754 from mRemoteNG/renovate/awssdk.core-4.x
Update dependency AWSSDK.Core to 4.0.0.24
2025-08-22 00:50:48 +01:00
renovate[bot]
56d72cb30b Update dependency AWSSDK.Core to 4.0.0.24 2025-08-21 23:40:29 +00:00
Dimitrij
2f6f03ce8f Merge pull request #2740 from mRemoteNG/renovate/nunit.console-3.x
Update dependency NUnit.Console to 3.20.1
2025-08-21 13:10:46 +01:00
renovate[bot]
b437ff3dcc Update dependency NUnit.Console to 3.20.1 2025-08-21 12:09:49 +00:00
Dimitrij
93d17c2c35 Merge pull request #2741 from mRemoteNG/renovate/nunit.consolerunner-3.x
Update dependency NUnit.ConsoleRunner to 3.20.1
2025-08-21 13:09:37 +01:00
Dimitrij
b70ea04f02 Merge pull request #2749 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-138.x
Update dependency chromiumembeddedframework.runtime.win-x64 to v138
2025-08-21 13:09:23 +01:00
Dimitrij
89cde8b518 Merge pull request #2748 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-138.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to v138
2025-08-21 13:09:07 +01:00
Dimitrij
8d78623730 Merge pull request #2747 from mRemoteNG/renovate/actions-checkout-5.x
Update actions/checkout action to v5
2025-08-21 13:08:54 +01:00
Dimitrij
4a5b05f669 Merge pull request #2751 from mRemoteNG/renovate/softprops-action-gh-release-2.x
Update softprops/action-gh-release action to v2
2025-08-21 13:08:40 +01:00
Dimitrij
c4f2b7ed2e Merge pull request #2745 from mRemoteNG/renovate/nunit3testadapter-5.x
Update dependency NUnit3TestAdapter to 5.1.0
2025-08-21 13:08:21 +01:00
renovate[bot]
e296c77b14 Update dependency chromiumembeddedframework.runtime.win-x64 to v138 2025-08-21 12:06:56 +00:00
Dimitrij
56611c6e41 Merge pull request #2752 from mRemoteNG/renovate/microsoft.extensions.dependencymodel-9.x
Update dependency Microsoft.Extensions.DependencyModel to 9.0.8
2025-08-21 13:06:56 +01:00
renovate[bot]
1e216b8cb3 Update dependency chromiumembeddedframework.runtime.win-arm64 to v138 2025-08-21 12:06:52 +00:00
renovate[bot]
302700ac80 Update dependency Microsoft.Extensions.DependencyModel to 9.0.8 2025-08-21 12:06:45 +00:00
Dimitrij
cc5d943a86 Merge pull request #2753 from mRemoteNG/renovate/microsoft.net.test.sdk-17.x
Update dependency Microsoft.NET.Test.Sdk to 17.14.1
2025-08-21 13:06:32 +01:00
Dimitrij
7942f93649 Merge pull request #2744 from mRemoteNG/renovate/nunit-4.x
Update dependency NUnit to 4.4.0
2025-08-21 13:05:51 +01:00
Dimitrij
270c6dd64b Merge pull request #2750 from mRemoteNG/renovate/gherkin-34.x
Update dependency Gherkin to v34
2025-08-21 13:05:33 +01:00
Dimitrij
9f1633bc63 Merge pull request #2746 from mRemoteNG/renovate/actions-cache-4.x
Update actions/cache action to v4
2025-08-21 13:05:20 +01:00
Dimitrij
8953ec0e1f Merge pull request #2738 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-x64-92.x
Update dependency chromiumembeddedframework.runtime.win-x64 to 92.0.26
2025-08-21 13:05:03 +01:00
Dimitrij
8f5dd3bc93 Merge pull request #2737 from mRemoteNG/renovate/chromiumembeddedframework.runtime.win-arm64-92.x
Update dependency chromiumembeddedframework.runtime.win-arm64 to 92.0.26
2025-08-21 13:04:45 +01:00
renovate[bot]
97ee6e6ee0 Update dependency Microsoft.NET.Test.Sdk to 17.14.1 2025-08-21 12:04:12 +00:00
renovate[bot]
ae626294f3 Update softprops/action-gh-release action to v2 2025-08-21 11:39:30 +00:00
renovate[bot]
842a45aa17 Update dependency Gherkin to v34 2025-08-21 11:39:26 +00:00
renovate[bot]
686936e7b2 Update actions/checkout action to v5 2025-08-21 11:39:15 +00:00
renovate[bot]
8ac8ad6ed9 Update actions/cache action to v4 2025-08-21 11:39:12 +00:00
renovate[bot]
e7eda49676 Update dependency NUnit3TestAdapter to 5.1.0 2025-08-21 11:39:09 +00:00
renovate[bot]
faae8c7a77 Update dependency NUnit to 4.4.0 2025-08-21 11:39:05 +00:00
renovate[bot]
5cb67a6e09 Update dependency NUnit.ConsoleRunner to 3.20.1 2025-08-21 11:38:52 +00:00
renovate[bot]
06747dc38d Update dependency chromiumembeddedframework.runtime.win-x64 to 92.0.26 2025-08-21 11:38:41 +00:00
renovate[bot]
c3813fd87b Update dependency chromiumembeddedframework.runtime.win-arm64 to 92.0.26 2025-08-21 11:38:34 +00:00
Dimitrij
901584a2e4 upd 2025-08-21 01:21:42 +01:00
Dimitrij
f9e33c7fca fix 2025-08-21 00:49:09 +01:00
Dimitrij
ea36ca37f0 Merge pull request #2736 from asherbiny/v1.78.2-dev
Change Default RDP Version to v10
2025-08-21 00:18:39 +01:00
Dimitrij
2ea06f3096 add include 2025-08-21 00:16:13 +01:00
Dimitrij
dc208973c8 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-21 00:03:44 +01:00
Dimitrij
18ddb1001b one more fix 2025-08-21 00:03:37 +01:00
Dimitrij
567bc4a112 Update Build_mR-NB.yml
fix step 1
2025-08-20 23:29:46 +01:00
Dimitrij
c5dbf5a412 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-20 23:21:00 +01:00
Dimitrij
c084e66db5 fix path attribute (finger cross) 2025-08-20 23:20:53 +01:00
Ahmed ElSherbiny
bb6d35f91f Change Default RDP Version to v10
Problem I'm solving:
When importing RDP files, mRemoteNG defaults to RDPv6 (which is extremely old, and particularly does not support Gateway access tokens). Thus I would have to manually change the config to a newer RDP protocol, so that I could initiate  the connection.

It is safe to assume that the majority of Windows PCs on the internet today are running Windows 10 or above, and by keeping the default at RDP6 we are causing more unnecessary friction to those majority users.

I've changed the default to Rdp10 (released in Windows 10).
https://en.wikipedia.org/wiki/Remote_Desktop_Protocol#Version_10.0
2025-08-20 15:05:09 -07:00
Dimitrij
ac59bc2999 Update Build_mR-NB.yml
upd
2025-08-20 23:03:30 +01:00
Dimitrij
7dfb1d395d Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-20 22:59:49 +01:00
Dimitrij
46672ca976 adjustment 2025-08-20 22:59:42 +01:00
Dimitrij
94e7e23cda Update Build_mR-NB.yml
extend t4 step
2025-08-20 22:58:08 +01:00
Dimitrij
2fa0ca41d6 adjustment 2025-08-20 22:51:50 +01:00
Dimitrij
2ebe35c6d6 amendments 2025-08-20 22:42:42 +01:00
Dimitrij
354066de0b corrections 2025-08-20 22:39:22 +01:00
Dimitrij
3d3c1f8f23 fix to local 2025-08-20 22:31:09 +01:00
Dimitrij
24448d604d fix path 2025-08-20 22:25:16 +01:00
Dimitrij
7d8e530ebf add EnvDTE 2025-08-20 22:22:29 +01:00
Dimitrij
5db88040cc lib update 2025-08-20 22:06:21 +01:00
Dimitrij
d9de6e78d7 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-20 21:54:55 +01:00
Dimitrij
da136bfebd update .tt template to include platform type 2025-08-20 21:54:47 +01:00
Dimitrij
6657063441 Update Build_mR-NB.yml
upd
2025-08-19 22:38:42 +01:00
Dimitrij
47e6d4d711 test 2025-08-19 22:32:07 +01:00
Dimitrij
32c7bd2627 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-19 22:12:06 +01:00
Dimitrij
3422d064ac change to set platform type 2025-08-19 22:11:58 +01:00
Dimitrij
0b01d40a85 Update Build_mR-NB.yml
override platform depending on build platform
2025-08-19 22:11:20 +01:00
Dimitrij
7f79dc6098 upd 2025-08-19 19:22:46 +01:00
Dimitrij
ac7590f23c Merge pull request #2734 from Mugundanmcw/fix_x64
fix native build for Windows-x64
2025-08-19 19:20:07 +01:00
Mugu~~
998bd3a1a9 fix native build for windows-x64 2025-08-19 23:43:53 +05:30
Dimitrij
0f62f1d72c update to signed version 2025-08-19 00:28:14 +01:00
Dimitrij
cb1b1a5cac lib updates 2025-08-18 08:29:03 +01:00
Dimitrij
63ccdd0a23 Merge pull request #2728 from Mugundanmcw/win_arm64
Add support for building mRemoteNG on Windows ARM64
2025-08-18 08:25:40 +01:00
Dimitrij
ead809cc90 Update mRemoteNG/mRemoteNG.csproj
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-18 08:23:54 +01:00
Dimitrij
dfd4851bf1 Update ObjectListView/ObjectListView.NetCore.csproj
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-18 08:23:44 +01:00
Mugu~~
e50f11697f Add support for building mRemoteNG on Windows ARM64 2025-08-17 20:23:35 +05:30
Dimitrij
4800ad53dc Create post_2_Reddit.yml
bump
2025-08-15 13:08:32 +01:00
Dimitrij
9349c3f055 Lib update 2025-08-15 12:19:35 +01:00
Dimitrij
d7a82ae911 Update Build_mR-NB.yml
fix
2025-08-15 11:06:28 +01:00
Dimitrij
b3354fb033 Update Build_mR-NB.yml
fix
2025-08-15 10:51:18 +01:00
Dimitrij
9b56b11c9b Update Build_mR-NB.yml
upd
2025-08-15 10:41:58 +01:00
Dimitrij
15247c3637 Update Build_mR-NB.yml
update actions
2025-08-14 22:37:37 +01:00
Dimitrij
4311d3b057 Update Build_mR-NB.yml
update action
2025-08-14 22:26:37 +01:00
Dimitrij
076db0637f Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-14 22:04:38 +01:00
Dimitrij
8a7108910d Update Change log 2025-08-14 22:04:30 +01:00
Dimitrij
be12600094 Update Build_mR-NB.yml
upd
2025-08-14 21:48:17 +01:00
Dimitrij
988305100d Update Build_mR-NB.yml
Update Action
2025-08-14 21:38:17 +01:00
Dimitrij
16ae28ee62 Update Build_mR-NB.yml
upd
2025-08-14 21:16:09 +01:00
Dimitrij
30aab57bc9 Update Build_mR-NB.yml
fix
2025-08-14 21:04:34 +01:00
Dimitrij
a573914668 Update Build_mR-NB.yml
test
2025-08-14 20:50:12 +01:00
Dimitrij
83771cc2e6 Update Build_mR-NB.yml
text
2025-08-14 20:28:09 +01:00
Dimitrij
d8eaba75d2 Update Build_mR-NB.yml
test
2025-08-14 13:06:34 +01:00
Dimitrij
96f917a1ab Update Build_mR-NB.yml
fix
2025-08-14 12:47:43 +01:00
Dimitrij
44d81a6bdf Update Build_mR-NB.yml
test
2025-08-14 12:33:12 +01:00
Dimitrij
1b0e8440ae Update Build_mR-NB.yml
test
2025-08-14 12:22:48 +01:00
Dimitrij
e236dbe661 Update Build_mR-NB.yml
test
2025-08-14 12:14:45 +01:00
Dimitrij
2ba7d09c21 Update Build_mR-NB.yml
test
2025-08-14 12:09:44 +01:00
Dimitrij
2b937689bd Update Build_mR-NB.yml
fix
2025-08-14 12:01:51 +01:00
Dimitrij
eeb7eb7ad2 Update Build_mR-NB.yml
test
2025-08-14 11:43:13 +01:00
Dimitrij
c8e29211eb Update Build_mR-NB.yml
test
2025-08-14 11:35:03 +01:00
Dimitrij
57cce7ec22 Update Build_mR-NB.yml
test
2025-08-14 11:23:18 +01:00
Dimitrij
78af721250 Update Build_mR-NB.yml
tst
2025-08-14 11:09:40 +01:00
Dimitrij
cba6c2dacc Update Build_mR-NB.yml
test
2025-08-14 11:08:56 +01:00
Dimitrij
b4b12cdbdc Update Build_mR-NB.yml
fix
2025-08-14 03:20:48 +01:00
Dimitrij
e7c86c95fe Update Build_mR-NB.yml
fix
2025-08-14 03:17:03 +01:00
Dimitrij
f28d96e91a Update Build_mR-NB.yml
fix
2025-08-14 03:09:46 +01:00
Dimitrij
b25217dd38 Update Build_mR-NB.yml
fix token
2025-08-14 02:53:55 +01:00
Dimitrij
f60da8665b Update Build_mR-NB.yml
add token
2025-08-14 02:47:39 +01:00
Dimitrij
3d8daff050 Update Build_mR-NB.yml
fix
2025-08-14 02:43:14 +01:00
Dimitrij
c41f3c21c1 Update Build_mR-NB.yml
fix
2025-08-14 02:29:19 +01:00
Dimitrij
8e7897bf76 Update Build_mR-NB.yml
fix
2025-08-14 02:17:48 +01:00
Dimitrij
050bf75fdd Update Build_mR-NB.yml
fix
2025-08-14 02:13:49 +01:00
Dimitrij
1bbfcd0a7c Update Build_mR-NB.yml
fix
2025-08-14 01:51:43 +01:00
Dimitrij
30106d0006 Update Build_mR-NB.yml
fix
2025-08-14 01:46:26 +01:00
Dimitrij
16974068d7 Update Build_mR-NB.yml
fix
2025-08-14 01:41:53 +01:00
Dimitrij
08d0f67062 Update Build_mR-NB.yml
fix
2025-08-14 01:23:26 +01:00
Dimitrij
2edcb5863c Update Build_mR-NB.yml
fix
2025-08-14 01:19:57 +01:00
Dimitrij
44b9e49a54 Update Build_mR-NB.yml
fix
2025-08-14 01:13:33 +01:00
Dimitrij
0175903f51 Update Build_mR-NB.yml
fix date
2025-08-14 00:52:28 +01:00
Dimitrij
0ef282f89c Update Build_mR-NB.yml
fix
2025-08-14 00:51:48 +01:00
Dimitrij
b4eec7d44c Update Build_mR-NB.yml
fix and upd
2025-08-14 00:39:41 +01:00
Dimitrij
2e040a39db Update Build_mR-NB.yml
upd
2025-08-14 00:30:37 +01:00
Dimitrij
7e0ee705ff Update Build_mR-NB.yml
upd
2025-08-14 00:28:37 +01:00
Dimitrij
361005e242 Update Build_mR-NB.yml
fix
2025-08-14 00:17:37 +01:00
Dimitrij
2ea26f7319 Update Build_mR-NB.yml
fix
2025-08-14 00:04:56 +01:00
Dimitrij
44c4ca232f Update Build_mR-NB.yml
fix 11
2025-08-13 23:57:16 +01:00
Dimitrij
f7bb45288e Update Build_mR-NB.yml
fix10
2025-08-13 23:50:46 +01:00
Dimitrij
c99aa41744 Update Build_mR-NB.yml
fix 9
2025-08-13 23:43:09 +01:00
Dimitrij
4eb1cc939c Update Build_mR-NB.yml
remove raw
2025-08-13 23:32:33 +01:00
Dimitrij
d4c51f18f5 Update Build_mR-NB.yml
fix8
2025-08-13 22:14:35 +01:00
Dimitrij
af89c8bba7 Update Build_mR-NB.yml
fix 6
2025-08-13 22:12:02 +01:00
Dimitrij
2e951ef0db Update Build_mR-NB.yml
fix5
2025-08-13 22:06:33 +01:00
Dimitrij
80b82366c4 Update Build_mR-NB.yml
fix4
2025-08-13 22:00:23 +01:00
Dimitrij
3d75eae9c0 Update Build_mR-NB.yml
fix3
2025-08-13 21:52:19 +01:00
Dimitrij
0bd8d9c4ca Update Build_mR-NB.yml
fix2
2025-08-13 19:55:06 +01:00
Dimitrij
b3c1132a25 Update Build_mR-NB.yml
fix
2025-08-13 19:07:42 +01:00
Dimitrij
bddcb16e8a Update Build_mR-NB.yml
fix folder path
2025-08-13 18:57:49 +01:00
Dimitrij
3cb2ba6fa3 Update Build_mR-NB.yml
correct path
2025-08-13 18:47:50 +01:00
Dimitrij
205c8914ed Update Build_mR-NB.yml
upd
2025-08-13 18:38:50 +01:00
Dimitrij
76e0b67599 Update Build_mR-NB.yml
removed !!!
2025-08-13 18:26:51 +01:00
Dimitrij
2c617b230a Update and rename Build mR-NB.yml to Build_mR-NB.yml
update a name
2025-08-13 18:23:26 +01:00
Dimitrij
72d3268d39 lib update 2025-08-13 18:19:40 +01:00
Dimitrij
a093a77610 Merge pull request #2723 from asherbiny/v1.78.2-dev
Read keyboardhook, gatewayaccesstoken and gatewaycredentialssource from RDP File
2025-08-12 10:03:24 +01:00
asherbiny
a9c6443c18 Merge branch 'v1.78.2-dev' into v1.78.2-dev 2025-08-08 11:45:29 -05:00
Ahmed ElSherbiny
757932ed4a Add comment for duplicate cases
Cases 3 & 4 both require the user to manually enter Gateway credentials. Comment added for code readability.
2025-08-08 09:43:03 -07:00
Dimitrij
55aad85bdd Update Build mR-NB.yml
debug
2025-08-08 03:24:14 +01:00
Dimitrij
952d87f858 Update Build mR-NB.yml
add debug
2025-08-08 03:11:46 +01:00
Dimitrij
81fbe68e3b Update Build mR-NB.yml
fix
2025-08-08 02:58:11 +01:00
Dimitrij
c82cd15f24 Update Build mR-NB.yml
fix
2025-08-08 02:56:06 +01:00
Dimitrij
9991f7015f Update Build mR-NB.yml
fix
2025-08-08 02:53:39 +01:00
Dimitrij
e94fac0459 Update Build mR-NB.yml
fix permission
2025-08-08 02:52:00 +01:00
Dimitrij
816833c9f3 Update Build mR-NB.yml
fix 403
2025-08-08 02:51:17 +01:00
Dimitrij
a202d72cd6 Update Build mR-NB.yml
release fix
2025-08-08 02:44:53 +01:00
Dimitrij
0558b0621a Update Build mR-NB.yml
fix
2025-08-08 02:31:05 +01:00
Dimitrij
6e12b398d4 Update Build mR-NB.yml
fix
2025-08-08 02:24:21 +01:00
Dimitrij
cce9aa5e97 Update Build mR-NB.yml
fix
2025-08-08 02:19:47 +01:00
Dimitrij
6020122297 Update Build mR-NB.yml
another fix
2025-08-08 02:13:00 +01:00
Dimitrij
bed11116fe Update Build mR-NB.yml
zip name
2025-08-08 02:01:23 +01:00
Dimitrij
66cf93ffdd Update Build mR-NB.yml
upd
2025-08-08 01:45:09 +01:00
Dimitrij
8f1ca7dee2 Update Build mR-NB.yml
upd
2025-08-08 01:40:01 +01:00
Dimitrij
b24eac52ae Update Build mR-NB.yml
upd
2025-08-08 01:31:12 +01:00
Dimitrij
5aaa3a00b4 upd 2025-08-08 01:22:03 +01:00
Dimitrij
0d737228b0 upd tt 2025-08-08 01:18:15 +01:00
Dimitrij
f57c862c3c Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-08 01:15:40 +01:00
Dimitrij
ba476533ed upd template 2025-08-08 01:15:33 +01:00
Dimitrij
28b39688ec Update Build mR-NB.yml
fix
2025-08-08 01:10:31 +01:00
Dimitrij
fd8b1a8807 Update Build mR-NB.yml
fix prj name
2025-08-08 01:07:37 +01:00
Dimitrij
bff44b5d74 Update Build mR-NB.yml
upd
2025-08-08 01:06:02 +01:00
Dimitrij
a9ee32d020 Update and rename mR-NB.yml to Build mR-NB.yml
upd env
2025-08-08 01:03:26 +01:00
Dimitrij
4fd1864eef Update mR-NB.yml
replace texttransform wiht dotnet-t4
2025-08-08 01:01:14 +01:00
Dimitrij
3775279659 upd prj 2025-08-08 00:55:21 +01:00
Dimitrij
5bba633ab1 Merge branch 'v1.78.2-dev' of https://github.com/mRemoteNG/mRemoteNG into v1.78.2-dev 2025-08-08 00:54:27 +01:00
Dimitrij
900cc0afe3 lib update 2025-08-08 00:54:19 +01:00
Dimitrij
29fa64825e Update mR-NB.yml
add TextTransform
2025-08-08 00:13:21 +01:00
Dimitrij
1c59404299 Update mR-NB.yml
fix
2025-08-07 23:59:25 +01:00
Dimitrij
563613be6b Update mR-NB.yml
upd to new build structure
2025-08-07 23:52:46 +01:00
Dimitrij
5ae2296400 Update mR-NB.yml
upd to latest VS
2025-08-07 23:31:44 +01:00
Dimitrij
9534ceccd9 Update and rename build-x86_64.yml to mR-NB.yml
update to latest and switch to new branch
2025-08-07 23:30:51 +01:00
asherbiny
878845941d Merge branch 'v1.78.2-dev' into v1.78.2-dev 2025-08-06 16:29:34 -05:00
Ahmed ElSherbiny
a5be2bb5b5 Read keyboardhook, gatewayaccesstoken and gatewaycredentialssource from RDP File
With this commit mRemoteNG, upon importing an RDP file, will read and apply those fields to the connection being imported.

Tested by verifying that the properties are reflected correctly in the UI (Config panel) and influence the behavior of the connection as expected.
2025-08-06 14:11:10 -07:00
Dimitrij
19c954f972 lib update 2025-08-05 15:33:16 +01:00
Dimitrij
576f9db387 lib upgrade 2025-07-29 22:33:30 +01:00
Dimitrij
28ff02f8cb Merge pull request #2715 from jcefoli/FixObjectListViewSerializerWarnings
Disable WinForms analyzers and suppress WFO1000 build errors for ObjectListView
2025-07-02 09:51:52 +01:00
Joe Cefoli
d4a590d292 Disable WinForms analyzers and suppress WFO1000 build errors 2025-07-01 15:01:44 -04:00
Dimitrij
25f928fc8a Merge pull request #2712 from caspChristian/imp2321
VNCEvent_Disconnected send the ProtocolBase based object reference
2025-06-26 13:31:53 +01:00
Christian Iwata Nilsson
5dd3d927d6 VNCEvent_Disconnected send the ProtocolBase based object reference
Fixes the exception mostly mentioned in #2321, but not the actual connection issues
2025-06-26 09:08:07 +02:00
Dimitrij
77950632f8 lib update 2025-06-23 14:08:48 +01:00
Dimitrij
e85cee752d few more 2025-06-11 23:38:36 +01:00
Dimitrij
5c48f13a27 fix warnings about null-able 2025-06-11 23:34:35 +01:00
Dimitrij
18b283db0a Lib updates 2025-06-11 20:14:52 +01:00
Dimitrij
ca7888a537 Lib update 2025-06-04 23:55:33 +01:00
Dimitrij
246e90acd1 lib update 2025-05-29 18:49:41 +01:00
Dimitrij
e58e33974a cosmetic changes 2025-05-29 18:49:20 +01:00
Dimitrij
5cb07d003c UI changes for DB Setup 2025-05-29 18:48:10 +01:00
Dimitrij
3ecedc8fcf Lib updates 2025-05-13 19:34:57 +01:00
Dimitrij
a88ed5d3a9 UI Changes related SQL server 2022 configuration
(partially done)
2025-04-10 01:03:56 +01:00
Dimitrij
37fead2076 Lib updates
(temporary removed test projects from solution)
2025-04-10 01:01:53 +01:00
Dimitrij
2770c761b2 fix for current version and released version comparison
small fixes in Language
amazon lib update
2025-04-02 13:19:10 +01:00
Dimitrij
4b28eb6758 patch to remove secure-string implementation (will need to be implemented differently)
what will temporary allow to type-in and edit passwords
2025-03-30 13:56:38 +01:00
Dimitrij
ba45b44f45 lib update 2025-03-30 13:04:24 +01:00
Dimitrij
f5186cbadd lib updates 2025-03-19 12:09:39 +00:00
Dimitrij
807924c51e fix for NETSDK1137 (https://learn.microsoft.com/en-us/dotnet/core/tools/sdk-errors/netsdk1137) 2025-03-10 10:59:11 +00:00
Dimitrij
155d849201 Lib update 2025-03-10 09:55:11 +00:00
Dimitrij
e9efd2705c Lib update 2025-03-01 15:24:00 +00:00
Dimitrij
204e0d041c fix to make _mRIdentifier class-level 2025-02-18 02:45:07 +00:00
Dimitrij
227d75d956 Add new method to generate a unique identifier for the machine 2025-02-18 02:20:37 +00:00
Dimitrij
d2706c8748 Switch to use central package version management 2025-02-18 01:58:43 +00:00
Dimitrij
2518b8600f System.Data.SqlClient package is now deprecated, migrated to Microsoft.Data.SqlClient. 2025-02-17 15:23:38 +00:00
Dimitrij
9300839d59 switch to .net9 2025-02-17 14:43:51 +00:00
317 changed files with 24748 additions and 11209 deletions

242
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,242 @@
# GitHub Copilot Instructions for mRemoteNG
## Project Overview
mRemoteNG is an open-source, multi-protocol, tabbed remote connections manager for Windows. It's a fork of mRemote that allows users to view and manage all their remote connections (RDP, VNC, SSH, Telnet, HTTP/HTTPS, rlogin, Raw Socket, PowerShell remoting, AnyDesk) in a simple yet powerful interface.
## Technology Stack
- **Language**: C# with latest language version
- **Framework**: .NET 10.0 for Windows (net10.0-windows10.0.26100.0)
- **UI Framework**: Windows Forms with WPF support
- **Target Platforms**: x64 and ARM64
- **Testing Framework**: NUnit with NSubstitute for mocking
- **Build System**: MSBuild with .NET SDK-style projects
## Building the Project
### Prerequisites
- Visual Studio 2022 (version 17.14.12 or later)
- .NET 10.0 Desktop Runtime
- Windows 10/11 or Windows Server 2016+
### Build Commands
```powershell
# Restore NuGet packages
dotnet restore
# Build the solution
msbuild mRemoteNG.sln -p:Configuration=Release -p:Platform=x64
# Or for ARM64
msbuild mRemoteNG.sln -p:Configuration=Release -p:Platform=arm64
```
### Running Tests
The project uses NUnit for testing. Test projects are in `mRemoteNGTests/` directory.
```powershell
dotnet test mRemoteNGTests/mRemoteNGTests.csproj
```
## Code Organization
### Main Projects
- **mRemoteNG**: Main application project
- **mRemoteNGTests**: Unit and integration tests
- **mRemoteNGSpecs**: Specification tests
- **ObjectListView.NetCore**: Custom list view control
- **ExternalConnectors**: External protocol connector implementations
- **mRemoteNGDocumentation**: reStructuredText documentation
### Key Directories in mRemoteNG Project
- `App/`: Application startup and initialization
- `Connection/`: Connection models, protocols, and management
- `Config/`: Configuration and serialization (XML, CSV)
- `Container/`: Container/folder node implementations
- `Credential/`: Credential storage and repositories
- `Language/`: Localization resource files (.resx)
- `Security/`: Authentication, encryption, and password management
- `Tree/`: Connection tree UI and management
- `UI/`: User interface components and forms
- `Tools/`: Utility classes and helpers
## Code Style and Conventions
### EditorConfig Settings
The project uses EditorConfig (`.editorconfig` in `mRemoteNG/` directory) with these key rules:
- **Indentation**: 4 spaces (no tabs)
- **Line Endings**: CRLF (Windows-style)
- **Charset**: UTF-8 with BOM for C# files
- **New Lines**: Opening braces on new lines (Allman style)
- **Using Directives**: Sort System directives first
- **this. Qualifier**: Do not use `this.` prefix unless necessary
### Naming Conventions
- **Classes/Interfaces**: PascalCase (e.g., `ConnectionInfo`, `IInheritable`)
- **Methods**: PascalCase (e.g., `GetConnection`, `SaveToXml`)
- **Properties**: PascalCase (e.g., `ConnectionName`, `Port`)
- **Fields**: Use camelCase for private fields, consider `_` prefix for backing fields
- **Constants**: PascalCase
### Code Patterns
#### Inheritance System
mRemoteNG has a sophisticated property inheritance system for connection settings:
1. Properties can be inherited from parent containers/folders
2. Each inheritable property has a corresponding `Inherit<PropertyName>` boolean in `ConnectionInfoInheritance` class
3. Use `IInheritable` interface for objects that support inheritance
4. Example: `ConnectionFrameColor` property has `InheritConnectionFrameColor` boolean
#### Serialization
The project supports multiple serialization formats:
**XML Serialization** (`Config/Serializers/ConnectionSerializers/Xml/`):
- Node-based serializers (e.g., `XmlConnectionNodeSerializer28.cs`)
- Deserializers handle backward compatibility
- Attributes for properties and inheritance flags
- Always maintain backward compatibility - old files must still load
**CSV Serialization** (`Config/Serializers/ConnectionSerializers/Csv/`):
- Export connections to CSV format
- Include both value and inheritance columns
- Maintain column order consistency
#### Localization
All user-facing strings must be localized:
1. Add entries to `Language/Language.resx` (English base)
2. Use `Language.ResourceName` to access strings in code
3. Resource naming:
- Properties: `PropertyName` (e.g., `ConnectionFrameColor`)
- Descriptions: `PropertyDescription<PropertyName>`
- Enum values: `<EnumName><Value>` (e.g., `FrameColorRed`)
4. Provide clear, concise descriptions for PropertyGrid tooltips
### Common Patterns
#### Adding a New Connection Property
1. **Add enum** (if needed) in `Connection/` directory
2. **Add property** to `AbstractConnectionRecord.cs` or `ConnectionInfo.cs`
- Add `[Category("CategoryName")]` attribute for PropertyGrid grouping
- Add `[Description("Language.PropertyDescription<Name>")]` for tooltip
- Use appropriate TypeConverter if needed
3. **Add inheritance support** in `ConnectionInfoInheritance.cs`
4. **Update serializers**:
- XML: Update latest `XmlConnectionNodeSerializer*.cs` and `XmlConnectionsDeserializer.cs`
- CSV: Update `CsvConnectionsSerializerMremotengFormat.cs`
5. **Add localization** in `Language/Language.resx`
6. **Write tests** in `mRemoteNGTests/Connection/`
7. **Update documentation** in `mRemoteNGDocumentation/` if user-facing
#### UI Controls
- Prefer existing mRemoteNG patterns for UI controls
- Connection panels use `InterfaceControl` base class
- Custom painting: Override `OnPaint` or handle `Paint` event
- Follow Windows Forms best practices
## Testing Guidelines
### Test Structure
- Use NUnit's `[Test]` attribute for test methods
- Use `[SetUp]` and `[TearDown]` for test initialization/cleanup
- Use `[TestCase]` for parameterized tests
- Use NSubstitute for mocking: `Substitute.For<IInterface>()`
### Test Naming
- Use descriptive names: `MethodName_Scenario_ExpectedBehavior`
- Example: `ConnectionInfo_SetPassword_EncryptsValue`
### Test Organization
Mirror the main project structure in `mRemoteNGTests/`:
- `Connection/` for connection tests
- `Security/` for security tests
- `Config/` for configuration/serialization tests
## Important Notes and Pitfalls
### Backward Compatibility
- **Critical**: Never break loading of old connection files
- Always provide default values for new properties
- Test that files without new attributes still load correctly
### Security
- Sensitive data (passwords, credentials) must be encrypted
- Use existing security providers in `Security/` namespace
- Never log or expose credentials in plain text
### Performance
- Connection tree can contain thousands of nodes
- Optimize for large connection files
- Avoid unnecessary UI refreshes
- Use async/await for I/O operations
### Platform-Specific Code
- The project targets both x64 and ARM64
- Avoid platform-specific code unless absolutely necessary
- Test on both platforms when possible
### External Dependencies
- PuTTY for SSH/Telnet (bundled)
- Terminal Service Client for RDP
- Various protocol-specific libraries (see CREDITS.md)
## Documentation
### User Documentation
- Located in `mRemoteNGDocumentation/`
- Written in reStructuredText (.rst)
- Follows ReadTheDocs format
- Include screenshots and examples for new features
### Code Documentation
- Use XML documentation comments for public APIs
- Document complex algorithms and business logic
- Keep implementation notes in `IMPLEMENTATION_NOTES.md` for significant features
## Common Tasks
### Adding a Protocol
1. Create protocol implementation in `Connection/Protocol/`
2. Add protocol enum value to protocol types
3. Implement connection logic
4. Add UI controls if needed
5. Update documentation
### Adding a Theme
1. Add theme files to `Themes/` directory
2. Update theme manager
3. Add documentation in `mRemoteNGDocumentation/themes/`
### Updating Dependencies
- Dependencies are centrally managed in `Directory.Packages.props`
- Use `dotnet restore` after updating
- Test thoroughly after dependency updates
## Version and Release
- Current development version: 1.78.2-dev
- Version is set in `mRemoteNG.csproj`
- Builds are automated via GitHub Actions (`.github/workflows/`)
- Changelog maintained in `CHANGELOG.md`
## Getting Help
- Project website: https://mremoteng.org
- Documentation: https://mremoteng.readthedocs.io
- GitHub Issues: Report bugs and feature requests
- Community: Reddit r/mRemoteNG, Matrix chat
## Summary
When contributing to mRemoteNG:
1. Follow the existing code style (EditorConfig)
2. Maintain backward compatibility with old connection files
3. Localize all user-facing strings
4. Write tests for new functionality
5. Update documentation for user-facing changes
6. Test on both x64 and ARM64 if possible
7. Keep security and performance in mind

284
.github/workflows/Build_mR-NB.yml vendored Normal file
View File

@@ -0,0 +1,284 @@
name: Build_and_Release_mR-NB_MultiDeploy
on:
push:
branches:
- v1.78.2-dev
workflow_dispatch:
inputs:
release_flag:
description: 'Run NB release'
required: false
default: 'true'
permissions:
contents: write
jobs:
NB-Build-and-Release:
strategy:
matrix:
include:
# Framework-Dependent builds (requires .NET runtime on user machine)
- runner: windows-latest
platform: x64
arch: x64
deployment: framework-dependent
deploy_suffix: FD
- runner: windows-11-arm
platform: ARM64
arch: arm64
deployment: framework-dependent
deploy_suffix: FD
# Self-Contained builds (includes .NET runtime)
- runner: windows-latest
platform: x64
arch: x64
deployment: self-contained
deploy_suffix: SC
- runner: windows-11-arm
platform: ARM64
arch: arm64
deployment: self-contained
deploy_suffix: SC
runs-on: ${{ matrix.runner }}
# Only run if:
# - manual dispatch, OR
# - push event AND commit message contains "NB release"
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && contains(github.event.head_commit.message, 'NB release'))
steps:
- name: (01) Checkout Repository
uses: actions/checkout@v6
- name: (02) Install .NET 10 SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'
- name: (03) Setup MSBuild
uses: microsoft/setup-msbuild@v2
with:
vs-version: '18.0'
- name: (04) Install and run dotnet-t4 to transform T4 templates
shell: pwsh
run: |
dotnet tool install --global dotnet-t4
# Refresh PATH to include global tools
$env:PATH += ";$env:USERPROFILE\.dotnet\tools"
$ttFile = "$env:GITHUB_WORKSPACE\mRemoteNG\Properties\AssemblyInfo.tt"
# VS Enterprise 2022 assemblies
$vsPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\PublicAssemblies"
Write-Host "Transforming T4 template"
t4 $ttFile -P platformType=${{ matrix.platform }} -r:"$vsPath\EnvDTE.dll" -r:"$vsPath\Microsoft.VisualStudio.Interop.dll"
env:
PLATFORM: '${{ matrix.platform }}'
- name: (05) Cache NuGet Packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-${{ matrix.arch }}-${{ matrix.deployment }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-${{ matrix.deployment }}-nuget-
${{ runner.os }}-${{ matrix.arch }}-nuget-
- name: (06) Restore NuGet Packages
shell: pwsh
run: dotnet restore
- name: (07) Build Framework-Dependent Release
if: matrix.deployment == 'framework-dependent'
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" -p:Configuration="Release" -p:Platform=${{ matrix.platform }} /verbosity:minimal
- name: (08) Build Self-Contained Release
if: matrix.deployment == 'self-contained'
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" /t:Publish /p:Configuration="Release Self-Contained" -p:Platform=${{ matrix.platform }} /verbosity:minimal /p:SelfContained=true /p:PublishDir="bin\${{ matrix.platform }}\Release"
- name: (09) Release Information
id: version
shell: pwsh
run: |
$assemblyInfoPath = "${{ github.workspace }}\mRemoteNG\Properties\AssemblyInfo.cs"
$line = Get-Content $assemblyInfoPath | Where-Object { $_ -match 'AssemblyVersion\("(.+?)"\)' }
if ($line -match 'AssemblyVersion\("(?<ver>\d+\.\d+\.\d+)\.(?<build>\d+)"\)') {
$version = $matches['ver']
$build = $matches['build']
} else {
throw "Could not extract version and build number"
}
$date = Get-Date -Format "yyyyMMdd"
$zipName = "mRemoteNG-$date-v$version-NB-$build-${{ matrix.arch }}-${{ matrix.deploy_suffix }}.zip"
$tag = "$date-v$version-NB-($build)"
$message = git log -1 --pretty=%B
echo "message=$message" >> $env:GITHUB_OUTPUT
echo "zipname=$zipName" >> $env:GITHUB_OUTPUT
echo "version=$version" >> $env:GITHUB_OUTPUT
echo "build=$build" >> $env:GITHUB_OUTPUT
echo "tag=$tag" >> $env:GITHUB_OUTPUT
echo "deployment=${{ matrix.deployment }}" >> $env:GITHUB_OUTPUT
- name: (10) Extract Changelog Section
id: changelog
shell: pwsh
run: |
$changelogPath = "$env:GITHUB_WORKSPACE\CHANGELOG.md"
$lines = Get-Content $changelogPath
$startIndex = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^## \[') {
$startIndex = $i
break
}
}
if ($startIndex -eq -1) {
throw "No version header found in CHANGELOG.md"
}
$section = @()
for ($i = $startIndex + 1; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^## ') {
break
}
$section += $lines[$i]
}
$joined = $section -join "`n"
echo "log<<EOF" >> $env:GITHUB_OUTPUT
echo $joined >> $env:GITHUB_OUTPUT
echo "EOF" >> $env:GITHUB_OUTPUT
- name: (11) Create Zip File
shell: pwsh
run: |
$sourceDir = "$Env:GITHUB_WORKSPACE\mRemoteNG\bin\${{ matrix.platform }}\Release"
Compress-Archive -Path "$sourceDir\*" -DestinationPath ${{ steps.version.outputs.zipname }}
echo "File: ${{ steps.version.outputs.zipname }}"
# Show file size
$fileSize = (Get-Item ${{ steps.version.outputs.zipname }}).Length / 1MB
echo "Size: $([math]::Round($fileSize, 2)) MB"
- name: (10) Upload artifacts for combination
uses: actions/upload-artifact@v6
with:
name: release-${{ matrix.arch }}-${{ matrix.deploy_suffix }}
path: ${{ steps.version.outputs.zipname }}
retention-days: 1
Create-Combined-Release:
needs: NB-Build-and-Release
runs-on: windows-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v6
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
- name: Extract version info
id: version
shell: pwsh
run: |
$assemblyInfoPath = "${{ github.workspace }}\mRemoteNG\Properties\AssemblyInfo.cs"
$line = Get-Content $assemblyInfoPath | Where-Object { $_ -match 'AssemblyVersion\("(.+?)"\)' }
if ($line -match 'AssemblyVersion\("(?<ver>\d+\.\d+\.\d+)\.(?<build>\d+)"\)') {
$version = $matches['ver']
$build = $matches['build']
} else {
throw "Could not extract version and build number"
}
$date = Get-Date -Format "yyyyMMdd"
$tag = "$date-v$version-NB-($build)"
$message = git log -1 --pretty=%B
echo "version=$version" >> $env:GITHUB_OUTPUT
echo "build=$build" >> $env:GITHUB_OUTPUT
echo "tag=$tag" >> $env:GITHUB_OUTPUT
echo "message=$message" >> $env:GITHUB_OUTPUT
- name: Extract Changelog
id: changelog
shell: pwsh
run: |
$changelogPath = "$env:GITHUB_WORKSPACE\CHANGELOG.md"
$lines = Get-Content $changelogPath
$startIndex = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^## \[') {
$startIndex = $i
break
}
}
if ($startIndex -eq -1) {
throw "No version header found in CHANGELOG.md"
}
$section = @()
for ($i = $startIndex + 1; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^## ') {
break
}
$section += $lines[$i]
}
$joined = $section -join "`n"
echo "log<<EOF" >> $env:GITHUB_OUTPUT
echo $joined >> $env:GITHUB_OUTPUT
echo "EOF" >> $env:GITHUB_OUTPUT
- name: Collect all release files
shell: pwsh
run: |
Get-ChildItem -Path artifacts -Recurse -Filter "*.zip" | ForEach-Object {
Copy-Item $_.FullName -Destination .
echo "Found: $($_.Name)"
}
- name: Create combined release
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.tag }}
name: "mRemoteNG ${{ steps.version.outputs.version }} NB ${{ steps.version.outputs.build }}"
files: '*.zip'
body: |
## mRemoteNG ${{ steps.version.outputs.version }} NB Build ${{ steps.version.outputs.build }}
### 📦 Available Downloads
**Framework-Dependent (FD)** - Requires .NET 10 Runtime installed:
- Smaller download size (~15-25 MB)
- Requires .NET 10 Desktop Runtime on user machine
- Files: `*-FD.zip`
**Self-Contained (SC)** - Portable, no installation required:
- Larger download size (~80-150 MB)
- Includes .NET 10 runtime - no installation needed
- Files: `*-SC.zip`
Both versions are available for **x64** and **ARM64** architectures.
---
### 📝 Changes in this Release
${{ steps.changelog.outputs.log }}
### 💬 Last Commit Message
${{ steps.version.outputs.message }}
draft: false
prerelease: true

126
.github/workflows/add_PR_2_chlog.yml vendored Normal file
View File

@@ -0,0 +1,126 @@
name: Update Changelog After Renovate PR Merge
on:
# 1) Auto on pushes to your repos default branch (merge commits included)
push:
branches:
- v1.78.2-dev
# 2) Manual trigger
workflow_dispatch:
inputs:
dryRun:
description: 'Run without committing changes'
required: false
default: 'true'
jobs:
update-changelog:
runs-on: ubuntu-latest
# Only proceed if…
# - manual dispatch
# - OR a push to default branch
if: |
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for Renovate dependency update
id: check-renovate
shell: bash
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "isRenovate=true" >> $GITHUB_OUTPUT
exit 0
fi
msg="$(git log -1 --pretty=%B)"
if echo "$msg" | grep -q 'chore(deps): update dependency'; then
echo "isRenovate=true" >> $GITHUB_OUTPUT
else
echo "isRenovate=false" >> $GITHUB_OUTPUT
fi
- name: Abort if not a Renovate PR
if: steps.check-renovate.outputs.isRenovate == 'false'
run: |
echo " Last commit is not a Renovate dependency update—skipping."
- name: Parse Renovate PR info
if: steps.check-renovate.outputs.isRenovate == 'true'
id: extract
shell: pwsh
run: |
# 1) Determine dryRun
$dryRun = '${{ github.event.inputs.dryRun }}'
if (-not $dryRun) { $dryRun = 'false' }
Write-Host "🔍 dryRun = $dryRun"
# 2) Read full commit message
$fullMsg = git log -1 --pretty=%B
Write-Host "📝 Commit message:"; Write-Host $fullMsg
# 3) Extract PR number
if ($fullMsg -match 'Merge pull request #(\d+)') {
$prNumber = $matches[1]
} else {
throw "❌ Could not locate PR number in merge commit"
}
# 4) Extract dependency name & version
if ($fullMsg -match 'chore\(deps\): update dependency ([\w\.\-]+) to ([\d\.]+)') {
$depName = $matches[1]
$depVersion = $matches[2]
} else {
throw "❌ Could not parse dependency name/version"
}
# 5) Export outputs
echo "pr=$prNumber" >> $env:GITHUB_OUTPUT
echo "depName=$depName" >> $env:GITHUB_OUTPUT
echo "depVersion=$depVersion" >> $env:GITHUB_OUTPUT
echo "dryRun=$dryRun" >> $env:GITHUB_OUTPUT
- name: Update CHANGELOG.md
if: steps.check-renovate.outputs.isRenovate == 'true'
shell: pwsh
run: |
$path = "$env:GITHUB_WORKSPACE/CHANGELOG.md"
if (-not (Test-Path $path)) { throw "❌ CHANGELOG.md not found" }
$lines = Get-Content $path
$pr = '${{ steps.extract.outputs.pr }}'
$dep = '${{ steps.extract.outputs.depName }}'
$ver = '${{ steps.extract.outputs.depVersion }}'
$entry = "- #$pr: update dependency $dep to $ver"
# Find latest version header: ## [x.y.z]
$vIndex = $lines.FindIndex({ $_ -match '^## \[\d+\.\d+\.\d+\]' })
if ($vIndex -lt 0) { throw "❌ No version header found" }
# Locate or create "### Dependency update"
$depIndex = -1
for ($i = $vIndex + 1; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^### Dependency update') { $depIndex = $i; break }
if ($lines[$i] -match '^## ') { break }
}
if ($depIndex -eq -1) {
$lines.Insert($vIndex + 1, '### Dependency update')
$depIndex = $vIndex + 1
}
# Insert the changelog entry
$lines.Insert($depIndex + 1, $entry)
Set-Content -Path $path -Value $lines
Write-Host "✅ Inserted in CHANGELOG.md:"; Write-Host " $entry"
- name: Commit & push
if: steps.check-renovate.outputs.isRenovate == 'true' && steps.extract.outputs.dryRun != 'true'
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add CHANGELOG.md
git commit -m "docs: update changelog for #${{ steps.extract.outputs.pr }}"
git push

View File

@@ -1,130 +0,0 @@
name: Build x86_64
on:
push:
branches:
- v1.77.3-dev
jobs:
Build-Debug-MSI:
runs-on: windows-2022
steps:
- name: 01. Copy repository
uses: actions/checkout@v4
- name: 02. Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.3.1 # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
with:
vs-version: '17.12.4'
- name: 03. Restore nuget packages for solution
shell: pwsh
run: |
dotnet restore
- name: 04. Compile mRemoteNG
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" -p:Configuration="Debug Installer" -p:Platform=x64 /verbosity:normal
- name: 05. Publish MSI as Artifact
uses: actions/upload-artifact@v4
with:
name: debug-msi-x86_64
path: ${{ github.workspace }}\mRemoteNGInstaller\Installer\bin\x64\Debug\en-US\
if-no-files-found: error
Build-Debug-Portable:
runs-on: windows-2022
steps:
- name: 01. Copy repository
uses: actions/checkout@v4
- name: 02. Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.3.1 # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
with:
vs-version: '17.8.3'
- name: 03. Restore nuget packages for solution
shell: pwsh
run: |
dotnet restore
- name: 04. Compile mRemoteNG
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" -p:Configuration="Debug Portable" -p:Platform=x64 /verbosity:normal
- name: 05. Publish Portable Binary as Artifact
uses: actions/upload-artifact@v4
with:
name: debug-portable-x86_64
path: ${{ github.workspace }}\mRemoteNG\bin\x64\Debug Portable\
if-no-files-found: error
Build-Release:
runs-on: windows-2022
steps:
- name: 01. Copy repository
uses: actions/checkout@v4
- name: 02. Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.3.1 # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
with:
vs-version: '17.12.4'
- name: 03. Restore nuget packages for solution
shell: pwsh
run: |
dotnet restore
- name: 04. Compile mRemoteNG
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" -p:Configuration="Release Installer and Portable" -p:Platform=x64 /verbosity:normal
- name: 05. Publish MSI Binary as Artifact
uses: actions/upload-artifact@v4
with:
name: release-msi-x86_64
path: ${{ github.workspace }}\mRemoteNGInstaller\Installer\bin\x64\Release\en-US\
if-no-files-found: error
- name: 06. Publish Portable Binary as Artifact
uses: actions/upload-artifact@v4
with:
name: release-portable-x86_64
path: ${{ github.workspace }}\mRemoteNG\bin\x64\Release
if-no-files-found: error
Create-Release:
needs: [Build-Debug-MSI, Build-Debug-Portable, Build-Release]
runs-on: ubuntu-22.04
steps:
- name: 01. Copy repository
uses: actions/checkout@v4
- name: 02. Download Artifacts
uses: actions/download-artifact@v4
- name: 03. Create compressed archives # Needs to be done because "actions/download-artifact@v4" is extracting the zipped Artifacts
shell: bash
run: |
zip -r debug-msi-x86_64.zip debug-msi-x86_64/
zip -r debug-portable-x86_64.zip debug-portable-x86_64/
zip -r release-msi-x86_64.zip release-msi-x86_64/
zip -r release-portable-x86_64.zip release-portable-x86_64/
- name: 04. Create Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "v1.77.3-dev-${GITHUB_RUN_NUMBER}" \
--title "v1.77.3-dev-${GITHUB_RUN_NUMBER}" \
--prerelease \
--generate-notes \
$GITHUB_WORKSPACE/debug-msi-x86_64.zip \
$GITHUB_WORKSPACE/debug-portable-x86_64.zip \
$GITHUB_WORKSPACE/release-msi-x86_64.zip \
$GITHUB_WORKSPACE/release-portable-x86_64.zip

49
.github/workflows/post_2_Reddit.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Post to Reddit via PowerShell
on:
workflow_dispatch:
jobs:
post:
runs-on: windows-latest
steps:
- name: Authenticate and post to Reddit
shell: pwsh
env:
CLIENT_ID: ${{ secrets.REDDIT_CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.REDDIT_CLIENT_SECRET }}
USERNAME: ${{ secrets.REDDIT_USERNAME }}
PASSWORD: ${{ secrets.REDDIT_PASSWORD }}
SUBREDDIT: ${{ secrets.REDDIT_SUBREDDIT }}
run: |
# Step 1: Get access token
$authHeaders = @{
Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$env:CLIENT_ID:$env:CLIENT_SECRET"))
"User-Agent" = "github-to-reddit-pwsh/0.1"
}
$authBody = @{
grant_type = "password"
username = $env:USERNAME
password = $env:PASSWORD
}
$authResponse = Invoke-RestMethod -Uri "https://www.reddit.com/api/v1/access_token" -Method Post -Headers $authHeaders -Body $authBody
$token = $authResponse.access_token
# Step 2: Post to subreddit
$postHeaders = @{
Authorization = "bearer $token"
"User-Agent" = "github-to-reddit-pwsh/0.1"
}
$postBody = @{
sr = $env:SUBREDDIT
title = "Hello from GitHub Actions (PowerShell)"
kind = "self"
text = "This post was made using PowerShell in GitHub Actions."
}
$postResponse = Invoke-RestMethod -Uri "https://oauth.reddit.com/api/submit" -Method Post -Headers $postHeaders -Body $postBody
Write-Host "Posted: $($postResponse.json.url)"

View File

@@ -2,6 +2,45 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.78.2]
### Fixed
- #2939: fixed SQL injection vulnerabilities via parameterized queries
- #2940: fixed for Possible command injection via Process.Start
- #2932: fixed HTTP/HTTPS protocol to support multiple concurrent connections
- #2855: fixed missing Username field for HTTP and HTTPS protocols
- #2852: fixed XML External Entity (XXE) vulnerability in XML deserialization
- #2851: fixed path traversal vulnerability in file operations
- #2850: fixed password dialog appearing behind splash screen on startup
- #2842: fixed element placement in options window
- #2734: fixed native build for Windows-x64
- #2715: fixed Disable WinForms analyzers and suppress WFO1000 build errors for ObjectListView
- #2712: fixed VNCEvent_Disconnected send the ProtocolBase based object reference
- #2668: fixed ssh quickconnect exception
- #2611: fixed correct registry path
- #2496: fixed use pwfile instead of cleartext password for putty connections
### Added
- #2931: added vault openbao connector
- #2900: added "Report a Bug" menu item to Help menu and update bug report URL to GitHub issues
- #2865: added configurable connection tab colors to distinguish between different environments
- #2864: added color property to connections and folders with inheritance support
- #2863: added ARD (Apple Remote Desktop) protocol support for macOS connections
- #2728: added support for building mRemoteNG on Windows ARM64
- #2723: added read keyboardhook, gatewayaccesstoken and gatewaycredentialssource from RDP File
- #2690: added தமிழ் (ta) Translation update
- #2643: added registry Settings: enhancements and new settings implementation
- #2591: add Clickstudios Passwordstate API connector
- #2212: added 1Password integration
### Updated
- #2883: Improve 1Password logging
- #2854: Refactor settings dialog to be opened in dockable panel (for consistency)
- #2597: Remember the opened connection file on relaunch
- #2502: Updated Polish translation
### Dependency update
- #3bd2fe8: puttyng updated to x64 version (and signed)
## [1.77.3.1784]
### Fixed
- #2362: Fix use of sql database

View File

@@ -1,7 +1,9 @@
# Contributors
## Current mRemoteNG dev team
[Dimitrij Gorodeckij](https://github.com/Kvarkas)
## Past Contributors
[David Sparer](http://github.com/sparerd)
[Sean Kaim](http://github.com/kmscode)
[Faryan Rezagholi](http://github.com/farosch)
@@ -28,8 +30,6 @@ Tony Lambert
[MitchellBot](http://github.com/MitchellBot)
[Filippo Ferrazini](http://github.com/Filippo125)
## Past Contributors
Felix Deimel - mRemote original developer
Riley McArdle - mRemoteNG original developer

167
DEPLOYMENT_OPTIONS.md Normal file
View File

@@ -0,0 +1,167 @@
# mRemoteNG Deployment Options
This document explains the two deployment options for mRemoteNG and how to build each version.
## Deployment Types
### 1. Framework-Dependent (FD)
**File suffix: `-FD.zip`**
- **Size**: ~15-25 MB
- **Requirements**: User must have .NET 10 Desktop Runtime installed
- **Startup**: Application checks for .NET runtime and prompts user to download if missing
- **Use case**: Standard release for users comfortable installing prerequisites
### 2. Self-Contained (SC)
**File suffix: `-SC.zip`**
- **Size**: ~80-150 MB
- **Requirements**: None - includes .NET 10 runtime
- **Startup**: No runtime checks performed (runtime is bundled)
- **Use case**: Portable version for users who want zero installation/configuration
## Building Locally
### Framework-Dependent Build
```powershell
# x64
msbuild mRemoteNG.sln -p:Configuration=Release -p:Platform=x64
# ARM64
msbuild mRemoteNG.sln -p:Configuration=Release -p:Platform=ARM64
```
### Self-Contained Build
```powershell
# x64
dotnet publish mRemoteNG\mRemoteNG.csproj `
--configuration Release `
--runtime win-x64 `
--self-contained true `
-p:Platform=x64 `
-p:PublishSingleFile=false `
-p:PublishReadyToRun=true `
-p:DefineConstants="SELF_CONTAINED"
# ARM64
dotnet publish mRemoteNG\mRemoteNG.csproj `
--configuration Release `
--runtime win-arm64 `
--self-contained true `
-p:Platform=ARM64 `
-p:PublishSingleFile=false `
-p:PublishReadyToRun=true `
-p:DefineConstants="SELF_CONTAINED"
```
## GitHub Actions Workflow
The new workflow file `Build_and_Release_mR-NB-MultiDeploy.yml` automatically builds all four variants:
1. **x64 Framework-Dependent** - `mRemoteNG-YYYYMMDD-vX.X.X-NB-XXXX-x64-FD.zip`
2. **x64 Self-Contained** - `mRemoteNG-YYYYMMDD-vX.X.X-NB-XXXX-x64-SC.zip`
3. **ARM64 Framework-Dependent** - `mRemoteNG-YYYYMMDD-vX.X.X-NB-XXXX-arm64-FD.zip`
4. **ARM64 Self-Contained** - `mRemoteNG-YYYYMMDD-vX.X.X-NB-XXXX-arm64-SC.zip`
### Workflow Triggers
The workflow runs when:
- You push to `v1.78.2-dev` branch with commit message containing "NB release"
- You manually trigger via workflow_dispatch
### Release Output
All four zip files are uploaded to a single GitHub Release with clear descriptions:
- Framework-Dependent versions are marked as requiring .NET 10 Runtime
- Self-Contained versions are marked as portable/no installation needed
## Code Changes
### ProgramRoot.cs
The `MainAsync` method now uses conditional compilation:
```csharp
#if !SELF_CONTAINED
// Runtime check code only included in Framework-Dependent builds
// Checks for .NET Runtime and Visual C++ Redistributable
#endif
```
When building with `-p:DefineConstants="SELF_CONTAINED"`, the runtime checks are completely excluded from the compiled binary.
## Recommendations
### For Users
**Choose Framework-Dependent (FD) if:**
- You don't mind installing .NET 10 Desktop Runtime once
- You want smaller download size
- You're using multiple .NET applications (runtime is shared)
**Choose Self-Contained (SC) if:**
- You want zero installation/setup
- You need portable deployment (USB drive, restricted environments)
- You don't want to deal with prerequisites
### For Distribution
Consider offering both options:
- Make Framework-Dependent the **default/recommended** option (smaller, faster updates)
- Offer Self-Contained as **portable alternative** for special use cases
## Technical Details
### Compilation Symbols
- Framework-Dependent builds: No special symbols
- Self-Contained builds: `SELF_CONTAINED` symbol defined
### Runtime Identifiers
- x64: `win-x64`
- ARM64: `win-arm64`
### Publish Options
Self-contained builds use these optimizations:
- `PublishReadyToRun=true` - AOT compilation for faster startup
- `IncludeNativeLibrariesForSelfExtract=true` - Bundle native dependencies
- `PublishSingleFile=false` - Keep files separate for better compatibility with mRemoteNG's plugin system
## File Size Comparison
Typical build sizes:
| Version | Framework-Dependent | Self-Contained |
|---------|---------------------|----------------|
| x64 | ~18 MB | ~95 MB |
| ARM64 | ~18 MB | ~95 MB |
*Note: Self-contained includes entire .NET 10 runtime (~80 MB overhead)*
## Testing
### Framework-Dependent Build
1. Uninstall .NET 10 Runtime (if installed)
2. Run mRemoteNG.exe
3. Should prompt to download .NET 10 Runtime
4. Install runtime and verify app launches
### Self-Contained Build
1. Uninstall .NET 10 Runtime (if installed)
2. Run mRemoteNG.exe
3. Should launch immediately without runtime check
4. Verify full functionality
## Migration from Old Workflow
The original workflow `Build_and_Release_mR-NB.yml` is preserved. To migrate:
1. Rename or remove old workflow: `Build_and_Release_mR-NB.yml`
2. Rename new workflow: `Build_and_Release_mR-NB-MultiDeploy.yml``Build_and_Release_mR-NB.yml`
3. Commit and push with "NB release" in message

105
Directory.Packages.props Normal file
View File

@@ -0,0 +1,105 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<NoWarn>$(NoWarn);NU1507;NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AWSSDK.Core" Version="4.0.3.14" />
<PackageVersion Include="AWSSDK.EC2" Version="4.0.76" />
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
<PackageVersion Include="Castle.Core" Version="5.2.1" />
<PackageVersion Include="ConsoleControl" Version="1.3.0" />
<PackageVersion Include="ConsoleControlAPI" Version="1.3.0" />
<PackageVersion Include="coverlet.collector" Version="8.0.0" />
<PackageVersion Include="Cucumber.Messages" Version="32.0.1" />
<PackageVersion Include="DockPanelSuite" Version="3.1.1" />
<PackageVersion Include="DockPanelSuite.ThemeVS2015" Version="3.1.1" />
<PackageVersion Include="envdte" Version="17.14.40260" />
<PackageVersion Include="Gherkin" Version="38.0.0" />
<PackageVersion Include="Google.Protobuf" Version="3.33.5" />
<PackageVersion Include="LiteDB" Version="5.0.21" />
<PackageVersion Include="log4net" Version="3.2.0" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.4" />
<PackageVersion Include="Microsoft.Data.SqlClient.SNI" Version="6.0.2" />
<PackageVersion Include="Microsoft.Data.SqlClient.SNI.runtime" Version="6.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="10.0.3" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.NETCore.Platforms" Version="7.0.4" />
<PackageVersion Include="Microsoft.NETCore.Targets" Version="5.0.0" />
<PackageVersion Include="Microsoft.VisualStudio.TextTemplating.VSHost" Version="17.14.40265" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3800.47" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageVersion Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.5" />
<PackageVersion Include="MySql.Data" Version="9.6.0" />
<PackageVersion Include="NETStandard.Library" Version="2.0.3" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Newtonsoft.Json.Schema" Version="4.0.1" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NUnit" Version="4.5.0" />
<PackageVersion Include="NUnit.Console" Version="3.22.0" />
<PackageVersion Include="NUnit.ConsoleRunner" Version="3.22.0" />
<PackageVersion Include="NUnit.Extension.TeamCityEventListener" Version="1.0.10" />
<PackageVersion Include="NUnit.Runners" Version="3.12.0" />
<PackageVersion Include="NUnit3TestAdapter" Version="6.1.0" />
<PackageVersion Include="OpenCover" Version="4.7.1221" />
<PackageVersion Include="Renci.SshNet.Async" Version="1.4.0" />
<PackageVersion Include="ReportGenerator" Version="5.5.1" />
<PackageVersion Include="runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.native.System" Version="4.3.1" />
<PackageVersion Include="runtime.native.System.IO.Compression" Version="4.3.2" />
<PackageVersion Include="runtime.native.System.Net.Http" Version="4.3.1" />
<PackageVersion Include="runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl" Version="4.3.3" />
<PackageVersion Include="SSH.NET" Version="2025.1.0" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.3" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.3" />
<PackageVersion Include="System.Console" Version="4.3.1" />
<PackageVersion Include="System.Data.Common" Version="4.3.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="10.0.3" />
<PackageVersion Include="System.Drawing.Common" Version="10.0.3" />
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.3" />
<PackageVersion Include="System.DirectoryServices" Version="10.0.3" />
<PackageVersion Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageVersion Include="System.IO.Pipelines" Version="10.0.3" />
<PackageVersion Include="System.Formats.Asn1" Version="10.0.3" />
<PackageVersion Include="System.Management" Version="10.0.3" />
<PackageVersion Include="System.Memory" Version="4.6.3" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Net.Primitives" Version="4.3.1" />
<PackageVersion Include="System.Net.Sockets" Version="4.3.0" />
<PackageVersion Include="System.Reflection.Emit" Version="4.7.0" />
<PackageVersion Include="System.Reflection.Emit.ILGeneration" Version="4.7.0" />
<PackageVersion Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageVersion Include="System.Reflection.Metadata" Version="10.0.3" />
<PackageVersion Include="System.Reflection.TypeExtensions" Version="4.7.0" />
<PackageVersion Include="System.Resources.ResourceManager" Version="4.3.0" />
<PackageVersion Include="System.Runtime" Version="4.3.1" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
<PackageVersion Include="System.Runtime.Extensions" Version="4.3.1" />
<PackageVersion Include="System.Security.AccessControl" Version="6.0.1" />
<PackageVersion Include="System.Security.Cryptography.Algorithms" Version="4.3.1" />
<PackageVersion Include="System.Security.Cryptography.Cng" Version="5.0.0" />
<PackageVersion Include="System.Security.Cryptography.OpenSsl" Version="5.0.0" />
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="10.0.3" />
<PackageVersion Include="System.Security.Cryptography.X509Certificates" Version="4.3.2" />
<PackageVersion Include="System.Security.Permissions" Version="10.0.3" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.3" />
<PackageVersion Include="System.Text.Json" Version="10.0.3" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="System.ValueTuple" Version="4.6.1" />
<PackageVersion Include="System.Windows.Extensions" Version="10.0.3" />
<PackageVersion Include="System.Xml.ReaderWriter" Version="4.3.1" />
<PackageVersion Include="VaultSharp" Version="1.17.5.1" />
<PackageVersion Include="VncSharpCore" Version="1.2.1" />
<PackageVersion Include="ZstdSharp.Port" Version="0.8.7" />
</ItemGroup>
</Project>

View File

@@ -257,15 +257,9 @@ public class PasswordstateInterface
return ""+textWriter.ToString();
}
private class PasswordFinder : IPasswordFinder
private class PasswordFinder(string password) : IPasswordFinder
{
private string password;
public PasswordFinder(string password)
{
this.password = password;
}
private string password = password;
public char[] GetPassword()
{

View File

@@ -58,10 +58,7 @@ namespace SecretServerAuthentication.DSS
/// <param name="refresh_token">The refresh token. Required when refreshing a token.</param>
/// <returns>Successful retrieval of an access token</returns>
/// <exception cref="ApiException">A server side error occurred.</exception>
public System.Threading.Tasks.Task<TokenResponse> AuthorizeAsync(Grant_type grant_type, string username, string password, string refresh_token, string OTP)
{
return AuthorizeAsync(grant_type, username, password, refresh_token, System.Threading.CancellationToken.None, OTP);
}
public System.Threading.Tasks.Task<TokenResponse> AuthorizeAsync(Grant_type grant_type, string username, string password, string refresh_token, string OTP) => AuthorizeAsync(grant_type, username, password, refresh_token, System.Threading.CancellationToken.None, OTP);
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <summary>Retrieve or Refresh Access Token</summary>
@@ -355,10 +352,7 @@ namespace SecretServerAuthentication.DSS
Headers = headers;
}
public override string ToString()
{
return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
}
public override string ToString() => string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.14.8.0 (NJsonSchema v10.5.2.0 (Newtonsoft.Json v11.0.0.0))")]

View File

@@ -223,15 +223,9 @@ public class SecretServerInterface
return ""+textWriter.ToString();
}
private class PasswordFinder : IPasswordFinder
private class PasswordFinder(string password) : IPasswordFinder
{
private string password;
public PasswordFinder(string password)
{
this.password = password;
}
private string password = password;
public char[] GetPassword()
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<UseWindowsForms>True</UseWindowsForms>
<Platforms>x64</Platforms>
<Configurations>Debug;Release;Debug Portable;Release Portable;Deploy to github</Configurations>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
<Platforms>x64;arm64</Platforms>
<Configurations>Debug;Release;Debug Portable;Release Self-Contained;Deploy to github</Configurations>
<SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Portable|x64'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Self-Contained|x64'">
<Optimize>True</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Self-Contained|arm64'">
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.Core" Version="3.7.402.1" />
<PackageReference Include="AWSSDK.EC2" Version="3.7.430.2" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="AWSSDK.Core" />
<PackageReference Include="AWSSDK.EC2" />
<PackageReference Include="BouncyCastle.Cryptography" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="VaultSharp" />
</ItemGroup>
<ItemGroup>
<Compile Update="AWS\AWSConnectionForm.cs" />
<Compile Update="CPS\CPSConnectionForm.cs" />
<Compile Update="DSS\SSConnectionForm.cs" />
<Compile Update="VO\VaultOpenbaoConnectionForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,131 @@
using System.Diagnostics;
using System.Net;
using System.Text.Json;
using System.Web;
namespace ExternalConnectors.OP;
public class OnePasswordCliException(string message, string arguments) : Exception(message)
{
public string Arguments { get; set; } = arguments;
}
public class OnePasswordCli
{
private const string OnePasswordCliExecutable = "op.exe";
// Username / password purpose metadata is used on Login category item fields
private const string UserNamePurpose = "USERNAME";
private const string PasswordPurpose = "PASSWORD";
// Server category items (and perhaps others) do have a built-in username/password field but don't have the `purpose` set
// and because it's a built-in field this can't be set afterwards.
// We use the label for as fallback because that can be user-modified to fit this convention in all cases.
private const string UserNameLabel = "username";
private const string PasswordLabel = "password";
private const string StringType = "STRING";
private const string SshKeyType = "SSHKEY";
private const string DomainLabel = "domain";
private record VaultUrl(string Label, string Href);
private record VaultField(string Id, string Label, string Type, string Purpose, string Value);
private record VaultItem(VaultUrl[]? Urls, VaultField[]? Fields);
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
public static void ReadPassword(string input, out string username, out string password, out string domain, out string privateKey)
{
var inputUrl = new Uri(input);
var vault = WebUtility.UrlDecode(inputUrl.Host);
var queryParams = HttpUtility.ParseQueryString(inputUrl.Query);
var account = queryParams["account"];
var item = WebUtility.UrlDecode(inputUrl.AbsolutePath.TrimStart('/'));
ItemGet(item, vault, account, out username, out password, out domain, out privateKey);
}
private static void ItemGet(string item, string? vault, string? account, out string username, out string password, out string domain, out string privateKey)
{
var args = new List<string> { "item", "get", item };
if (!string.IsNullOrEmpty(account))
{
args.Add("--account");
args.Add(account);
}
if (!string.IsNullOrEmpty(vault))
{
args.Add("--vault");
args.Add(vault);
}
args.Add("--format");
args.Add("json");
string commandLine = OnePasswordCliExecutable + " " + string.Join(' ', args);
var exitCode = RunCommand(OnePasswordCliExecutable, args, out var output, out var error);
if (exitCode != 0)
{
username = string.Empty;
password = string.Empty;
privateKey = string.Empty;
domain = string.Empty;
throw new OnePasswordCliException($"Error running op item get: {error}",
commandLine);
}
var items = JsonSerializer.Deserialize<VaultItem>(output, JsonSerializerOptions) ??
throw new OnePasswordCliException("1Password returned null",
commandLine);
username = FindField(items, UserNamePurpose, UserNameLabel);
password = FindField(items, PasswordPurpose, PasswordLabel);
privateKey = items.Fields?.FirstOrDefault(x => x.Type == SshKeyType)?.Value ?? string.Empty;
domain = items.Fields?.FirstOrDefault(x => x.Type == StringType && x.Label == DomainLabel)?.Value ?? string.Empty;
if(string.IsNullOrEmpty(password) && string.IsNullOrEmpty(privateKey))
{
throw new OnePasswordCliException("No secret found in 1Password. At least fields with labels username/password or a SshKey are expected.", commandLine);
}
}
private static string FindField(VaultItem items, string purpose, string fallbackLabel)
{
return items.Fields?.FirstOrDefault(x => x.Purpose == purpose)?.Value ??
items.Fields?.FirstOrDefault(x => x.Type == StringType && string.Equals(x.Id, fallbackLabel, StringComparison.InvariantCultureIgnoreCase))?.Value ??
items.Fields?.FirstOrDefault(x => x.Type == StringType && string.Equals(x.Label, fallbackLabel, StringComparison.InvariantCultureIgnoreCase))?.Value ??
string.Empty;
}
private static int RunCommand(string command, IReadOnlyCollection<string> arguments, out string output,
out string error)
{
var processStartInfo = new ProcessStartInfo
{
FileName = command,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
foreach (var argument in arguments)
{
processStartInfo.ArgumentList.Add(argument);
}
using var process = new Process();
process.StartInfo = processStartInfo;
process.Start();
output = process.StandardOutput.ReadToEnd();
error = process.StandardError.ReadToEnd();
process.WaitForExit();
return process.ExitCode;
}
}

View File

@@ -0,0 +1,105 @@
using Microsoft.Win32;
using System.Net;
using System.Net.Sockets;
using VaultSharp;
using VaultSharp.V1.AuthMethods;
using VaultSharp.V1.AuthMethods.Token;
namespace ExternalConnectors.VO {
public class VaultOpenbaoException(string message, string? arguments = null) : Exception(message) {
public string Arguments { get; set; } = arguments ?? string.Empty;
}
public static class VaultOpenbao {
private static readonly RegistryKey baseKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\mRemoteVaultOpenbao");
private static string token = "";
private static VaultClient GetClient() {
string url = (string)baseKey.GetValue("URL", "");
using VaultOpenbaoConnectionForm voForm = new();
voForm.tbUrl.Text = url;
voForm.tbToken.Text = token;
_ = voForm.ShowDialog();
if (voForm.DialogResult != DialogResult.OK)
throw new VaultOpenbaoException($"No credential provided");
url = voForm.tbUrl.Text;
if (!string.IsNullOrEmpty(voForm.tbToken.Text)) // override token if provided
token = voForm.tbToken.Text;
IAuthMethodInfo authMethod = new TokenAuthMethodInfo(token);
var vaultClientSettings = new VaultClientSettings(url, authMethod);
VaultClient client = new(vaultClientSettings);
var sysInfo = client.V1.System.GetInitStatusAsync().Result;
if (!sysInfo) {
MessageBox.Show("Test connection failed", "Vault Openbao", MessageBoxButtons.OK, MessageBoxIcon.Error);
throw new VaultOpenbaoException("Url not working");
}
baseKey.SetValue("URL", url);
return client;
}
private static void TestMountType(VaultClient vaultClient, string mount, int VaultOpenbaoSecretEngine) {
switch (vaultClient.V1.System.GetSecretBackendAsync(mount).Result.Data.Type.Type) {
case "kv" when VaultOpenbaoSecretEngine != 0:
throw new VaultOpenbaoException($"Backend of type kv does not match expected type {VaultOpenbaoSecretEngine}");
case "ldap" when VaultOpenbaoSecretEngine != 1 && VaultOpenbaoSecretEngine != 2:
throw new VaultOpenbaoException($"Backend of type ldap does not match expected type {VaultOpenbaoSecretEngine}");
case "ssh" when VaultOpenbaoSecretEngine != 3:
throw new VaultOpenbaoException($"Backend of type ssh does not match expected type {VaultOpenbaoSecretEngine}");
}
}
public static void ReadOtpSSH(string mount, string role, string? username, string address, out string password) {
VaultClient vaultClient = GetClient();
TestMountType(vaultClient, mount, 3);
if (!IPAddress.TryParse(address, out _)) {
try {
var addrs = Dns.GetHostAddressesAsync(address).Result;
if (addrs == null || addrs.Length == 0) {
throw new VaultOpenbaoException($"Could not resolve address '{address}'");
}
// Prefer IPv4, otherwise take first available
var selected = addrs.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork) ?? addrs[0];
address = selected.ToString();
} catch (Exception ex) {
throw new VaultOpenbaoException($"Failed to resolve address '{address}'", ex.Message);
}
}
var otp = vaultClient.V1.Secrets.SSH.GetCredentialsAsync(role, address, username, mount).Result;
password = otp.Data.Key;
}
public static void ReadPasswordSSH(int secretEngine, string mount, string role, string username, out string password) {
VaultClient vaultClient = GetClient();
TestMountType(vaultClient, mount, secretEngine);
switch (secretEngine) {
case 0:
var kv = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(role, mountPoint: mount).Result;
password = kv.Data.Data[username].ToString() ?? string.Empty;
return;
default:
throw new VaultOpenbaoException($"Backend of type {secretEngine} is not supported");
}
}
public static void ReadPasswordRDP(int secretEngine, string mount, string role, ref string username, out string password) {
VaultClient vaultClient = GetClient();
TestMountType(vaultClient, mount, secretEngine);
switch (secretEngine) {
case 0:
var kv = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(role, mountPoint: mount).Result;
password = kv.Data.Data[username].ToString() ?? string.Empty;
return;
case 1:
var ldapd = vaultClient.V1.Secrets.OpenLDAP.GetDynamicCredentialsAsync(role, mount).Result;
username = ldapd.Data.Username;
password = ldapd.Data.Password;
return;
case 2:
var ldaps = vaultClient.V1.Secrets.OpenLDAP.GetStaticCredentialsAsync(role, mount).Result;
username = ldaps.Data.Username;
password = ldaps.Data.Password;
return;
default:
throw new VaultOpenbaoException($"Backend of type {secretEngine} is not supported");
}
}
}
}

View File

@@ -0,0 +1,185 @@
namespace ExternalConnectors.VO
{
partial class VaultOpenbaoConnectionForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
tbUrl = new TextBox();
tbToken = new TextBox();
btnOK = new Button();
btnCancel = new Button();
tableLayoutPanel1 = new TableLayoutPanel();
label1 = new Label();
label2 = new Label();
tableLayoutPanel2 = new TableLayoutPanel();
tableLayoutPanel1.SuspendLayout();
tableLayoutPanel2.SuspendLayout();
SuspendLayout();
//
// tbUrl
//
tbUrl.Dock = DockStyle.Fill;
tbUrl.Location = new Point(174, 5);
tbUrl.Margin = new Padding(5);
tbUrl.Name = "tbUrl";
tbUrl.Size = new Size(559, 27);
tbUrl.TabIndex = 0;
//
// tbToken
//
tbToken.Dock = DockStyle.Fill;
tbToken.Location = new Point(174, 57);
tbToken.Margin = new Padding(5);
tbToken.Name = "tbToken";
tbToken.Size = new Size(559, 27);
tbToken.TabIndex = 2;
tbToken.UseSystemPasswordChar = true;
tbToken.Focus();
//
// btnOK
//
btnOK.Anchor = AnchorStyles.Right;
btnOK.DialogResult = DialogResult.OK;
btnOK.Location = new Point(250, 16);
btnOK.Margin = new Padding(5);
btnOK.Name = "btnOK";
btnOK.Size = new Size(101, 35);
btnOK.TabIndex = 10;
btnOK.Text = "OK";
btnOK.UseVisualStyleBackColor = true;
//
// btnCancel
//
btnCancel.Anchor = AnchorStyles.Left;
btnCancel.DialogResult = DialogResult.Cancel;
btnCancel.Location = new Point(387, 16);
btnCancel.Margin = new Padding(5);
btnCancel.Name = "btnCancel";
btnCancel.Size = new Size(101, 35);
btnCancel.TabIndex = 11;
btnCancel.Text = "Cancel";
btnCancel.UseVisualStyleBackColor = true;
//
// tableLayoutPanel1
//
tableLayoutPanel1.ColumnCount = 2;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 22.92994F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 77.07006F));
tableLayoutPanel1.Controls.Add(label1, 0, 0);
tableLayoutPanel1.Controls.Add(label2, 0, 1);
tableLayoutPanel1.Controls.Add(tbUrl, 1, 0);
tableLayoutPanel1.Controls.Add(tbToken, 1, 1);
tableLayoutPanel1.Dock = DockStyle.Top;
tableLayoutPanel1.Location = new Point(0, 0);
tableLayoutPanel1.Margin = new Padding(5);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 3;
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 31F));
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 31F));
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 31F));
tableLayoutPanel1.Size = new Size(738, 136);
tableLayoutPanel1.TabIndex = 12;
//
// label1
//
label1.AutoSize = true;
label1.Dock = DockStyle.Fill;
label1.Location = new Point(5, 0);
label1.Margin = new Padding(5, 0, 5, 0);
label1.Name = "label1";
label1.Size = new Size(159, 52);
label1.TabIndex = 2;
label1.Text = "Server URL";
label1.TextAlign = ContentAlignment.MiddleLeft;
//
// label2
//
label2.AutoSize = true;
label2.Dock = DockStyle.Fill;
label2.Location = new Point(5, 52);
label2.Margin = new Padding(5, 0, 5, 0);
label2.Name = "label2";
label2.Size = new Size(159, 52);
label2.TabIndex = 4;
label2.Text = "Access Token";
label2.TextAlign = ContentAlignment.MiddleLeft;
//
// tableLayoutPanel2
//
tableLayoutPanel2.ColumnCount = 5;
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 106F));
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 26F));
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 106F));
tableLayoutPanel2.Controls.Add(btnOK, 1, 0);
tableLayoutPanel2.Controls.Add(btnCancel, 3, 0);
tableLayoutPanel2.Dock = DockStyle.Bottom;
tableLayoutPanel2.Location = new Point(0, 149);
tableLayoutPanel2.Margin = new Padding(5);
tableLayoutPanel2.Name = "tableLayoutPanel2";
tableLayoutPanel2.RowCount = 1;
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
tableLayoutPanel2.Size = new Size(738, 67);
tableLayoutPanel2.TabIndex = 13;
//
// VaultOpenbaoConnectionForm
//
AcceptButton = btnOK;
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(738, 216);
Controls.Add(tableLayoutPanel2);
Controls.Add(tableLayoutPanel1);
FormBorderStyle = FormBorderStyle.FixedDialog;
Margin = new Padding(5);
MaximizeBox = false;
MinimizeBox = false;
Name = "VaultOpenbaoConnectionForm";
SizeGripStyle = SizeGripStyle.Hide;
Text = "Vault/Openbao API Login Data";
Activated += VaultOpenbaoConnectionForm_Activated;
tableLayoutPanel1.ResumeLayout(false);
tableLayoutPanel1.PerformLayout();
tableLayoutPanel2.ResumeLayout(false);
ResumeLayout(false);
}
#endregion
public System.Windows.Forms.TextBox tbUrl;
public System.Windows.Forms.TextBox tbToken;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
}
}

View File

@@ -0,0 +1,13 @@
namespace ExternalConnectors.VO
{
public partial class VaultOpenbaoConnectionForm : Form {
public VaultOpenbaoConnectionForm() {
InitializeComponent();
}
private void VaultOpenbaoConnectionForm_Activated(object sender, EventArgs e) {
tbUrl.Focus();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

158
IMPLEMENTATION_NOTES.md Normal file
View File

@@ -0,0 +1,158 @@
# Connection Frame Color Feature - Implementation Summary
## Overview
This implementation adds a "Connection Frame Color" feature to mRemoteNG that allows users to visually distinguish between different connection environments (e.g., production, test, development) by displaying a colored border around connection panels.
## Feature Request Context
The feature was requested in issue to prevent accidental operations on production systems. The user cited DBeaver database management tool as an example, which uses a red frame to indicate production database connections.
## Implementation Details
### 1. Data Model (Connection/ConnectionFrameColor.cs)
Created an enum with the following values:
- **None** (default): No colored border
- **Red**: Intended for production environments
- **Yellow**: Intended for staging/UAT environments
- **Green**: Intended for test environments
- **Blue**: Intended for development environments
- **Purple**: Intended for custom/other environments
### 2. Property Addition (Connection/AbstractConnectionRecord.cs)
- Added `ConnectionFrameColor` property to the base connection record class
- Property is categorized under "Display" section in PropertyGrid
- Uses EnumTypeConverter for proper display in PropertyGrid
- Includes localized descriptions
### 3. Inheritance Support (Connection/ConnectionInfoInheritance.cs)
- Added `ConnectionFrameColor` inheritance property
- Allows folders to set a frame color that child connections can inherit
- Follows the same pattern as other inheritable properties
### 4. Serialization
#### XML Serialization (Config/Serializers/ConnectionSerializers/Xml/)
- **XmlConnectionNodeSerializer28.cs**: Serializes ConnectionFrameColor as an XML attribute
- **XmlConnectionsDeserializer.cs**: Deserializes ConnectionFrameColor from XML
- Includes inheritance attribute handling (InheritConnectionFrameColor)
- Backward compatible: old files without this attribute will default to None
#### CSV Serialization (Config/Serializers/ConnectionSerializers/Csv/)
- **CsvConnectionsSerializerMremotengFormat.cs**: Added ConnectionFrameColor to CSV export
- Includes both value and inheritance columns
- Maintains CSV column order consistency
### 5. Visual Rendering (Connection/InterfaceControl.cs)
- Added custom Paint event handler to InterfaceControl
- Draws a 4-pixel colored border around the connection panel when ConnectionFrameColor is set
- Uses specific colors:
- Red: RGB(220, 53, 69) - Bootstrap danger red
- Yellow: RGB(255, 193, 7) - Warning yellow
- Green: RGB(40, 167, 69) - Success green
- Blue: RGB(0, 123, 255) - Primary blue
- Purple: RGB(111, 66, 193) - Purple
- Border is drawn inside the control bounds to avoid clipping
### 6. Localization (Language/Language.resx)
Added language resources for:
- ConnectionFrameColor: "Connection Frame Color"
- PropertyDescriptionConnectionFrameColor: Description shown in PropertyGrid
- FrameColorNone: "None"
- FrameColorRed: "Red (Production)"
- FrameColorYellow: "Yellow (Staging/UAT)"
- FrameColorGreen: "Green (Test)"
- FrameColorBlue: "Blue (Development)"
- FrameColorPurple: "Purple (Custom)"
### 7. Documentation (mRemoteNGDocumentation/howtos/connection_frame_color.rst)
Created comprehensive documentation including:
- Overview and purpose
- Step-by-step usage instructions
- Visual examples
- Inheritance explanation
- Best practices for environment organization
- Troubleshooting guide
## Technical Design Decisions
### Why 4-pixel border?
- Wide enough to be immediately noticeable
- Not so wide as to obscure content
- Consistent with modern UI design patterns
### Why these specific colors?
- Colors chosen based on common conventions:
- Red = danger/production (universal warning color)
- Yellow = caution/staging (standard warning color)
- Green = safe/test (universal "go" color)
- Blue = development (calm, neutral)
- Purple = custom (distinct but not alarming)
- Colors use accessible, high-contrast RGB values
### Why enum instead of custom color picker?
- Simpler UI (dropdown vs color picker)
- Ensures consistency across team/organization
- Prevents confusion from too many color choices
- Follows principle of "convention over configuration"
- Can be extended in future if needed
### Why inherit from Panel?
- InterfaceControl is already a Panel (see InterfaceControl.Designer.cs)
- Panel has built-in Paint event support
- No need for additional controls or complexity
## Backward Compatibility
- Old connection files (without ConnectionFrameColor attribute) automatically default to None
- No migration needed
- Feature is completely opt-in
- Does not affect existing functionality
## Testing Recommendations
When testing this feature, verify:
1. **Property Display**: ConnectionFrameColor appears in PropertyGrid under Display section
2. **Enum Values**: All color options appear in dropdown
3. **Visual Rendering**: Border appears when color is selected and connection is active
4. **Inheritance**: Setting on folder and enabling inheritance on child works correctly
5. **Serialization**:
- Save connection with frame color set
- Close and reopen file
- Verify color is preserved
6. **CSV Export**: ConnectionFrameColor appears in exported CSV
7. **Backward Compatibility**: Open old connection files without errors
## Future Enhancements (Out of Scope)
Potential future improvements:
- Custom color picker support
- Border width customization
- Border style options (solid, dashed, etc.)
- Tab header color indicator in addition to panel border
- Global warning when connecting to production (confirmation dialog)
- Audit logging for production connections
## Files Modified
1. mRemoteNG/Connection/ConnectionFrameColor.cs (NEW)
2. mRemoteNG/Connection/AbstractConnectionRecord.cs
3. mRemoteNG/Connection/ConnectionInfo.cs
4. mRemoteNG/Connection/ConnectionInfoInheritance.cs
5. mRemoteNG/Connection/InterfaceControl.cs
6. mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs
7. mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs
8. mRemoteNG/Config/Serializers/ConnectionSerializers/Csv/CsvConnectionsSerializerMremotengFormat.cs
9. mRemoteNG/Language/Language.resx
10. mRemoteNGDocumentation/howtos/connection_frame_color.rst (NEW)
## Code Review Checklist
- [x] Property follows existing naming conventions
- [x] Enum values are localized
- [x] Inheritance support implemented
- [x] XML serialization/deserialization working
- [x] CSV serialization updated
- [x] Visual rendering implemented
- [x] Documentation created
- [x] Backward compatibility maintained
- [x] No breaking changes
- [x] Code follows existing patterns in codebase

View File

@@ -46,18 +46,14 @@ namespace BrightIdeasSoftware
/// <summary>
/// These items allow combo boxes to remember a value and its description.
/// </summary>
public class ComboBoxItem
/// <remarks>
///
/// </remarks>
/// <param name="key"></param>
/// <param name="description"></param>
public class ComboBoxItem(Object key, String description)
{
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="description"></param>
public ComboBoxItem(Object key, String description) {
this.key = key;
this.description = description;
}
private readonly String description;
private readonly String description = description;
/// <summary>
///
@@ -65,7 +61,7 @@ namespace BrightIdeasSoftware
public Object Key {
get { return key; }
}
private readonly Object key;
private readonly Object key = key;
/// <summary>
/// Returns a string that represents the current object.

View File

@@ -158,15 +158,12 @@ namespace BrightIdeasSoftware
/// This class isn't intended to be used directly, but it is left as a public
/// class just in case someone wants to subclass it.
/// </remarks>
public class FastObjectListDataSource : AbstractVirtualListDataSource
/// <remarks>
/// Create a FastObjectListDataSource
/// </remarks>
/// <param name="listView"></param>
public class FastObjectListDataSource(FastObjectListView listView) : AbstractVirtualListDataSource(listView)
{
/// <summary>
/// Create a FastObjectListDataSource
/// </summary>
/// <param name="listView"></param>
public FastObjectListDataSource(FastObjectListView listView)
: base(listView) {
}
#region IVirtualListDataSource Members

View File

@@ -185,15 +185,11 @@ namespace BrightIdeasSoftware
/// A model object must satisfy all filters to be included.
/// If there are no filters, all model objects are included
/// </summary>
public class CompositeAllFilter : CompositeFilter {
/// <summary>
/// Create a filter
/// </summary>
/// <param name="filters"></param>
public CompositeAllFilter(List<IModelFilter> filters)
: base(filters) {
}
/// <remarks>
/// Create a filter
/// </remarks>
/// <param name="filters"></param>
public class CompositeAllFilter(List<IModelFilter> filters) : CompositeFilter(filters) {
/// <summary>
/// Decide whether or not the given model should be included by the filter
@@ -215,15 +211,11 @@ namespace BrightIdeasSoftware
/// A model object must only satisfy one of the filters to be included.
/// If there are no filters, all model objects are included
/// </summary>
public class CompositeAnyFilter : CompositeFilter {
/// <summary>
/// Create a filter from the given filters
/// </summary>
/// <param name="filters"></param>
public CompositeAnyFilter(List<IModelFilter> filters)
: base(filters) {
}
/// <remarks>
/// Create a filter from the given filters
/// </remarks>
/// <param name="filters"></param>
public class CompositeAnyFilter(List<IModelFilter> filters) : CompositeFilter(filters) {
/// <summary>
/// Decide whether or not the given model should be included by the filter

View File

@@ -50,7 +50,13 @@ namespace BrightIdeasSoftware
/// <para>This is used by normal (non-virtual) ObjectListViews. Virtual lists use
/// ModelObjectComparer</para>
/// </remarks>
public class ColumnComparer : IComparer, IComparer<OLVListItem>
/// <remarks>
/// Create a ColumnComparer that will order the rows in a list view according
/// to the values in a given column
/// </remarks>
/// <param name="col">The column whose values will be compared</param>
/// <param name="order">The ordering for column values</param>
public class ColumnComparer(OLVColumn col, SortOrder order) : IComparer, IComparer<OLVListItem>
{
/// <summary>
/// Gets or sets the method that will be used to compare two strings.
@@ -63,18 +69,6 @@ namespace BrightIdeasSoftware
}
private static StringCompareDelegate stringComparer;
/// <summary>
/// Create a ColumnComparer that will order the rows in a list view according
/// to the values in a given column
/// </summary>
/// <param name="col">The column whose values will be compared</param>
/// <param name="order">The ordering for column values</param>
public ColumnComparer(OLVColumn col, SortOrder order)
{
this.column = col;
this.sortOrder = order;
}
/// <summary>
/// Create a ColumnComparer that will order the rows in a list view according
/// to the values in a given column, and by a secondary column if the primary
@@ -165,8 +159,8 @@ namespace BrightIdeasSoftware
return StringComparer(x, y);
}
private OLVColumn column;
private SortOrder sortOrder;
private OLVColumn column = col;
private SortOrder sortOrder = order;
private ColumnComparer secondComparer;
}
@@ -175,15 +169,12 @@ namespace BrightIdeasSoftware
/// This comparer sort list view groups. OLVGroups have a "SortValue" property,
/// which is used if present. Otherwise, the titles of the groups will be compared.
/// </summary>
public class OLVGroupComparer : IComparer<OLVGroup>
/// <remarks>
/// Create a group comparer
/// </remarks>
/// <param name="order">The ordering for column values</param>
public class OLVGroupComparer(SortOrder order) : IComparer<OLVGroup>
{
/// <summary>
/// Create a group comparer
/// </summary>
/// <param name="order">The ordering for column values</param>
public OLVGroupComparer(SortOrder order) {
this.sortOrder = order;
}
/// <summary>
/// Compare the two groups. OLVGroups have a "SortValue" property,
@@ -207,7 +198,7 @@ namespace BrightIdeasSoftware
return result;
}
private SortOrder sortOrder;
private SortOrder sortOrder = order;
}
/// <summary>
@@ -217,7 +208,12 @@ namespace BrightIdeasSoftware
/// <para>This is used by virtual ObjectListViews. Non-virtual lists use
/// ColumnComparer</para>
/// </remarks>
public class ModelObjectComparer : IComparer, IComparer<object>
/// <remarks>
/// Create a model object comparer
/// </remarks>
/// <param name="col"></param>
/// <param name="order"></param>
public class ModelObjectComparer(OLVColumn col, SortOrder order) : IComparer, IComparer<object>
{
/// <summary>
/// Gets or sets the method that will be used to compare two strings.
@@ -230,17 +226,6 @@ namespace BrightIdeasSoftware
}
private static StringCompareDelegate stringComparer;
/// <summary>
/// Create a model object comparer
/// </summary>
/// <param name="col"></param>
/// <param name="order"></param>
public ModelObjectComparer(OLVColumn col, SortOrder order)
{
this.column = col;
this.sortOrder = order;
}
/// <summary>
/// Create a model object comparer with a secondary sorting column
/// </summary>
@@ -318,8 +303,8 @@ namespace BrightIdeasSoftware
return StringComparer(x, y);
}
private OLVColumn column;
private SortOrder sortOrder;
private OLVColumn column = col;
private SortOrder sortOrder = order;
private ModelObjectComparer secondComparer;
#region IComparer<object> Members

View File

@@ -878,25 +878,16 @@ namespace BrightIdeasSoftware
/// <summary>
/// Let the world know that a cell edit operation is beginning or ending
/// </summary>
public class CellEditEventArgs : EventArgs
/// <remarks>
/// Create an event args
/// </remarks>
/// <param name="column"></param>
/// <param name="control"></param>
/// <param name="cellBounds"></param>
/// <param name="item"></param>
/// <param name="subItemIndex"></param>
public class CellEditEventArgs(OLVColumn column, Control control, Rectangle cellBounds, OLVListItem item, int subItemIndex) : EventArgs
{
/// <summary>
/// Create an event args
/// </summary>
/// <param name="column"></param>
/// <param name="control"></param>
/// <param name="cellBounds"></param>
/// <param name="item"></param>
/// <param name="subItemIndex"></param>
public CellEditEventArgs(OLVColumn column, Control control, Rectangle cellBounds, OLVListItem item, int subItemIndex) {
this.Control = control;
this.column = column;
this.cellBounds = cellBounds;
this.listViewItem = item;
this.rowObject = item.RowObject;
this.subItemIndex = subItemIndex;
this.value = column.GetValue(item.RowObject);
}
/// <summary>
/// Change this to true to cancel the cell editing operation.
@@ -917,7 +908,7 @@ namespace BrightIdeasSoftware
/// entered and commit that value to the model. Changing the control during the finishing
/// event has no effect.
/// </summary>
public Control Control;
public Control Control = control;
/// <summary>
/// The column of the cell that is going to be or has been edited.
@@ -925,7 +916,7 @@ namespace BrightIdeasSoftware
public OLVColumn Column {
get { return this.column; }
}
private OLVColumn column;
private OLVColumn column = column;
/// <summary>
/// The model object of the row of the cell that is going to be or has been edited.
@@ -933,7 +924,7 @@ namespace BrightIdeasSoftware
public Object RowObject {
get { return this.rowObject; }
}
private Object rowObject;
private Object rowObject = item.RowObject;
/// <summary>
/// The listview item of the cell that is going to be or has been edited.
@@ -941,7 +932,7 @@ namespace BrightIdeasSoftware
public OLVListItem ListViewItem {
get { return this.listViewItem; }
}
private OLVListItem listViewItem;
private OLVListItem listViewItem = item;
/// <summary>
/// The data value of the cell as it stands in the control.
@@ -959,7 +950,7 @@ namespace BrightIdeasSoftware
public int SubItemIndex {
get { return this.subItemIndex; }
}
private int subItemIndex;
private int subItemIndex = subItemIndex;
/// <summary>
/// The data value of the cell before the edit operation began.
@@ -967,7 +958,7 @@ namespace BrightIdeasSoftware
public Object Value {
get { return this.value; }
}
private Object value;
private Object value = column.GetValue(item.RowObject);
/// <summary>
/// The bounds of the cell that is going to be or has been edited.
@@ -975,7 +966,7 @@ namespace BrightIdeasSoftware
public Rectangle CellBounds {
get { return this.cellBounds; }
}
private Rectangle cellBounds;
private Rectangle cellBounds = cellBounds;
/// <summary>
/// Gets or sets whether the control used for editing should be auto matically disposed
@@ -1160,25 +1151,22 @@ namespace BrightIdeasSoftware
}
private SortOrder secondarySortOrder;
}
/// <summary>
/// This event is triggered when the contents of a list have changed
/// and we want the world to have a chance to filter the list.
/// </summary>
public class FilterEventArgs : EventArgs
/// <remarks>
/// Create a FilterEventArgs
/// </remarks>
/// <param name="objects"></param>
public class FilterEventArgs(IEnumerable objects) : EventArgs
{
/// <summary>
/// Create a FilterEventArgs
/// </summary>
/// <param name="objects"></param>
public FilterEventArgs(IEnumerable objects) {
this.Objects = objects;
}
/// <summary>
/// Gets or sets what objects are being filtered
/// </summary>
public IEnumerable Objects;
public IEnumerable Objects = objects;
/// <summary>
/// Gets or sets what objects survived the filtering
@@ -1267,17 +1255,13 @@ namespace BrightIdeasSoftware
/// <remarks>
/// When used with a virtual list, OldObjects will always be null.
/// </remarks>
public class ItemsChangingEventArgs : CancellableEventArgs
/// <remarks>
/// Create ItemsChangingEventArgs
/// </remarks>
/// <param name="oldObjects"></param>
/// <param name="newObjects"></param>
public class ItemsChangingEventArgs(IEnumerable oldObjects, IEnumerable newObjects) : CancellableEventArgs
{
/// <summary>
/// Create ItemsChangingEventArgs
/// </summary>
/// <param name="oldObjects"></param>
/// <param name="newObjects"></param>
public ItemsChangingEventArgs(IEnumerable oldObjects, IEnumerable newObjects) {
this.oldObjects = oldObjects;
this.NewObjects = newObjects;
}
/// <summary>
/// Gets the objects that were in the list before it change.
@@ -1286,47 +1270,40 @@ namespace BrightIdeasSoftware
public IEnumerable OldObjects {
get { return oldObjects; }
}
private IEnumerable oldObjects;
private IEnumerable oldObjects = oldObjects;
/// <summary>
/// Gets or sets the objects that will be in the list after it changes.
/// </summary>
public IEnumerable NewObjects;
public IEnumerable NewObjects = newObjects;
}
/// <summary>
/// This event is triggered by RemoveObjects before any change has been made to the list.
/// </summary>
public class ItemsRemovingEventArgs : CancellableEventArgs
/// <remarks>
/// Create an ItemsRemovingEventArgs
/// </remarks>
/// <param name="objectsToRemove"></param>
public class ItemsRemovingEventArgs(ICollection objectsToRemove) : CancellableEventArgs
{
/// <summary>
/// Create an ItemsRemovingEventArgs
/// </summary>
/// <param name="objectsToRemove"></param>
public ItemsRemovingEventArgs(ICollection objectsToRemove) {
this.ObjectsToRemove = objectsToRemove;
}
/// <summary>
/// Gets or sets the objects that will be removed
/// </summary>
public ICollection ObjectsToRemove;
public ICollection ObjectsToRemove = objectsToRemove;
}
/// <summary>
/// Triggered after the user types into a list
/// </summary>
public class AfterSearchingEventArgs : EventArgs
/// <remarks>
/// Create an AfterSearchingEventArgs
/// </remarks>
/// <param name="stringToFind"></param>
/// <param name="indexSelected"></param>
public class AfterSearchingEventArgs(string stringToFind, int indexSelected) : EventArgs
{
/// <summary>
/// Create an AfterSearchingEventArgs
/// </summary>
/// <param name="stringToFind"></param>
/// <param name="indexSelected"></param>
public AfterSearchingEventArgs(string stringToFind, int indexSelected) {
this.stringToFind = stringToFind;
this.indexSelected = indexSelected;
}
/// <summary>
/// Gets the string that was actually searched for
@@ -1334,7 +1311,7 @@ namespace BrightIdeasSoftware
public string StringToFind {
get { return this.stringToFind; }
}
private string stringToFind;
private string stringToFind = stringToFind;
/// <summary>
/// Gets or sets whether an the event handler already handled this event
@@ -1348,23 +1325,19 @@ namespace BrightIdeasSoftware
public int IndexSelected {
get { return this.indexSelected; }
}
private int indexSelected;
private int indexSelected = indexSelected;
}
/// <summary>
/// Triggered when the user types into a list
/// </summary>
public class BeforeSearchingEventArgs : CancellableEventArgs
/// <remarks>
/// Create BeforeSearchingEventArgs
/// </remarks>
/// <param name="stringToFind"></param>
/// <param name="startSearchFrom"></param>
public class BeforeSearchingEventArgs(string stringToFind, int startSearchFrom) : CancellableEventArgs
{
/// <summary>
/// Create BeforeSearchingEventArgs
/// </summary>
/// <param name="stringToFind"></param>
/// <param name="startSearchFrom"></param>
public BeforeSearchingEventArgs(string stringToFind, int startSearchFrom) {
this.StringToFind = stringToFind;
this.StartSearchFrom = startSearchFrom;
}
/// <summary>
/// Gets or sets the string that will be found by the search routine
@@ -1372,12 +1345,12 @@ namespace BrightIdeasSoftware
/// <remarks>Modifying this value does not modify the memory of what the user has typed.
/// When the user next presses a character, the search string will revert to what
/// the user has actually typed.</remarks>
public string StringToFind;
public string StringToFind = stringToFind;
/// <summary>
/// Gets or sets the index of the first row that will be considered to matching.
/// </summary>
public int StartSearchFrom;
public int StartSearchFrom = startSearchFrom;
}
/// <summary>
@@ -2035,27 +2008,20 @@ namespace BrightIdeasSoftware
return string.Format("NewHotCellHitLocation: {0}, HotCellHitLocationEx: {1}, NewHotColumnIndex: {2}, NewHotRowIndex: {3}, HotGroup: {4}", this.newHotCellHitLocation, this.hotCellHitLocationEx, this.newHotColumnIndex, this.newHotRowIndex, this.hotGroup);
}
}
/// <summary>
/// Let the world know that a checkbox on a subitem is changing
/// </summary>
public class SubItemCheckingEventArgs : CancellableEventArgs
/// <remarks>
/// Create a new event block
/// </remarks>
/// <param name="column"></param>
/// <param name="item"></param>
/// <param name="subItemIndex"></param>
/// <param name="currentValue"></param>
/// <param name="newValue"></param>
public class SubItemCheckingEventArgs(OLVColumn column, OLVListItem item, int subItemIndex, CheckState currentValue, CheckState newValue) : CancellableEventArgs
{
/// <summary>
/// Create a new event block
/// </summary>
/// <param name="column"></param>
/// <param name="item"></param>
/// <param name="subItemIndex"></param>
/// <param name="currentValue"></param>
/// <param name="newValue"></param>
public SubItemCheckingEventArgs(OLVColumn column, OLVListItem item, int subItemIndex, CheckState currentValue, CheckState newValue) {
this.column = column;
this.listViewItem = item;
this.subItemIndex = subItemIndex;
this.currentValue = currentValue;
this.newValue = newValue;
}
/// <summary>
/// The column of the cell that is having its checkbox changed.
@@ -2063,7 +2029,7 @@ namespace BrightIdeasSoftware
public OLVColumn Column {
get { return this.column; }
}
private OLVColumn column;
private OLVColumn column = column;
/// <summary>
/// The model object of the row of the cell that is having its checkbox changed.
@@ -2078,7 +2044,7 @@ namespace BrightIdeasSoftware
public OLVListItem ListViewItem {
get { return this.listViewItem; }
}
private OLVListItem listViewItem;
private OLVListItem listViewItem = item;
/// <summary>
/// The current check state of the cell.
@@ -2086,7 +2052,7 @@ namespace BrightIdeasSoftware
public CheckState CurrentValue {
get { return this.currentValue; }
}
private CheckState currentValue;
private CheckState currentValue = currentValue;
/// <summary>
/// The proposed new check state of the cell.
@@ -2095,7 +2061,7 @@ namespace BrightIdeasSoftware
get { return this.newValue; }
set { this.newValue = value; }
}
private CheckState newValue;
private CheckState newValue = newValue;
/// <summary>
/// The index of the cell that is going to be or has been edited.
@@ -2103,21 +2069,18 @@ namespace BrightIdeasSoftware
public int SubItemIndex {
get { return this.subItemIndex; }
}
private int subItemIndex;
private int subItemIndex = subItemIndex;
}
/// <summary>
/// This event argument block is used when groups are created for a list.
/// </summary>
public class CreateGroupsEventArgs : EventArgs
/// <remarks>
/// Create a CreateGroupsEventArgs
/// </remarks>
/// <param name="parms"></param>
public class CreateGroupsEventArgs(GroupingParameters parms) : EventArgs
{
/// <summary>
/// Create a CreateGroupsEventArgs
/// </summary>
/// <param name="parms"></param>
public CreateGroupsEventArgs(GroupingParameters parms) {
this.parameters = parms;
}
/// <summary>
/// Gets the settings that control the creation of groups
@@ -2125,7 +2088,7 @@ namespace BrightIdeasSoftware
public GroupingParameters Parameters {
get { return this.parameters; }
}
private GroupingParameters parameters;
private GroupingParameters parameters = parms;
/// <summary>
/// Gets or sets the groups that should be used
@@ -2151,16 +2114,12 @@ namespace BrightIdeasSoftware
/// <summary>
/// This event argument block is used when the text of a group task is clicked
/// </summary>
public class GroupTaskClickedEventArgs : EventArgs
/// <remarks>
/// Create a GroupTaskClickedEventArgs
/// </remarks>
/// <param name="group"></param>
public class GroupTaskClickedEventArgs(OLVGroup group) : EventArgs
{
/// <summary>
/// Create a GroupTaskClickedEventArgs
/// </summary>
/// <param name="group"></param>
public GroupTaskClickedEventArgs(OLVGroup group)
{
this.group = group;
}
/// <summary>
/// Gets which group was clicked
@@ -2169,7 +2128,7 @@ namespace BrightIdeasSoftware
{
get { return this.group; }
}
private readonly OLVGroup group;
private readonly OLVGroup group = group;
}
/// <summary>
@@ -2207,18 +2166,13 @@ namespace BrightIdeasSoftware
/// <summary>
/// This event argument block is used when the state of group has changed (collapsed, selected)
/// </summary>
public class GroupStateChangedEventArgs : EventArgs {
/// <summary>
/// Create a GroupStateChangedEventArgs
/// </summary>
/// <param name="group"></param>
/// <param name="oldState"> </param>
/// <param name="newState"> </param>
public GroupStateChangedEventArgs(OLVGroup group, GroupState oldState, GroupState newState) {
this.group = group;
this.oldState = oldState;
this.newState = newState;
}
/// <remarks>
/// Create a GroupStateChangedEventArgs
/// </remarks>
/// <param name="group"></param>
/// <param name="oldState"> </param>
/// <param name="newState"> </param>
public class GroupStateChangedEventArgs(OLVGroup group, GroupState oldState, GroupState newState) : EventArgs {
/// <summary>
/// Gets whether the group was collapsed by this event
@@ -2291,7 +2245,7 @@ namespace BrightIdeasSoftware
get { return this.group; }
}
private readonly OLVGroup group;
private readonly OLVGroup group = group;
/// <summary>
/// Gets the previous state of the group
@@ -2300,7 +2254,7 @@ namespace BrightIdeasSoftware
get { return this.oldState; }
}
private readonly GroupState oldState;
private readonly GroupState oldState = oldState;
/// <summary>
@@ -2310,7 +2264,7 @@ namespace BrightIdeasSoftware
get { return this.newState; }
}
private readonly GroupState newState;
private readonly GroupState newState = newState;
}
/// <summary>

View File

@@ -311,18 +311,14 @@ namespace BrightIdeasSoftware
/// <remarks>
/// Munger uses a chain of these resolve a dotted aspect name.
/// </remarks>
public class SimpleMunger
/// <remarks>
/// Create a SimpleMunger
/// </remarks>
/// <param name="aspectName"></param>
public class SimpleMunger(String aspectName)
{
#region Life and death
/// <summary>
/// Create a SimpleMunger
/// </summary>
/// <param name="aspectName"></param>
public SimpleMunger(String aspectName)
{
this.aspectName = aspectName;
}
#region Life and death
#endregion
@@ -344,7 +340,7 @@ namespace BrightIdeasSoftware
public string AspectName {
get { return aspectName; }
}
private readonly string aspectName;
private readonly string aspectName = aspectName;
#endregion
@@ -494,19 +490,14 @@ namespace BrightIdeasSoftware
/// <summary>
/// These exceptions are raised when a munger finds something it cannot process
/// </summary>
public class MungerException : ApplicationException
/// <remarks>
/// Create a MungerException
/// </remarks>
/// <param name="munger"></param>
/// <param name="target"></param>
/// <param name="ex"></param>
public class MungerException(SimpleMunger munger, object target, Exception ex) : ApplicationException("Munger failed", ex)
{
/// <summary>
/// Create a MungerException
/// </summary>
/// <param name="munger"></param>
/// <param name="target"></param>
/// <param name="ex"></param>
public MungerException(SimpleMunger munger, object target, Exception ex)
: base("Munger failed", ex) {
this.munger = munger;
this.target = target;
}
/// <summary>
/// Get the munger that raised the exception
@@ -514,7 +505,7 @@ namespace BrightIdeasSoftware
public SimpleMunger Munger {
get { return munger; }
}
private readonly SimpleMunger munger;
private readonly SimpleMunger munger = munger;
/// <summary>
/// Gets the target that threw the exception
@@ -522,7 +513,7 @@ namespace BrightIdeasSoftware
public object Target {
get { return target; }
}
private readonly object target;
private readonly object target = target;
}
/*

View File

@@ -309,12 +309,9 @@ namespace BrightIdeasSoftware
/// A default implementation of the IOwnerDataCallback interface
/// </summary>
[Guid("6FC61F50-80E8-49b4-B200-3F38D3865ABD")]
internal class OwnerDataCallbackImpl : IOwnerDataCallback
internal class OwnerDataCallbackImpl(VirtualObjectListView olv) : IOwnerDataCallback
{
public OwnerDataCallbackImpl(VirtualObjectListView olv) {
this.olv = olv;
}
VirtualObjectListView olv;
VirtualObjectListView olv = olv;
#region IOwnerDataCallback Members

View File

@@ -145,20 +145,17 @@ namespace BrightIdeasSoftware
/// <summary>
/// A do-nothing implementation of the VirtualListDataSource interface.
/// </summary>
public class AbstractVirtualListDataSource : IVirtualListDataSource, IFilterableDataSource
/// <remarks>
/// Creates an AbstractVirtualListDataSource
/// </remarks>
/// <param name="listView"></param>
public class AbstractVirtualListDataSource(VirtualObjectListView listView) : IVirtualListDataSource, IFilterableDataSource
{
/// <summary>
/// Creates an AbstractVirtualListDataSource
/// </summary>
/// <param name="listView"></param>
public AbstractVirtualListDataSource(VirtualObjectListView listView) {
this.listView = listView;
}
/// <summary>
/// The list view that this data source is giving information to.
/// </summary>
protected VirtualObjectListView listView;
protected VirtualObjectListView listView = listView;
/// <summary>
///
@@ -295,15 +292,12 @@ namespace BrightIdeasSoftware
/// <summary>
/// This class mimics the behavior of VirtualObjectListView v1.x.
/// </summary>
public class VirtualListVersion1DataSource : AbstractVirtualListDataSource
/// <remarks>
/// Creates a VirtualListVersion1DataSource
/// </remarks>
/// <param name="listView"></param>
public class VirtualListVersion1DataSource(VirtualObjectListView listView) : AbstractVirtualListDataSource(listView)
{
/// <summary>
/// Creates a VirtualListVersion1DataSource
/// </summary>
/// <param name="listView"></param>
public VirtualListVersion1DataSource(VirtualObjectListView listView)
: base(listView) {
}
#region Public properties

View File

@@ -369,14 +369,8 @@ namespace BrightIdeasSoftware.Design
/// only have to modify the returned collection of actions, but we have to implement
/// the properties and commands that the returned actions use. </para>
/// </remarks>
private class ListViewActionListAdapter : DesignerActionList
private class ListViewActionListAdapter(ObjectListViewDesigner designer, DesignerActionList wrappedList) : DesignerActionList(wrappedList.Component)
{
public ListViewActionListAdapter(ObjectListViewDesigner designer, DesignerActionList wrappedList)
: base(wrappedList.Component) {
this.designer = designer;
this.wrappedList = wrappedList;
}
public override DesignerActionItemCollection GetSortedActionItems() {
DesignerActionItemCollection items = wrappedList.GetSortedActionItems();
items.RemoveAt(2); // remove Edit Groups
@@ -425,21 +419,16 @@ namespace BrightIdeasSoftware.Design
set { SetValue(base.Component, "View", value); }
}
ObjectListViewDesigner designer;
DesignerActionList wrappedList;
ObjectListViewDesigner designer = designer;
DesignerActionList wrappedList = wrappedList;
}
#endregion
#region DesignerCommandSet
private class CDDesignerCommandSet : DesignerCommandSet
private class CDDesignerCommandSet(ComponentDesigner componentDesigner) : DesignerCommandSet
{
public CDDesignerCommandSet(ComponentDesigner componentDesigner) {
this.componentDesigner = componentDesigner;
}
public override ICollection GetCommands(string name) {
// Debug.WriteLine("CDDesignerCommandSet.GetCommands:" + name);
if (componentDesigner != null) {
@@ -453,7 +442,7 @@ namespace BrightIdeasSoftware.Design
return base.GetCommands(name);
}
private readonly ComponentDesigner componentDesigner;
private readonly ComponentDesigner componentDesigner = componentDesigner;
}
#endregion
@@ -463,15 +452,12 @@ namespace BrightIdeasSoftware.Design
/// This class works in conjunction with the OLVColumns property to allow OLVColumns
/// to be added to the ObjectListView.
/// </summary>
public class OLVColumnCollectionEditor : System.ComponentModel.Design.CollectionEditor
/// <remarks>
/// Create a OLVColumnCollectionEditor
/// </remarks>
/// <param name="t"></param>
public class OLVColumnCollectionEditor(Type t) : System.ComponentModel.Design.CollectionEditor(t)
{
/// <summary>
/// Create a OLVColumnCollectionEditor
/// </summary>
/// <param name="t"></param>
public OLVColumnCollectionEditor(Type t)
: base(t) {
}
/// <summary>
/// What type of object does this editor create?

View File

@@ -1,15 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<Deterministic>false</Deterministic>
<RootNamespace>BrightIdeasSoftware</RootNamespace>
<AssemblyName>ObjectListView</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<NoWarn>$(NoWarn);WFO1000</NoWarn>
<EnableWinFormsAnalyzers>false</EnableWinFormsAnalyzers>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)' == 'x64'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)' == 'ARM64'">
<PlatformTarget>ARM64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Content Include="CustomDictionary.xml" Link="CustomDictionary.xml" />
<Content Include="Resources\clear-filter.png" Link="Resources\clear-filter.png" />
@@ -19,7 +25,6 @@
<Content Include="Resources\sort-ascending.png" Link="Resources\sort-ascending.png" />
<Content Include="Resources\sort-descending.png" Link="Resources\sort-descending.png" />
</ItemGroup>
<ItemGroup>
<Folder Include="CellEditing\" />
<Folder Include="DragDrop\" />
@@ -30,9 +35,4 @@
<Folder Include="Resources\" />
<Folder Include="Rendering\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="9.0.2" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.0" />
</ItemGroup>
</Project>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -231,15 +231,12 @@ namespace BrightIdeasSoftware {
/// This class provides compatibility for v1 RendererDelegates
/// </summary>
[ToolboxItem(false)]
internal class Version1Renderer : AbstractRenderer {
public Version1Renderer(RenderDelegate renderDelegate) {
this.RenderDelegate = renderDelegate;
}
internal class Version1Renderer(RenderDelegate renderDelegate) : AbstractRenderer {
/// <summary>
/// The renderer delegate that this renderer wraps
/// </summary>
public RenderDelegate RenderDelegate;
public RenderDelegate RenderDelegate = renderDelegate;
#region IRenderer Members
@@ -518,7 +515,7 @@ namespace BrightIdeasSoftware {
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ImageList ImageListOrDefault {
get { return this.ImageList ?? this.ListView.SmallImageList; }
get { return this.ImageList ?? this.ListView.GetSmallImageList(); }
}
/// <summary>
@@ -809,7 +806,7 @@ namespace BrightIdeasSoftware {
/// <param name="g"></param>
/// <returns></returns>
protected virtual Size CalculatePrimaryCheckBoxSize(Graphics g) {
if (!this.ListView.CheckBoxes || !this.ColumnIsPrimary)
if (!this.ListView.GetCheckBoxes() || !this.ColumnIsPrimary)
return Size.Empty;
Size size = this.CalculateCheckBoxSize(g);
@@ -1299,7 +1296,7 @@ namespace BrightIdeasSoftware {
int width = 0;
// Did they hit a check box on the primary column?
if (this.ColumnIsPrimary && this.ListView.CheckBoxes) {
if (this.ColumnIsPrimary && this.ListView.GetCheckBoxes()) {
Size checkBoxSize = this.CalculateCheckBoxSize(g);
int checkBoxTop = this.AlignVertically(r, checkBoxSize.Height);
Rectangle r3 = new Rectangle(r.X, checkBoxTop, checkBoxSize.Width, checkBoxSize.Height);
@@ -1635,7 +1632,7 @@ namespace BrightIdeasSoftware {
/// <param name="r">Bounds of the cell</param>
protected virtual void DrawImageAndText(Graphics g, Rectangle r) {
int offset = 0;
if (this.ListView.CheckBoxes && this.ColumnIsPrimary) {
if (this.ListView.GetCheckBoxes() && this.ColumnIsPrimary) {
offset = this.DrawCheckBox(g, r) + 6;
r.X += offset;
r.Width -= offset;

View File

@@ -51,17 +51,20 @@
* If you wish to use this code in a closed source application, please contact phillip.piper@gmail.com.
*/
using BrightIdeasSoftware.Properties;
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Forms.VisualStyles;
using System.Drawing.Drawing2D;
using BrightIdeasSoftware.Properties;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace BrightIdeasSoftware
{
[SupportedOSPlatform("windows")]
/// <summary>
/// Class used to capture window messages for the header of the list view
/// control.
@@ -428,7 +431,7 @@ namespace BrightIdeasSoftware
/// Override the basic message pump
/// </summary>
/// <param name="m"></param>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
//[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
const int WM_DESTROY = 2;
@@ -489,7 +492,7 @@ namespace BrightIdeasSoftware
base.WndProc(ref m);
}
private bool HandleReflectNotify(ref Message m)
private static bool HandleReflectNotify(ref Message m)
{
NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR));
System.Diagnostics.Debug.WriteLine(String.Format("rn: {0}", nmhdr.code));

View File

@@ -40,11 +40,13 @@ using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Windows.Forms;
namespace BrightIdeasSoftware
{
[SupportedOSPlatform("windows")]
/// <summary>
/// A limited wrapper around a Windows tooltip window.
/// </summary>
@@ -643,7 +645,6 @@ namespace BrightIdeasSoftware
/// Mess with the basic message pump of the tooltip
/// </summary>
/// <param name="msg"></param>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
override protected void WndProc(ref Message msg) {
//System.Diagnostics.Trace.WriteLine(String.Format("xx {0:x}", msg.Msg));
switch (msg.Msg) {
@@ -695,5 +696,4 @@ namespace BrightIdeasSoftware
#endregion
}
}

View File

@@ -193,7 +193,7 @@ namespace BrightIdeasSoftware
// ReSharper restore DoNotCallOverridableMethodsInConstructor
// This improves hit detection even if we don't have any state image
this.SmallImageList = new ImageList();
this.SetSmallImageList(new ImageList());
// this.StateImageList.ImageSize = new Size(6, 6);
}
@@ -364,7 +364,7 @@ namespace BrightIdeasSoftware
return;
this.hierarchicalCheckboxes = value;
this.CheckBoxes = value;
this.SetCheckBoxes(value);
if (value)
this.TriStateCheckBoxes = false;
}
@@ -2180,15 +2180,12 @@ namespace BrightIdeasSoftware
/// <summary>
/// This class sorts branches according to how their respective model objects are sorted
/// </summary>
public class BranchComparer : IComparer<Branch>
/// <remarks>
/// Create a BranchComparer
/// </remarks>
/// <param name="actualComparer"></param>
public class BranchComparer(IComparer actualComparer) : IComparer<Branch>
{
/// <summary>
/// Create a BranchComparer
/// </summary>
/// <param name="actualComparer"></param>
public BranchComparer(IComparer actualComparer) {
this.actualComparer = actualComparer;
}
/// <summary>
/// Order the two branches
@@ -2200,7 +2197,7 @@ namespace BrightIdeasSoftware
return this.actualComparer.Compare(x.Model, y.Model);
}
private readonly IComparer actualComparer;
private readonly IComparer actualComparer = actualComparer;
}
}

View File

@@ -125,7 +125,7 @@ namespace BrightIdeasSoftware
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.objectListView1.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
this.objectListView1.CheckBoxes = true;
this.objectListView1.SetCheckBoxes(true);
this.objectListView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.olvColumn1});
this.objectListView1.FullRowSelect = true;

View File

@@ -233,13 +233,9 @@ namespace BrightIdeasSoftware
/// A Comparer that will sort a list of columns so that visible ones come before hidden ones,
/// and that are ordered by their display order.
/// </summary>
private class SortByDisplayOrder : IComparer<OLVColumn>
private class SortByDisplayOrder(ColumnSelectionForm form) : IComparer<OLVColumn>
{
public SortByDisplayOrder(ColumnSelectionForm form)
{
this.Form = form;
}
private ColumnSelectionForm Form;
private ColumnSelectionForm Form = form;
#region IComparer<OLVColumn> Members

View File

@@ -72,15 +72,12 @@ namespace BrightIdeasSoftware
/// }
/// </code>
/// </example>
public class TypedObjectListView<T> where T : class
/// <remarks>
/// Create a typed wrapper around the given list.
/// </remarks>
/// <param name="olv">The listview to be wrapped</param>
public class TypedObjectListView<T>(ObjectListView olv) where T : class
{
/// <summary>
/// Create a typed wrapper around the given list.
/// </summary>
/// <param name="olv">The listview to be wrapped</param>
public TypedObjectListView(ObjectListView olv) {
this.olv = olv;
}
//--------------------------------------------------------------------------------------
// Properties
@@ -115,7 +112,7 @@ namespace BrightIdeasSoftware
get { return olv; }
set { olv = value; }
}
private ObjectListView olv;
private ObjectListView olv = olv;
/// <summary>
/// Get or set the list of all model objects
@@ -325,16 +322,13 @@ namespace BrightIdeasSoftware
/// A type-safe wrapper around an OLVColumn
/// </summary>
/// <typeparam name="T"></typeparam>
public class TypedColumn<T> where T : class
/// <remarks>
/// Creates a TypedColumn
/// </remarks>
/// <param name="column"></param>
public class TypedColumn<T>(OLVColumn column) where T : class
{
/// <summary>
/// Creates a TypedColumn
/// </summary>
/// <param name="column"></param>
public TypedColumn(OLVColumn column) {
this.column = column;
}
private OLVColumn column;
private OLVColumn column = column;
/// <summary>
///

View File

@@ -77,14 +77,16 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Windows.Forms;
using MethodInvoker = System.Windows.Forms.MethodInvoker;
namespace BrightIdeasSoftware
{
[SupportedOSPlatform("windows")]
/// <summary>
/// A virtual object list view operates in virtual mode, that is, it only gets model objects for
/// a row when it is needed. This gives it the ability to handle very large numbers of rows with
@@ -99,7 +101,7 @@ namespace BrightIdeasSoftware
/// <para>
/// Although it isn't documented, .NET virtual lists cannot have checkboxes. This class codes around this limitation,
/// but you must use the functions provided by ObjectListView: CheckedObjects, CheckObject(), UncheckObject() and their friends.
/// If you use the normal check box properties (CheckedItems or CheckedIndicies), they will throw an exception, since the
/// If you use the normal check box properties (CheckedItems or CheckedIndicie), they will throw an exception, since the
/// list is in virtual mode, and .NET "knows" it can't handle checkboxes in virtual mode.
/// </para>
/// <para>Due to the limits of the underlying Windows control, virtual lists do not trigger ItemCheck/ItemChecked events.
@@ -153,7 +155,7 @@ namespace BrightIdeasSoftware
/// <para>
/// This property returns a simple collection. Changes made to the returned
/// collection do NOT affect the list. This is different to the behaviour of
/// CheckedIndicies collection.
/// CheckedIndicie collection.
/// </para>
/// <para>
/// When getting CheckedObjects, the performance of this method is O(n) where n is the number of checked objects.
@@ -175,7 +177,7 @@ namespace BrightIdeasSoftware
public override IList CheckedObjects {
get {
// If we aren't should checkboxes, then no objects can be checked
if (!this.CheckBoxes)
if (!this.GetCheckBoxes())
return new ArrayList();
// If the data source has somehow vanished, we can't do anything
@@ -199,7 +201,7 @@ namespace BrightIdeasSoftware
return objects;
}
set {
if (!this.CheckBoxes)
if (!this.GetCheckBoxes())
return;
// If a custom check state getter is install, we can't use our check state management
@@ -403,8 +405,6 @@ namespace BrightIdeasSoftware
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_virtualListSize")]
private static extern ref int GetVirtualListSizeField(ListView listView);
static private FieldInfo virtualListSizeFieldInfo;
#endregion
#region OLV accessing

67
PANEL_BINDING_FEATURE.md Normal file
View File

@@ -0,0 +1,67 @@
# Panel Binding Feature
## Overview
This feature allows users to bind the Connections and Config panels together when they are in auto-hide state (collapsed). When one panel is clicked to expand, the other panel will automatically expand as well.
## How It Works
### User Workflow
1. The user collapses both the Connections and Config panels by clicking the auto-hide pin icon (they become auto-hidden tabs on the left side)
2. The user enables the "Bind Connections and Config panels together when auto-hidden" option in Tools > Options > Tabs & Panels
3. When the user clicks on the Connections tab to expand it, the Config panel will automatically expand as well
4. Similarly, when clicking on the Config tab, the Connections panel will expand
5. Both panels stay expanded together, allowing the user to view connection settings easily
6. When the user clicks away from the panels, both collapse back to auto-hide
### Benefits
- Reduces the number of clicks needed to view and edit connection settings
- Panels work together seamlessly when in auto-hide mode
- User can still use panels independently when they are pinned (docked)
- Configurable option allows users to enable/disable as needed
## Implementation Details
### Files Modified
1. **Properties/OptionsTabsPanelsPage.settings** - Added `BindConnectionsAndConfigPanels` setting (default: false)
2. **Properties/OptionsTabsPanelsPage.Designer.cs** - Added property accessor for the new setting
3. **UI/Panels/PanelBinder.cs** - NEW - Core logic for binding panel visibility
4. **UI/Forms/OptionsPages/TabsPanelsPage.cs** - Added checkbox and load/save logic
5. **UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs** - Added UI checkbox control
6. **UI/Forms/frmMain.cs** - Initialize PanelBinder after panels are loaded
7. **Config/Settings/Registry/OptRegistryTabsPanelsPage.cs** - Added registry support for enterprise deployment
### Key Classes
#### PanelBinder
- Singleton class that manages the binding between panels
- Subscribes to VisibleChanged events on both TreeForm (Connections) and ConfigForm (Config)
- Only acts when:
- The binding setting is enabled
- Both panels are in auto-hide state
- One panel becomes visible (user clicked its tab)
- Uses a `_isProcessing` flag to prevent recursive event triggers
- Calls `Activate()` on the other panel to show it
### How to Test
1. Build and run mRemoteNG
2. Go to Tools > Options > Tabs & Panels
3. Verify the new checkbox "Bind Connections and Config panels together when auto-hidden" is present
4. Create a test connection in the Connections panel
5. Auto-hide both the Connections and Config panels (click the pin icon on each)
6. Both panels should now appear as collapsed tabs on the left side
7. Enable the binding option in Options
8. Click on the Connections tab - both Connections and Config should expand
9. Click away from the panels - both should collapse
10. Click on the Config tab - both panels should expand again
11. Disable the binding option
12. Verify panels now work independently when clicking their tabs
13. Pin one or both panels (dock them)
14. Verify the binding only works when BOTH panels are in auto-hide state
## Registry Support
Administrators can configure this setting via registry for enterprise deployment:
- Key: `HKEY_LOCAL_MACHINE\SOFTWARE\mRemoteNG\TabsAndPanels` or `HKEY_CURRENT_USER\SOFTWARE\mRemoteNG\TabsAndPanels`
- Value: `BindConnectionsAndConfigPanels` (DWORD)
- 0 = Disabled, 1 = Enabled

View File

@@ -1,6 +1,18 @@
**NOTICE: This project currently transited to a new maintainer. Development help would be greatly appreciated.**
<p align="Left">
Developing mRemoteNG to its fullest potential is my personal priority.<br>
While the project remains non-commercial, it does come with ongoing costs — including VPS hosting for testing, AI tools, domain fees, and more. <br> If you find value in mRemoteNG and want to support its future, even a small donation from our community can make a huge difference.<br>
Your support helps me keep the project secure, modern, and accessible for everyone who relies on it — and brings us closer to a brighter, more collaborative future.<br><br>
Consider donating — every contribution counts!
<br><br>
<a href="https://www.paypal.com/paypalme/mremoteng">
<img height='36' alt="PayPal" style='border:0px;height:36px;' src="https://img.shields.io/badge/%24-PayPal-blue.svg?label=Donate&logo=PayPal&style=flat-square">
</a><br>
<a href='https://ko-fi.com/Q5Q41I7JS' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
</a>
</p>
---
<br/><br/>
<p align="center">
<img width="450" src="https://github.com/mRemoteNG/mRemoteNG/blob/mRemoteNGProjectFiles/Header_dark.png">
</p>
@@ -24,14 +36,6 @@
<img alt="Element" src="https://img.shields.io/matrix/mremoteng:matrix.org?label=Join%20to%20chat%20about%20mRemoteNG&logo=element&style=social&link=https://app.element.io/#/room/#mremoteng:matrix.org">
</a>
</p>
<p align="center">
<a href="https://www.paypal.com/paypalme/mremoteng">
<img alt="PayPal" src="https://img.shields.io/badge/%24-PayPal-blue.svg?label=Donate&logo=PayPal&style=flat-square">
</a>
<a href="bitcoin:16fUnHUM3k7W9Fvpc6dug7TAdfeGEcLbSg">
<img alt="Bitcoin" src="https://img.shields.io/badge/%24-Bitcoin.svg?label=Donate&logo=bitcoin&style=flat-square">
</a>
</p>
<p align="center">
<a href="https://github.com/mRemoteNG/mRemoteNG/blob/develop/COPYING.TXT">
@@ -54,7 +58,7 @@
| ---------------|--------------|-----------|
| Stable | ![Build status](https://ci.appveyor.com/api/projects/status/rqwxjxldail7btcf?svg=true) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.76.20/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.76.20) |
| Preview | ![Build status](https://ci.appveyor.com/api/projects/status/rqwxjxldail7btcf/branch/preview?svg=true) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/v1.77.1/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.77.1) |
| Nightly | ![Build status](https://ci.appveyor.com/api/projects/status/rqwxjxldail7btcf/branch/develop?svg=true) | [![Github Releases (by Release)](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/2023.03.03-v1.77.3-nb/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/2023.03.03-v1.77.3-nb) |
| Nightly | ![Build status](https://ci.appveyor.com/api/projects/status/rqwxjxldail7btcf/branch/develop?svg=true) | [![Github Releases](https://img.shields.io/github/downloads/mRemoteNG/mRemoteNG/20250916-v1.78.2-NB-(3177)/total.svg)](https://github.com/mRemoteNG/mRemoteNG/releases/tag/20250916-v1.78.2-NB-(3177)) |
## Features
@@ -68,6 +72,7 @@ The following protocols are supported:
* rlogin (Remote Login)
* Raw Socket Connections
* Powershell remoting
* AnyDesk
For a detailed feature list and general usage support, refer to the [Documentation](https://mremoteng.readthedocs.io/en/latest/).
@@ -85,15 +90,19 @@ For a detailed feature list and general usage support, refer to the [Documentati
#### Source package
This contains the source code from which mRemoteNG is build.
This contains the source code from which mRemoteNG is built.
You will need to compile it yourself using Visual Studio.
### Minimum Requirements
* [Microsoft Visual C++ Redistributable for Visual Studio 2015 - 2022](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads)
* [Microsoft .NET 6.0 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/6.0)
* Microsoft Terminal Service Client 6.0 or later
* Needed if you use RDP. mstscax.dll and/or msrdp.ocx be registered.
Make sure you have the latest version installed:
* [Microsoft .NET Desktop Runtime 10.0](https://dotnet.microsoft.com/download/dotnet/10.0)
* Microsoft Visual C++ Redistributable 20152026 is needed:
- [x64](https://aka.ms/vs/18/release/vc_redist.x64.exe)
- [ARM64](https://aka.ms/vs/18/release/vc_redist.arm64.exe)
- [x86](https://aka.ms/vs/18/release/vc_redist.x86.exe)
* Microsoft Terminal Service Client 6.0 or later (needed if you use RDP with mstscax.dll and/or msrdp.ocx to be registered)
### Download
@@ -137,6 +146,7 @@ _If you are using the Portable version, simply deleting the folder that contains
* [PSmRemoteNG](https://github.com/realslacker/PSmRemoteNG) A module to create mRemoteNG connection files from PowerShell.
* [mRemoteNGOpenVPN](https://github.com/T3los/mRemoteNGOpenVPN) A script that can be embedded as an external tool to control OpenVPN.
* [mRemoteNG-Icons](https://github.com/bearlikelion/mRemoteNG-Icons) A collection of fancy icons to customize the connections
## Contribute

View File

@@ -1,38 +0,0 @@
U2FsdGVkX1/uEeToOEIrunpoPNl7NUYNQfI+ixMzGgKX0DlHZxa/PonAVd9NoAE+
dqWegkN8fa/M2HcW8moN5sN0yS88amG8cfwRZNRSgRB4IxDdYPjM/iX7y8FjUh9R
OZnGhq1rAkqcf7ASAdZfQDSFOAEDPQgByN4IB2j/G3ueqV3jf5sWWiM0ielcorWX
jXuEL7uIk9diI3Qh3BVqmrotzErzqTTLB4DWoL1aWqRRYH+exKahfcMT3C9r+tul
ETH6o1im3kdYzFgHl58FmihbHa+h1+c+DWVGGXRxJPw1DZfg8/+ldIy8J75aWimz
2MX+PiBVQj+wYlSSkQLj2EdbpSERlinE1O55ldwpbnMPAlYCgFRdO3/hiB6LiLLt
n9s8f32HLNG20Mk1oxXdN9VPOw+RwQpUf6Zfcyps6e/9EFKBLnwq4cYwM/dHRuez
w48EJX5wKzpukHn2UFg5aCRGYU/4NyUn+AlIjjCMBWY1R0uBhC340cl6YqoPFN12
clzbS6JdQS+ktusCeaKcsj2iknVqQrGY81LKrTaQZdfehGwAn9pMWE3iWRX80yzO
s08lpmHfPK4uhtlyIbdReLn4n7hvB8KRVa7Foms+4wpEwKrL8KF/8CYc89Tm3PSD
LCrLr7rzCHh51ncJXHAwZqY2ZRLnQBVwhIRsFYyZ595b89tuDY00sYpWnTKzWubK
UD993CmYKg1cA+mj6NR6iSmecawsUz68nI/nmHM2APE5cCCHSK3lz40e9Z9Hmy5Y
kVS6c86a+gwNyn4F9t3iISdj2vIOwGMVWQLeY+nwpiKnnOuI0XPtIMjNbhoaDToT
kph2ZVjqbpmYHgTSX71v8Y16Stl+p/dZn0dE2d4JhxOJxDN//H6y7mOwg8DYX9GP
rFBMIEWyEQyEFYTmWgztQ5KU89w0lV1qiWpaiWR/IDkGbUzHR8ELp4NHYPbZnuYa
FFXooJGPsQ02ioXPm18Lkhloo63lANgyBE0jc1x9hPrI0oVn1wTkKdeW13IbHzrn
VsGXeZz06bB46QChXUPmQ49sNkAXcMDnfNFM9ayUa8eVmNx9fWabtBy8qs7rpdv0
1y/2ud4Da9t7SAUvxwI65+b2Ytk05pLFLmQYb01g4BpBDxbJW3yw3CqKgMnLoZ3t
s2kiUpn7FEQU8jbpbFV+UB4DdJgm8S7o1gbTEWYTscZ7l+oLCmQgMYoi/EJDDIa2
cCSdGy4p7kLlLUoO438Mz36+FDf6qX2B86ezVdNnXQb3UPljjDxiOFM6NkI3HTpl
RqxjBg8JdrwoQ1UMha6ucDKhPXq1xkg0dpO9QyjxywssG3krgQ5Py64s5Xu7IgQm
AzmwGTZ6gFZlDTr9SpJkiucF9vexCo6JHHkF8OjhS49FanqB8otJvg5JclVugP51
LcqqvuMkAsFago261SNcOhgtR6nV5B9QgHyr66c6YnTlwt07T1Qq3S1lw2x0Eccs
PKbJDVU5rAHiM71QYmwsuoC8qkYPTtVPIoUTs+5u5aLywVoLejr1dE5twNXy5PYY
fDwubg0YG3kchvv85N3epZ1h50ADq3W3msU9bWDKWwdwIbpGq+dwjkLssBQmjVtI
R8rGbt1DgL7xtRNF9ESnWVkfHJvJu/5oD6wGAU/oIfBxVON0VYb1evc8wRdQTbDH
Dnt+aKwcSPYdyGVRKfRtBGvEZ8rB5hzCXQnS795L0imdfXjBSJn7Pnl9VwpcB3Pr
aZ6s0GcB8kYDEXzjv+o7JF6k5i2I+sVGwvFVGIoVd/Igq2ysrk/GfWVov0SUu78A
JeHYdtRuKwXOdZw2cjZQ72bvFaHOuoXrQnyKyZDWRyu0NB5HLW75v/YEbr4msIm9
E+3HFwRvKSTfUx/M4NgVKrgsHDeBRD4tLNx/SerQvqaplunM7OfAtULucveUhwSo
vT6uNK3URe1qDgX554cz8c6+KrkglTLFMuKfNWj3q/uSM0BxTTD9QgorNdlMmErH
TfV/ZpZACpuMFRbC5xQRkCG1x4U12pdPbtIkGtVBJROEXhP1aw3BDWwrIN7zSgfj
8I4OF4fbj/rSuvI4klzi1zlUMQQnenlRURE+7DKRxtWipJhW9vtDI0LXN7gGfmbR
73uR3YUny6zUJ0svqaWj4Eo6t3g99nmk4D2hm/622dRksv2HqEQiq29jJxlcbdZB
PU96wOp54s/BzgodyI5dh+xL06Obr9AltLV9vw3iK0VBZqquj9FuhvWC1tYlZQJF
AOgVDOGUZzmAJXftI7gaohFBwsT5tAHQtBuY7tB3b1hrnfrFb9FTNxGZJKcIH3p4
dOAvedsfuq+2/lU9iM4tX9fjSzfnGRZRuKCGDSdhE6EDik9/f2kSCoY9z0zJwdZH
324TpGbZNbgcwgHDL9i5Nsnaua5yxtr0/Fr1We1tvn0=

122
VISUAL_EXAMPLES.md Normal file
View File

@@ -0,0 +1,122 @@
# Connection Frame Color - Visual Examples
## Before and After
### Without Frame Color (Default)
```
┌──────────────────────────────────────────────┐
│ Connection Tab │
├──────────────────────────────────────────────┤
│ │
│ │
│ [Normal connection content area] │
│ │
│ │
│ │
└──────────────────────────────────────────────┘
```
### With Red Frame Color (Production)
```
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Connection Tab (Production) ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ ╔════════════════════════════════════════╗ ┃
┃ ║ ║ ┃
┃ ║ [Connection content area] ║ ┃
┃ ║ With 4-pixel RED border all around ║ ┃
┃ ║ ║ ┃
┃ ╚════════════════════════════════════════╝ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
```
### With Green Frame Color (Test)
```
┌──────────────────────────────────────────────┐
│ Connection Tab (Test) │
├──────────────────────────────────────────────┤
│ ╔════════════════════════════════════════╗ │
│ ║ ║ │
│ ║ [Connection content area] ║ │
│ ║ With 4-pixel GREEN border all around ║ │
│ ║ ║ │
│ ╚════════════════════════════════════════╝ │
└──────────────────────────────────────────────┘
```
## Side-by-Side Comparison
```
Test Connection Production Connection
┌─────────────────────┐ ┏━━━━━━━━━━━━━━━━━━━━━┓
│ [test server] │ ┃ [production server] ┃
│ │ ┃ ╔═══════════════╗ ┃
│ ┌───────────────┐ │ ┃ ║ ║ ┃
│ │ │ │ ┃ ║ !WARNING! ║ ┃
│ │ SSH Session │ │ ┃ ║ Production ║ ┃
│ │ (Green) │ │ ┃ ║ Environment ║ ┃
│ └───────────────┘ │ ┃ ║ (Red) ║ ┃
│ │ ┃ ╚═══════════════╝ ┃
└─────────────────────┘ ┗━━━━━━━━━━━━━━━━━━━━━┛
Safe to experiment Requires extra caution!
```
## Property Grid Display
When you select a connection in mRemoteNG, the Config panel will show:
```
┌─ Display ──────────────────────────────────┐
│ │
│ Name: My Server │
│ Description: Production DB │
│ Icon: SSH │
│ Panel: General │
│ Color: [empty] │
│ Tab Color: [empty] │
│ Connection Frame Color: ▼ Red (Production)│
│ ├─ None │
│ ├─ Red (Prod...)│
│ ├─ Yellow (St...)│
│ ├─ Green (Test) │
│ ├─ Blue (Dev) │
│ └─ Purple (C...)│
└────────────────────────────────────────────┘
```
## Folder Inheritance Example
```
📁 Production Servers (ConnectionFrameColor: Red)
├─ 📄 Web Server 1 (inherits Red)
├─ 📄 Web Server 2 (inherits Red)
└─ 📄 Database Server (inherits Red)
📁 Development Servers (ConnectionFrameColor: Blue)
├─ 📄 Dev Server 1 (inherits Blue)
└─ 📄 Dev Server 2 (inherits Blue)
📁 Test Servers (ConnectionFrameColor: Green)
├─ 📄 Test Server 1 (inherits Green)
└─ 📄 QA Server (inherits Green)
```
All connections in the "Production Servers" folder will automatically
get a red border when you connect to them (assuming inheritance is enabled).
## Color Palette
The implementation uses these specific colors:
- **Red (Production)**: RGB(220, 53, 69) - High visibility warning color
- **Yellow (Staging/UAT)**: RGB(255, 193, 7) - Caution/warning color
- **Green (Test)**: RGB(40, 167, 69) - Safe/go color
- **Blue (Development)**: RGB(0, 123, 255) - Calm, neutral color
- **Purple (Custom)**: RGB(111, 66, 193) - Distinct custom color
- **None (Default)**: Transparent - No border
These colors are chosen for:
1. High contrast and visibility
2. Universal recognition (red = danger, green = safe)
3. Accessibility considerations
4. Consistency with modern UI design patterns

View File

@@ -1,80 +1,64 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31912.275
MinimumVisualStudioVersion = 14.0.25420.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mRemoteNG", "mRemoteNG\mRemoteNG.csproj", "{4934A491-40BC-4E5B-9166-EA1169A220F6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mRemoteNGTests", "mRemoteNGTests\mRemoteNGTests.csproj", "{1453B37F-8621-499E-B0B2-6091F76DC0BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mRemoteNGInstaller", "mRemoteNGInstaller", "{4FE795BE-646E-4F1B-BAD0-A68EA26394DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomActions", "mRemoteNGInstaller\CustomActions\CustomActions.csproj", "{5423D985-CB48-4344-B47F-E8C6D60C8B04}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Installer", "mRemoteNGInstaller\Installer\Installer.wixproj", "{F0168B9F-6815-40DF-BA53-46CEE7683B68}"
ProjectSection(ProjectDependencies) = postProject
{4934A491-40BC-4E5B-9166-EA1169A220F6} = {4934A491-40BC-4E5B-9166-EA1169A220F6}
{5423D985-CB48-4344-B47F-E8C6D60C8B04} = {5423D985-CB48-4344-B47F-E8C6D60C8B04}
{A56A2029-79B8-492A-ABE5-D2BFE05801BD} = {A56A2029-79B8-492A-ABE5-D2BFE05801BD}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mRemoteNGSpecs", "mRemoteNGSpecs\mRemoteNGSpecs.csproj", "{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExternalConnectors", "ExternalConnectors\ExternalConnectors.csproj", "{A56A2029-79B8-492A-ABE5-D2BFE05801BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectListView.NetCore", "ObjectListView\ObjectListView.NetCore.csproj", "{5718734C-03AC-4954-89B1-1723CF03AF10}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|arm64 = Debug|arm64
Debug|x64 = Debug|x64
Release Installer and Portable|x64 = Release Installer and Portable|x64
Release Self-Contained|arm64 = Release Self-Contained|arm64
Release Self-Contained|x64 = Release Self-Contained|x64
Release|arm64 = Release|arm64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|arm64.ActiveCfg = Debug|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|arm64.Build.0 = Debug|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x64.ActiveCfg = Debug|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x64.Build.0 = Debug|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer and Portable|x64.ActiveCfg = Release Portable|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer and Portable|x64.Build.0 = Release Portable|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Self-Contained|arm64.ActiveCfg = Release Self-Contained|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Self-Contained|arm64.Build.0 = Release Self-Contained|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Self-Contained|x64.ActiveCfg = Release Self-Contained|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Self-Contained|x64.Build.0 = Release Self-Contained|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|arm64.ActiveCfg = Release|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|arm64.Build.0 = Release|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x64.ActiveCfg = Release|x64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x64.Build.0 = Release|x64
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x64.ActiveCfg = Debug|x64
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x64.Build.0 = Debug|x64
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer and Portable|x64.ActiveCfg = Release Portable|x64
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|x64.ActiveCfg = Release|x64
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x64.ActiveCfg = Debug|x64
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x64.Build.0 = Debug|x64
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer and Portable|x64.ActiveCfg = Release|x64
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer and Portable|x64.Build.0 = Release|x64
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|x64.ActiveCfg = Release|x64
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|x64.ActiveCfg = Debug|x64
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|x64.Build.0 = Debug|x64
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer and Portable|x64.ActiveCfg = Release|x64
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer and Portable|x64.Build.0 = Release|x64
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release|x64.ActiveCfg = Release|x64
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Debug|x64.ActiveCfg = Debug|x64
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Debug|x64.Build.0 = Debug|x64
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Release Installer and Portable|x64.ActiveCfg = Release Installer|x64
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Release|x64.ActiveCfg = Release|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Debug|arm64.ActiveCfg = Debug|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Debug|arm64.Build.0 = Debug|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Debug|x64.ActiveCfg = Debug|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Debug|x64.Build.0 = Debug|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Installer and Portable|x64.ActiveCfg = Release Portable|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Installer and Portable|x64.Build.0 = Release Portable|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Self-Contained|arm64.ActiveCfg = Release Self-Contained|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Self-Contained|arm64.Build.0 = Release Self-Contained|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Self-Contained|x64.ActiveCfg = Release Self-Contained|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Self-Contained|x64.Build.0 = Release Self-Contained|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|arm64.ActiveCfg = Release|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|arm64.Build.0 = Release|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|x64.ActiveCfg = Release|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|x64.Build.0 = Release|x64
{5718734C-03AC-4954-89B1-1723CF03AF10}.Debug|arm64.ActiveCfg = Debug|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Debug|arm64.Build.0 = Debug|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Debug|x64.ActiveCfg = Debug|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Debug|x64.Build.0 = Debug|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Installer and Portable|x64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Installer and Portable|x64.Build.0 = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Self-Contained|arm64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Self-Contained|arm64.Build.0 = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Self-Contained|x64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Self-Contained|x64.Build.0 = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|arm64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|arm64.Build.0 = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|x64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5423D985-CB48-4344-B47F-E8C6D60C8B04} = {4FE795BE-646E-4F1B-BAD0-A68EA26394DD}
{F0168B9F-6815-40DF-BA53-46CEE7683B68} = {4FE795BE-646E-4F1B-BAD0-A68EA26394DD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5D390A0C-2FC4-4908-B86E-7E4DEF5916EC}
EndGlobalSection

View File

@@ -10,7 +10,7 @@ using mRemoteNG.UI.Window;
namespace mRemoteNG.App
{
[SupportedOSPlatform("windows")]
public static class Windows
public static class AppWindows
{
private static ActiveDirectoryImportWindow _adimportForm;
private static ExternalToolsWindow _externalappsForm;
@@ -26,8 +26,9 @@ namespace mRemoteNG.App
internal static ConfigWindow ConfigForm { get; set; } = new ConfigWindow();
internal static ErrorAndInfoWindow ErrorsForm { get; set; } = new ErrorAndInfoWindow();
private static UpdateWindow UpdateForm { get; set; } = new UpdateWindow();
internal static UpdateWindow UpdateForm { get; set; } = new UpdateWindow();
internal static SSHTransferWindow SshtransferForm { get; private set; } = new SSHTransferWindow();
internal static OptionsWindow OptionsFormWindow { get; private set; }
public static void Show(WindowType windowType)
@@ -44,8 +45,10 @@ namespace mRemoteNG.App
_adimportForm.Show(dockPanel);
break;
case WindowType.Options:
FrmMain.OptionsForm.SetActivatedPage(Language.StartupExit);
FrmMain.OptionsForm.Visible = true;
if (OptionsFormWindow == null || OptionsFormWindow.IsDisposed)
OptionsFormWindow = new OptionsWindow();
OptionsFormWindow.SetActivatedPage(Language.StartupExit);
OptionsFormWindow.Show(dockPanel);
break;
case WindowType.SSHTransfer:
if (SshtransferForm == null || SshtransferForm.IsDisposed)

View File

@@ -0,0 +1,124 @@
using Microsoft.Win32;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace mRemoteNG.DotNet.Update
{
[SupportedOSPlatform("windows")]
public class DotNetRuntimeCheck
{
public const string RequiredDotnetVersion = "9.0";
private const string ReleaseFeedUrl = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json";
#region Installed Version Check
/// <summary>
/// Gets the installed .NET 9 runtime version if present
/// </summary>
/// <returns>The version string (e.g., "v9.0.0") or null if not found</returns>
[SupportedOSPlatform("windows")]
public static string? GetLatestDotNetRuntimeVersion()
{
string[] registryPaths = new[]
{
@"SOFTWARE\dotnet\Setup\InstalledVersions\x86",
@"SOFTWARE\dotnet\Setup\InstalledVersions\x64",
@"SOFTWARE\dotnet\Setup\InstalledVersions\arm64"
};
foreach (string path in registryPaths)
{
try
{
using RegistryKey? key = Registry.LocalMachine.OpenSubKey(path);
if (key == null)
{
continue;
}
// Check for the "sharedhost" subkey
using (RegistryKey? sharedHostKey = key.OpenSubKey("sharedhost"))
{
if (sharedHostKey == null) {
continue;
};
// Look for the "Version" value in sharedhost
object? versionValue = sharedHostKey.GetValue("Version");
if (versionValue != null)
{
string? version = versionValue.ToString();
if (!string.IsNullOrWhiteSpace(version))
{
return version;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error checking registry fallback: {ex.Message}");
}
}
return null;
}
#endregion Installed Version Check
#region Latest Online Version Check
public static async Task<(string latestRuntimeVersion, string downloadUrl)> GetLatestAvailableDotNetVersionAsync()
{
try
{
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("User-Agent", "DotNetRuntimeChecker");
string jsonContent = await httpClient.GetStringAsync(ReleaseFeedUrl);
JObject releasesIndex = JObject.Parse(jsonContent);
// Find the entry for .NET matching RequiredDotnetVersion
JToken? dotnetEntry = releasesIndex["releases-index"]?.FirstOrDefault(entry => entry["channel-version"]?.ToString() == RequiredDotnetVersion);
if (dotnetEntry != null && dotnetEntry["latest-runtime"] != null)
{
string? latestRuntimeVersion = dotnetEntry["latest-runtime"]?.ToString();
string arch;
switch (RuntimeInformation.OSArchitecture)
{
case Architecture.Arm64:
arch = "arm64";
break;
case Architecture.X86:
arch = "x86";
break;
case Architecture.X64:
arch = "x64";
break;
default:
throw new NotSupportedException($"Unsupported architecture: {RuntimeInformation.OSArchitecture}");
}
if (!string.IsNullOrEmpty(latestRuntimeVersion))
{
// Construct the download URL using the latest version
string downloadUrl = $"https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-{latestRuntimeVersion}-windows-{arch}-installer";
return (latestRuntimeVersion, downloadUrl);
}
}
return ("Unknown", "");
}
catch (Exception ex)
{
Console.WriteLine($"Error fetching latest version: {ex.Message}");
return ("Unknown", "");
}
}
#endregion Latest Online Version Check
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace mRemoteNG.App.Update
{
public class InternetConnection
{
public static bool IsPosible()
{
try
{
using var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(5);
return client.GetAsync("https://www.microsoft.com").Result.IsSuccessStatusCode;
}
catch (Exception)
{
return false;
}
}
}
}

View File

@@ -0,0 +1,42 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Runtime.Versioning; // Add for SupportedOSPlatform
namespace mRemoteNG.App.Update
{
public class VCppRuntimeCheck
{
[SupportedOSPlatform("windows")]
public static List<string> GetInstalledVcRedistVersions()
{
var installedVersions = new List<string>();
var baseKeys = new[]
{
@"SOFTWARE\Microsoft\VisualStudio",
@"SOFTWARE\WOW6432Node\Microsoft\VisualStudio"
};
for (int major = 14; major <= 17; major++) // Covers 20152022+
{
for (int minor = 0; minor <= 3; minor++)
{
string version = $"{major}.{minor}";
foreach (var baseKey in baseKeys)
{
string path = $@"{baseKey}\{version}\VC\Runtimes\x64";
using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(path))
{
if (key?.GetValue("Installed") is int installed && installed == 1)
{
installedVersions.Add(version);
}
}
}
}
}
return installedVersions;
}
}
}

View File

@@ -15,8 +15,10 @@ namespace mRemoteNG.App.Info
{
public const string UrlHome = "https://mremoteng.org";
public const string UrlDonate = "https://mremoteng.org/contribute";
public const string UrlForum = "https://www.reddit.com/r/mRemoteNG";
public const string UrlBugs = "https://bugs.mremoteng.org";
public const string UrlForum = "https://github.com/orgs/mRemoteNG/discussions";
public const string UrlChat = "https://app.element.io/#/room/#mremoteng:matrix.org";
public const string UrlCommunity = "https://www.reddit.com/r/mRemoteNG";
public const string UrlBugs = "https://github.com/mRemoteNG/mRemoteNG/issues/new";
public const string UrlDocumentation = "https://mremoteng.readthedocs.io/en/latest/";
public static readonly string ApplicationVersion = Application.ProductVersion;
public static readonly string ProductName = Application.ProductName;
@@ -54,8 +56,11 @@ namespace mRemoteNG.App.Info
public static Version GetApplicationVersion()
{
_ = System.Version.TryParse(ApplicationVersion, out Version v);
return v;
string cleanedVersion = ApplicationVersion.Split(' ')[0].Replace("(", "").Replace(")", "").Replace("Build", "");
cleanedVersion = cleanedVersion + "." + ApplicationVersion.Split(' ')[^1].Replace(")", "");
_ = System.Version.TryParse(cleanedVersion, out Version parsedVersion);
return parsedVersion;
}
}
}

View File

@@ -57,9 +57,9 @@ namespace mRemoteNG.App.Initialization
return new OnlyLogMessageFilter(
new MessageTypeFilterDecorator(
new NotificationPanelMessageFilteringOptions(),
new MessageFocusDecorator(Windows.ErrorsForm,
new MessageFocusDecorator(AppWindows.ErrorsForm,
new NotificationPanelSwitchOnMessageFilteringOptions(),
new NotificationPanelMessageWriter(Windows.ErrorsForm))
new NotificationPanelMessageWriter(AppWindows.ErrorsForm))
)
);
}

View File

@@ -9,14 +9,9 @@ using mRemoteNG.Resources.Language;
namespace mRemoteNG.App.Initialization
{
[SupportedOSPlatform("windows")]
public class StartupDataLogger
public class StartupDataLogger(MessageCollector messageCollector)
{
private readonly MessageCollector _messageCollector;
public StartupDataLogger(MessageCollector messageCollector)
{
_messageCollector = messageCollector ?? throw new ArgumentNullException(nameof(messageCollector));
}
private readonly MessageCollector _messageCollector = messageCollector ?? throw new ArgumentNullException(nameof(messageCollector));
public void LogStartupData()
{

View File

@@ -1,101 +1,158 @@
using System;
using Microsoft.IdentityModel.Tokens;
using mRemoteNG.App.Update;
using mRemoteNG.Config.Settings;
using mRemoteNG.DotNet.Update;
using mRemoteNG.UI.Forms;
using mRemoteNG.Resources.Language;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using mRemoteNG.Config.Settings;
using mRemoteNG.UI.Forms;
namespace mRemoteNG.App
{
[SupportedOSPlatform("windows")]
public static class ProgramRoot
{
private static Mutex _mutex;
private static FrmSplashScreenNew _frmSplashScreen = null;
private static Mutex? _mutex;
private static string customResourcePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Languages");
/// <summary>
/// The main entry point for the application.
/// </summary>
private static System.Threading.Thread? _wpfSplashThread;
private static FrmSplashScreenNew? _wpfSplash;
[STAThread]
public static void Main(string[] args)
{
Trace.WriteLine("!!!!!!=============== TEST ==================!!!!!!!!!!!!!");
// Forcing to load System.Configuration.ConfigurationManager before any other assembly to be able to check settings
try
{
string assemblyFile = "System.Configuration.ConfigurationManager" + ".dll";
string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assemblies", assemblyFile);
// Ensure the real entry point is definitely STA
MainAsync(args).GetAwaiter().GetResult();
}
if (File.Exists(assemblyPath))
{
Assembly.LoadFrom(assemblyPath);
}
}
catch (FileNotFoundException ex)
{
Trace.WriteLine("Error occured: " + ex.Message);
}
//Subscribe to AssemblyResolve event
private static Task MainAsync(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
//Check if local settings DB exist or accessible
CheckLockalDB();
#if !SELF_CONTAINED
// Runtime checks only needed for framework-dependent deployments
// Self-contained builds include the runtime, so no check is needed
string? installedVersion = DotNetRuntimeCheck.GetLatestDotNetRuntimeVersion();
//installedVersion = ""; // Force check for testing purposes
Lazy<bool> singleInstanceOption = new Lazy<bool>(() => Properties.OptionsStartupExitPage.Default.SingleInstance);
var checkFail = false;
// Checking .NET Runtime version
var (latestRuntimeVersion, downloadUrl) = DotNetRuntimeCheck.GetLatestAvailableDotNetVersionAsync().GetAwaiter().GetResult();
if (string.IsNullOrEmpty(installedVersion))
{
try
{
var result = ShowDownloadCancelDialog(
$".NET " + DotNetRuntimeCheck.RequiredDotnetVersion + ".0 " + Language.MsgRuntimeIsRequired + "\n\n" +
Language.MsgDownloadLatestRuntime + "\n" + downloadUrl + "\n\n" +
Language.MsgExit + "\n\n",
Language.MsgMissingRuntime + " .NET " + DotNetRuntimeCheck.RequiredDotnetVersion);
if (result == DialogResult.OK && InternetConnection.IsPosible())
{
try
{
Process.Start(new ProcessStartInfo(fileName: downloadUrl) { UseShellExecute = true });
}
catch (Exception ex)
{
MessageBox.Show($"Unable to open download link: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch { }
checkFail = true;
}
// Checking Visual C++ Redistributable version
if (VCppRuntimeCheck.GetInstalledVcRedistVersions() == null || VCppRuntimeCheck.GetInstalledVcRedistVersions().Count == 0)
{
var downloadUrl2 = "https://aka.ms/vs/17/release/vc_redist.x64.exe";
try
{
var result = ShowDownloadCancelDialog(
$"A Visual C++ (MSVC) " + Language.MsgRuntimeIsRequired + "\n\n" +
Language.MsgDownloadLatestRuntime + "\n" + downloadUrl2 + "\n\n" +
Language.MsgExit + "\n\n",
Language.MsgMissingRuntime + " Visual C++ Redistributable x64");
if (result == DialogResult.OK && InternetConnection.IsPosible())
{
try
{
Process.Start(new ProcessStartInfo(fileName: downloadUrl2) { UseShellExecute = true });
}
catch (Exception ex)
{
MessageBox.Show($"Unable to open download link: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch { }
checkFail = true;
}
if (checkFail)
{
Environment.Exit(0);
}
#endif
Lazy<bool> singleInstanceOption = new(() => Properties.OptionsStartupExitPage.Default.SingleInstance);
if (singleInstanceOption.Value)
{
StartApplicationAsSingleInstance();
}
else
{
StartApplication();
return Task.CompletedTask;
}
// Assembly resolve handler
private static Assembly? OnAssemblyResolve(object? sender, ResolveEventArgs args)
{
try
{
string assemblyName = new AssemblyName(args.Name).Name ?? string.Empty;
if (assemblyName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
return null;
string assemblyFile = assemblyName + ".dll";
string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assemblies", assemblyFile);
if (File.Exists(assemblyPath))
return Assembly.LoadFrom(assemblyPath);
}
catch
{
// Suppress resolution exceptions; return null to continue standard probing
}
return null;
}
private static void CheckLockalDB()
{
LocalSettingsDBManager settingsManager = new LocalSettingsDBManager(dbPath: "mRemoteNG.appSettings", useEncryption: false, schemaFilePath: "");
LocalDBManager settingsManager = new LocalDBManager(dbPath: "mRemoteNG.appSettings", useEncryption: false, schemaFilePath: "");
}
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs resolveArgs)
{
string assemblyName = new AssemblyName(resolveArgs.Name).Name.Replace(".resources", string.Empty);
string assemblyFile = assemblyName + ".dll";
string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assemblies", assemblyFile);
if (File.Exists(assemblyPath))
{
return Assembly.LoadFrom(assemblyPath);
}
return null;
}
private static void StartApplication()
{
CatchAllUnhandledExceptions();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_frmSplashScreen = FrmSplashScreenNew.GetInstance();
Screen targetScreen = Screen.PrimaryScreen;
Rectangle viewport = targetScreen.WorkingArea;
_frmSplashScreen.Top = viewport.Top;
_frmSplashScreen.Left = viewport.Left;
// normally it should be screens[1] however due DPI apply 1 size "same" as default with 100%
_frmSplashScreen.Left = viewport.Left + (targetScreen.Bounds.Size.Width - _frmSplashScreen.Width) / 2;
_frmSplashScreen.Top = viewport.Top + (targetScreen.Bounds.Size.Height - _frmSplashScreen.Height) / 2;
_frmSplashScreen.ShowInTaskbar = false;
_frmSplashScreen.Show();
ShowSplashOnStaThread();
Application.Run(FrmMain.Default);
}
@@ -134,8 +191,24 @@ namespace mRemoteNG.App
Process currentProcess = Process.GetCurrentProcess();
foreach (Process enumeratedProcess in Process.GetProcessesByName(currentProcess.ProcessName))
{
// Safely check for null MainModule and FileName
string? enumeratedFileName = null;
string? currentFileName = null;
try
{
enumeratedFileName = enumeratedProcess.MainModule?.FileName;
currentFileName = currentProcess.MainModule?.FileName;
}
catch
{
// Access to MainModule can throw exceptions for some processes; ignore and continue
continue;
}
if (enumeratedProcess.Id != currentProcess.Id &&
enumeratedProcess.MainModule.FileName == currentProcess.MainModule.FileName &&
!string.IsNullOrEmpty(enumeratedFileName) &&
!string.IsNullOrEmpty(currentFileName) &&
enumeratedFileName == currentFileName &&
enumeratedProcess.MainWindowHandle != IntPtr.Zero)
windowHandle = enumeratedProcess.MainWindowHandle;
}
@@ -145,31 +218,152 @@ namespace mRemoteNG.App
private static void CatchAllUnhandledExceptions()
{
System.Windows.Forms.Application.ThreadException += ApplicationOnThreadException;
System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += ApplicationOnThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
}
private static void ApplicationOnThreadException(object sender, ThreadExceptionEventArgs e)
{
// if (PresentationSource.FromVisual(FrmSplashScreenNew))
FrmSplashScreenNew.GetInstance().Close();
CloseSplash();
if (FrmMain.Default.IsDisposed) return;
FrmUnhandledException window = new(e.Exception, false);
window.ShowDialog(FrmMain.Default);
}
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//TODO: Check if splash closed properly
//if (!FrmSplashScreenNew.GetInstance().IsDisposed)
// FrmSplashScreenNew.GetInstance().Close();
FrmUnhandledException window = new(e.ExceptionObject as Exception, e.IsTerminating);
window.ShowDialog(FrmMain.Default);
}
private static void ShowSplashOnStaThread()
{
_wpfSplashThread = new System.Threading.Thread(() =>
{
_wpfSplash = FrmSplashScreenNew.GetInstance();
// Center the splash screen on the primary screen before showing it
_wpfSplash.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
_wpfSplash.ShowInTaskbar = false;
_wpfSplash.Show();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(_wpfSplash);
System.Windows.Threading.Dispatcher.Run(); // WPF message loop
})
{ IsBackground = true };
_wpfSplashThread.SetApartmentState(System.Threading.ApartmentState.STA);
_wpfSplashThread.Start();
}
private static void CloseSplash()
{
if (_wpfSplash != null)
{
_wpfSplash.Dispatcher.Invoke(() => _wpfSplash.Close());
_wpfSplash = null;
}
if (_wpfSplashThread != null)
{
_wpfSplashThread.Join();
_wpfSplashThread = null;
}
}
// Helper to show a dialog with "Download" and "Cancel" buttons.
// Returns DialogResult.OK if Download clicked, otherwise DialogResult.Cancel.
private static DialogResult ShowDownloadCancelDialog(string message, string caption)
{
using Form dialog = new Form()
{
Text = caption,
StartPosition = FormStartPosition.CenterScreen,
FormBorderStyle = FormBorderStyle.FixedDialog,
MinimizeBox = false,
MaximizeBox = false,
ShowInTaskbar = false,
ClientSize = new Size(560, 200),
Icon = SystemIcons.Information
};
// Try to find a URL in the message (very simple heuristic: first "http" until whitespace/newline)
int urlStart = message.IndexOf("http", StringComparison.OrdinalIgnoreCase);
string? url = null;
if (urlStart >= 0)
{
int urlEnd = message.IndexOfAny(new char[] { ' ', '\r', '\n', '\t' }, urlStart);
if (urlEnd == -1) urlEnd = message.Length;
url = message.Substring(urlStart, urlEnd - urlStart);
}
LinkLabel lbl = new LinkLabel()
{
AutoSize = false,
Text = message,
Location = new Point(12, 12),
Size = new Size(dialog.ClientSize.Width - 24, dialog.ClientSize.Height - 60),
TextAlign = ContentAlignment.TopLeft,
LinkBehavior = LinkBehavior.SystemDefault
};
lbl.MaximumSize = new Size(dialog.ClientSize.Width - 24, 0);
if (!string.IsNullOrEmpty(url) && urlStart >= 0)
{
// Ensure link indices are within bounds of the LinkLabel text
int linkStartInLabel = urlStart;
int linkLength = url.Length;
if (linkStartInLabel + linkLength <= lbl.Text.Length)
{
lbl.Links.Add(linkStartInLabel, linkLength, url);
}
}
lbl.LinkClicked += (s, e) =>
{
string? linkUrl = e.Link.LinkData as string;
if (string.IsNullOrEmpty(linkUrl))
return;
if (!InternetConnection.IsPosible())
{
MessageBox.Show("No internet connection is available.", "Network", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// Treat clicking the link the same as clicking the "Download" button:
// set DialogResult to OK so the caller receives DialogResult.OK and can proceed to open the download URL.
dialog.DialogResult = DialogResult.OK;
// Do not call Process.Start here to avoid duplicate launches; caller already opens the URL when it sees DialogResult.OK.
};
Button btnDownload = new Button()
{
Text = "Download",
DialogResult = DialogResult.OK,
Size = new Size(100, 28),
};
Button btnCancel = new Button()
{
Text = "Cancel",
DialogResult = DialogResult.Cancel,
Size = new Size(100, 28),
};
// Position buttons
int padding = 12;
btnCancel.Location = new Point(dialog.ClientSize.Width - padding - btnCancel.Width, dialog.ClientSize.Height - padding - btnCancel.Height);
btnDownload.Location = new Point(btnCancel.Left - 8 - btnDownload.Width, btnCancel.Top);
// Set dialog defaults
dialog.Controls.Add(lbl);
dialog.Controls.Add(btnDownload);
dialog.Controls.Add(btnCancel);
dialog.AcceptButton = btnDownload;
dialog.CancelButton = btnCancel;
// Adjust label height to wrap text properly
lbl.Height = btnCancel.Top - lbl.Top - 8;
return dialog.ShowDialog();
}
}
}

View File

@@ -121,7 +121,11 @@ namespace mRemoteNG.App
private static void RunUpdateFile()
{
if (UpdatePending)
{
// Validate the update file path to prevent command injection
Tools.PathValidator.ValidateExecutablePathOrThrow(_updateFilePath, nameof(_updateFilePath));
Process.Start(new ProcessStartInfo(_updateFilePath) { UseShellExecute = true });
}
}
}
}

View File

@@ -84,10 +84,8 @@ namespace mRemoteNG.App
try
{
await _appUpdate.GetUpdateInfoAsync();
if (_appUpdate.IsUpdateAvailable())
{
Windows.Show(WindowType.Update);
}
// Update is available, but don't show the panel automatically at startup
// User can check for updates manually via Help > Check for Updates menu
}
catch (Exception ex)
{

View File

@@ -19,22 +19,16 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Connections
{
[SupportedOSPlatform("windows")]
public class SqlConnectionsLoader : IConnectionsLoader
public class SqlConnectionsLoader(
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> localConnectionPropertiesDeserializer,
IDataProvider<string> dataProvider) : IConnectionsLoader
{
private readonly IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> _localConnectionPropertiesDeserializer;
private readonly IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> _localConnectionPropertiesDeserializer = localConnectionPropertiesDeserializer.ThrowIfNull(nameof(localConnectionPropertiesDeserializer));
private readonly IDataProvider<string> _dataProvider;
private readonly IDataProvider<string> _dataProvider = dataProvider.ThrowIfNull(nameof(dataProvider));
private Func<Optional<SecureString>> AuthenticationRequestor { get; set; } = () => MiscTools.PasswordDialog("", false);
public SqlConnectionsLoader(
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> localConnectionPropertiesDeserializer,
IDataProvider<string> dataProvider)
{
_localConnectionPropertiesDeserializer = localConnectionPropertiesDeserializer.ThrowIfNull(nameof(localConnectionPropertiesDeserializer));
_dataProvider = dataProvider.ThrowIfNull(nameof(dataProvider));
}
public ConnectionTreeModel Load()
{
IDatabaseConnector connector = DatabaseConnectorFactory.DatabaseConnectorFromSettings();

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Data.Common;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
@@ -23,18 +24,11 @@ using mRemoteNG.Config.Serializers.ConnectionSerializers.Sql;
namespace mRemoteNG.Config.Connections
{
[SupportedOSPlatform("windows")]
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
public class SqlConnectionsSaver(SaveFilter saveFilter, ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> localPropertieSerializer, IDataProvider<string> localPropertiesDataProvider) : ISaver<ConnectionTreeModel>
{
private readonly SaveFilter _saveFilter;
private readonly ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> _localPropertiesSerializer;
private readonly IDataProvider<string> _dataProvider;
public SqlConnectionsSaver(SaveFilter saveFilter, ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> localPropertieSerializer, IDataProvider<string> localPropertiesDataProvider)
{
_saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
_localPropertiesSerializer = localPropertieSerializer.ThrowIfNull(nameof(localPropertieSerializer));
_dataProvider = localPropertiesDataProvider.ThrowIfNull(nameof(localPropertiesDataProvider));
}
private readonly SaveFilter _saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
private readonly ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> _localPropertiesSerializer = localPropertieSerializer.ThrowIfNull(nameof(localPropertieSerializer));
private readonly IDataProvider<string> _dataProvider = localPropertiesDataProvider.ThrowIfNull(nameof(localPropertiesDataProvider));
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
{
@@ -133,11 +127,20 @@ namespace mRemoteNG.Config.Connections
if (rootTreeNode != null)
{
dbQuery =
databaseConnector.DbCommand(
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES('" +
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "', 0, '" + strProtected + "','" +
ConnectionsFileInfo.ConnectionFileVersion + "')");
dbQuery = databaseConnector.DbCommand(
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(@Name, 0, @Protected, @Version)");
DbParameter nameParam = dbQuery.CreateParameter();
nameParam.ParameterName = "@Name";
nameParam.Value = rootTreeNode.Name;
DbParameter protectedParam = dbQuery.CreateParameter();
protectedParam.ParameterName = "@Protected";
protectedParam.Value = strProtected;
DbParameter versionParam = dbQuery.CreateParameter();
versionParam.ParameterName = "@Version";
versionParam.Value = ConnectionsFileInfo.ConnectionFileVersion;
dbQuery.Parameters.Add(nameParam);
dbQuery.Parameters.Add(protectedParam);
dbQuery.Parameters.Add(versionParam);
dbQuery.ExecuteNonQuery();
}
else
@@ -165,7 +168,15 @@ namespace mRemoteNG.Config.Connections
// TODO: use transaction
System.Data.Common.DbCommand dbQuery = databaseConnector.DbCommand("TRUNCATE TABLE tblUpdate");
dbQuery.ExecuteNonQuery();
dbQuery = databaseConnector.DbCommand("INSERT INTO tblUpdate (LastUpdate) VALUES('" + MiscTools.DBDate(DateTime.Now.ToUniversalTime()) + "')");
dbQuery = databaseConnector.DbCommand("INSERT INTO tblUpdate (LastUpdate) VALUES(@LastUpdate)");
DbParameter lastUpdateParam = dbQuery.CreateParameter();
lastUpdateParam.ParameterName = "@LastUpdate";
// Use DBTimeStampNow() instead of DBDate() - the column is datetime type, not string
// DBTimeStampNow() returns the database-specific .NET type: DateTime for MSSQL, MySqlDateTime for MySQL
lastUpdateParam.Value = MiscTools.DBTimeStampNow();
dbQuery.Parameters.Add(lastUpdateParam);
dbQuery.ExecuteNonQuery();
}

View File

@@ -4,6 +4,7 @@ using System.Runtime.Versioning;
using mRemoteNG.App;
using mRemoteNG.Messages;
using mRemoteNG.Resources.Language;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.DataProviders
{
@@ -17,8 +18,13 @@ namespace mRemoteNG.Config.DataProviders
if (WeDontNeedToBackup(fileName))
return;
PathValidator.ValidatePathOrThrow(fileName, nameof(fileName));
string backupFileName =
string.Format(Properties.OptionsBackupPage.Default.BackupFileNameFormat, fileName, DateTime.Now);
PathValidator.ValidatePathOrThrow(backupFileName, nameof(backupFileName));
File.Copy(fileName, backupFileName);
}
catch (Exception ex)

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.Linq;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.DataProviders
{
@@ -7,6 +8,8 @@ namespace mRemoteNG.Config.DataProviders
{
public void PruneBackupFiles(string filePath, int maxBackupsToKeep)
{
PathValidator.ValidatePathOrThrow(filePath, nameof(filePath));
string fileName = Path.GetFileName(filePath);
string directoryName = Path.GetDirectoryName(filePath);

View File

@@ -2,18 +2,30 @@
using System.IO;
using System.Runtime.Versioning;
using mRemoteNG.App;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.DataProviders
{
[SupportedOSPlatform("windows")]
public class FileDataProvider : IDataProvider<string>
{
private string _filePath;
[SupportedOSPlatform("windows")]
public string FilePath { get; set; }
public string FilePath
{
get => _filePath;
set
{
PathValidator.ValidatePathOrThrow(value, nameof(FilePath));
_filePath = value;
}
}
public FileDataProvider(string filePath)
{
FilePath = filePath;
PathValidator.ValidatePathOrThrow(filePath, nameof(filePath));
_filePath = filePath;
}
public virtual string Load()
@@ -59,6 +71,7 @@ namespace mRemoteNG.Config.DataProviders
{
try
{
PathValidator.ValidatePathOrThrow(newPath, nameof(newPath));
File.Move(FilePath, newPath);
FilePath = newPath;
}

View File

@@ -3,14 +3,9 @@
namespace mRemoteNG.Config.DataProviders
{
[SupportedOSPlatform("windows")]
public class FileDataProviderWithRollingBackup : FileDataProvider
public class FileDataProviderWithRollingBackup(string filePath) : FileDataProvider(filePath)
{
private readonly FileBackupCreator _fileBackupCreator;
public FileDataProviderWithRollingBackup(string filePath) : base(filePath)
{
_fileBackupCreator = new FileBackupCreator();
}
private readonly FileBackupCreator _fileBackupCreator = new FileBackupCreator();
public override void Save(string content)
{

View File

@@ -1,13 +1,8 @@
namespace mRemoteNG.Config.DataProviders
{
public class InMemoryStringDataProvider : IDataProvider<string>
public class InMemoryStringDataProvider(string initialContents = "") : IDataProvider<string>
{
private string _contents;
public InMemoryStringDataProvider(string initialContents = "")
{
_contents = initialContents;
}
private string _contents = initialContents;
public string Load()
{

View File

@@ -3,20 +3,15 @@ using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using mRemoteNG.App;
using MySql.Data.MySqlClient;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Runtime.Versioning;
namespace mRemoteNG.Config.DataProviders
{
[SupportedOSPlatform("windows")]
public class SqlDataProvider : IDataProvider<DataTable>
public class SqlDataProvider(IDatabaseConnector databaseConnector) : IDataProvider<DataTable>
{
public IDatabaseConnector DatabaseConnector { get; }
public SqlDataProvider(IDatabaseConnector databaseConnector)
{
DatabaseConnector = databaseConnector;
}
public IDatabaseConnector DatabaseConnector { get; } = databaseConnector;
public DataTable Load()
{

View File

@@ -1,44 +1,149 @@
using System;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using LiteDB;
using mRemoteNG.Resources.Language;
namespace mRemoteNG.Config.DatabaseConnectors
{
[SupportedOSPlatform("windows")]
//[SupportedOSPlatform("windows")]
/// <summary>
/// A helper class for testing database connectivity
/// </summary>
///
using System;
using System.Data.SqlClient;
public class DatabaseConnectionTester
{
public async Task<ConnectionTestResult> TestConnectivity(string type,
string server,
string database,
string username,
string password)
public async Task<ConnectionTestResult> TestConnectivity(string type, string server, string database, string username, string password)
{
using (IDatabaseConnector dbConnector = DatabaseConnectorFactory.DatabaseConnector(type, server, database, username, password))
try
{
try
// Build the connection string based on the provided parameters
string connectionString = $"Data Source={server};Initial Catalog={database};User ID={username};Password={password}";
// Attempt to open a connection to the database
using (SqlConnection connection = new SqlConnection(connectionString))
{
await dbConnector.ConnectAsync();
return ConnectionTestResult.ConnectionSucceded;
await connection.OpenAsync();
}
catch (SqlException sqlException)
return ConnectionTestResult.ConnectionSucceded;
}
catch (SqlException ex)
{
// Handle specific SQL exceptions
switch (ex.Number)
{
if (sqlException.Message.Contains("The server was not found"))
return ConnectionTestResult.ServerNotAccessible;
if (sqlException.Message.Contains("Cannot open database"))
case 4060: // Invalid Database
return ConnectionTestResult.UnknownDatabase;
if (sqlException.Message.Contains("Login failed for user"))
case 18456: // Login Failed
return ConnectionTestResult.CredentialsRejected;
return ConnectionTestResult.UnknownError;
}
catch (Exception)
{
return ConnectionTestResult.UnknownError;
case -1: // Server not accessible
return ConnectionTestResult.ServerNotAccessible;
default:
return ConnectionTestResult.UnknownError;
}
}
catch
{
// Handle any other exceptions
return ConnectionTestResult.UnknownError;
}
}
}
//public class DatabaseConnectionTester
//{
//public async Task<ConnectionTestResult> TestConnectivity(string type, string server, string database, string username, string password)
//{
//using IDatabaseConnector dbConnector = DatabaseConnectorFactory.DatabaseConnector(type, server, database, username, password);
//try
//{
// Validate architecture compatibility
//if (!Environment.Is64BitProcess)
//{
// throw new PlatformNotSupportedException("The application must run in a 64-bit process to use this database connector.");
// }
// Attempt to connect
//using (SqlConnection connection = new SqlConnection("Data Source=172.22.155.100,1433;Initial Catalog=Demo;Integrated Security=False;User ID=sa;Password=London123;Multiple Active Result Sets=True;Connect Timeout=30;Encrypt=True;Trust Server Certificate=True;Application Name=mRemoteNG;Application Intent=ReadOnly"))
//{
// connection.Open();
// Console.WriteLine("Connection successful!");
//}
//Console.WriteLine($"{RuntimeInformation.OSArchitecture}");
//Console.WriteLine($"{RuntimeInformation.ProcessArchitecture}");
//try
//{
// using (SqlConnection connection = new SqlConnection("Data Source=172.22.155.100,1433;Initial Catalog=Demo;Integrated Security=False;User ID=sa;Password=London123;Multiple Active Result Sets=True;Connect Timeout=30;Encrypt=True;Trust Server Certificate=True;Application Name=mRemoteNG;Application Intent=ReadOnly"))
// {
// connection.Open();
// Console.WriteLine("Connection successful!");
// }
//}
//catch (Exception ex)
//{
// Console.WriteLine($"Connection failed: {ex.Message}");
//}
//}
/*
try
{
using (SqlConnection connection = new SqlConnection("Data Source=172.22.155.100,1433;Initial Catalog=Demo;Integrated Security=False;User ID=sa;Password=London123;Multiple Active Result Sets=True;Connect Timeout=30;Encrypt=True;Trust Server Certificate=True;Application Name=mRemoteNG;Application Intent=ReadOnly"))
{
connection.Open();
}
}
catch (TypeInitializationException ex)
{
Console.WriteLine($"Type initialization error: {ex.InnerException?.Message}");
}
//await dbConnector.ConnectAsync();
return ConnectionTestResult.ConnectionSucceded;
}
catch (PlatformNotSupportedException ex)
{
// Log or handle architecture mismatch
Console.WriteLine(string.Format(Language.ErrorPlatformNotSupported, ex.Message));
return ConnectionTestResult.UnknownError;
}
catch (DllNotFoundException ex)
{
// Handle missing native dependencies
Console.WriteLine(string.Format(Language.ErrorMissingDependency, ex.Message));
return ConnectionTestResult.UnknownError;
}
catch (BadImageFormatException ex)
{
// Handle architecture mismatch in native libraries
Console.WriteLine(string.Format(Language.ErrorArchitectureMismatch, ex.Message));
return ConnectionTestResult.UnknownError;
}
catch (SqlException sqlException)
{
if (sqlException.Message.Contains("The server was not found"))
return ConnectionTestResult.ServerNotAccessible;
if (sqlException.Message.Contains("Cannot open database"))
return ConnectionTestResult.UnknownDatabase;
if (sqlException.Message.Contains("Login failed for user"))
return ConnectionTestResult.CredentialsRejected;
return ConnectionTestResult.UnknownError;
}
catch (Exception ex)
{
// Log unexpected errors
Console.WriteLine($"Unexpected error: {ex.Message}");
return ConnectionTestResult.UnknownError;
}
*/
// }
// }
}

View File

@@ -1,7 +1,8 @@
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Threading.Tasks;
using static BrightIdeasSoftware.TreeListView;
// ReSharper disable ArrangeAccessorOwnerBody
@@ -9,7 +10,7 @@ namespace mRemoteNG.Config.DatabaseConnectors
{
public class MSSqlDatabaseConnector : IDatabaseConnector
{
private DbConnection _dbConnection { get; set; } = default(SqlConnection);
private DbConnection _dbConnection { get; set; } = default!;
private string _dbConnectionString = "";
private readonly string _dbHost;
private readonly string _dbCatalog;
@@ -58,10 +59,17 @@ namespace mRemoteNG.Config.DatabaseConnectors
_dbConnectionString = new SqlConnectionStringBuilder
{
ApplicationName = "mRemoteNG",
ApplicationIntent = ApplicationIntent.ReadOnly,
DataSource = $"{hostParts[0]},{_dbPort}",
InitialCatalog = _dbCatalog,
UserID = _dbUsername,
Password = _dbPassword,
IntegratedSecurity = false,
Encrypt = true,
TrustServerCertificate = true,
ConnectTimeout = 30,
MultipleActiveResultSets = true
}.ToString();
}

View File

@@ -10,14 +10,9 @@ using mRemoteNG.Tools;
namespace mRemoteNG.Config.Import
{
[SupportedOSPlatform("windows")]
public class PortScanImporter : IConnectionImporter<IEnumerable<ScanHost>>
public class PortScanImporter(ProtocolType targetProtocolType) : IConnectionImporter<IEnumerable<ScanHost>>
{
private readonly ProtocolType _targetProtocolType;
public PortScanImporter(ProtocolType targetProtocolType)
{
_targetProtocolType = targetProtocolType;
}
private readonly ProtocolType _targetProtocolType = targetProtocolType;
public void Import(IEnumerable<ScanHost> hosts, ContainerInfo destinationContainer)
{

View File

@@ -0,0 +1,140 @@
using System;
using System.Management;
using System.Net.NetworkInformation;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
namespace mRemoteNG.Config.MachineIdentifier
{
[SupportedOSPlatform("windows")]
/// <summary>
/// Provides functionality to generate a consistent and unique machine identifier
/// based on hardware properties (disk serial number, MAC address, BIOS UUID, and machine name).
/// This class is supported only on Windows.
/// </summary>
public static class MachineIdentifierGenerator
{
/// <summary>
/// Generates a consistent machine identifier by combining hardware-based identifiers
/// (disk serial number, MAC address, BIOS UUID, and machine name) and hashing the result.
/// </summary>
/// <returns>A consistent and unique identifier for the machine.</returns>
/// <exception cref="PlatformNotSupportedException">Thrown if the method is called on a non-Windows platform.</exception>
public static string GenerateMachineIdentifier()
{
// Ensure the code runs only on Windows
if (!OperatingSystem.IsWindows())
{
throw new PlatformNotSupportedException("This method is supported only on Windows.");
}
// Retrieve hardware-based identifiers (with fallbacks)
string diskId = GetDiskSerialNumber() ?? "NO_DISK_ID";
string macAddress = GetMacAddress() ?? "NO_MAC_ADDRESS";
string biosUuid = GetBiosUuid() ?? "NO_BIOS_UUID";
string machineName = Environment.MachineName;
// Combine them into a single string
string combined = $"{diskId}_{macAddress}_{biosUuid}_{machineName}";
// Hash the combined string to ensure a fixed length and improve security
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
/// <summary>
/// Retrieves the serial number of the first physical disk using WMI.
/// </summary>
/// <returns>The disk serial number, or null if the serial number cannot be retrieved.</returns>
private static string GetDiskSerialNumber()
{
try
{
using (ManagementObjectSearcher searcher = new("SELECT SerialNumber FROM Win32_DiskDrive"))
{
foreach (ManagementObject wmi_HD in searcher.Get())
{
if (wmi_HD["SerialNumber"] != null)
{
string serialNumber = wmi_HD["SerialNumber"].ToString().Trim();
if (!string.IsNullOrEmpty(serialNumber))
{
return serialNumber;
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error retrieving disk serial number: {ex.Message}");
}
return null; // Return null if the disk serial number cannot be retrieved
}
/// <summary>
/// Retrieves the MAC address of the first active network adapter.
/// </summary>
/// <returns>The MAC address, or null if the MAC address cannot be retrieved.</returns>
private static string GetMacAddress()
{
try
{
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in interfaces)
{
if (adapter.OperationalStatus == OperationalStatus.Up)
{
string macAddress = adapter.GetPhysicalAddress().ToString();
if (!string.IsNullOrEmpty(macAddress))
{
return macAddress;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error retrieving MAC address: {ex.Message}");
}
return null; // Return null if the MAC address cannot be retrieved
}
/// <summary>
/// Retrieves the BIOS UUID of the machine using WMI.
/// </summary>
/// <returns>The BIOS UUID, or null if the UUID cannot be retrieved.</returns>
private static string GetBiosUuid()
{
try
{
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct"))
{
foreach (ManagementObject wmi_HD in searcher.Get())
{
if (wmi_HD["UUID"] != null)
{
string uuid = wmi_HD["UUID"].ToString().Trim();
if (!string.IsNullOrEmpty(uuid))
{
return uuid;
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error retrieving BIOS UUID: {ex.Message}");
}
return null; // Return null if the BIOS UUID cannot be retrieved
}
}
}

View File

@@ -4,13 +4,8 @@ using mRemoteNG.Connection;
namespace mRemoteNG.Config.Putty
{
public class PuttySessionChangedEventArgs : EventArgs
public class PuttySessionChangedEventArgs(PuttySessionInfo sessionChanged = null) : EventArgs
{
public PuttySessionInfo Session { get; set; }
public PuttySessionChangedEventArgs(PuttySessionInfo sessionChanged = null)
{
Session = sessionChanged;
}
public PuttySessionInfo Session { get; set; } = sessionChanged;
}
}

View File

@@ -135,17 +135,17 @@ namespace mRemoteNG.Config.Putty
{
public static string[] Names => Instance.GetSessionNames();
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext? context)
{
return new StandardValuesCollection(Names);
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context)
{
return true;
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
public override bool GetStandardValuesSupported(ITypeDescriptorContext? context)
{
return true;
}

View File

@@ -113,8 +113,10 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
: "";
connectionRecord.Password = headers.Contains("Password")
? connectionCsv[headers.IndexOf("Password")].ConvertToSecureString()
: "".ConvertToSecureString();
// ? connectionCsv[headers.IndexOf("Password")].ConvertToSecureString()
// : "".ConvertToSecureString();
? connectionCsv[headers.IndexOf("Password")]
: "";
connectionRecord.Domain = headers.Contains("Domain")
? connectionCsv[headers.IndexOf("Domain")]
@@ -166,6 +168,11 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
? connectionCsv[headers.IndexOf("UserField")]
: "";
connectionRecord.EnvironmentTags =
headers.Contains("EnvironmentTags")
? connectionCsv[headers.IndexOf("EnvironmentTags")]
: "";
connectionRecord.ExtApp = headers.Contains("ExtApp")
? connectionCsv[headers.IndexOf("ExtApp")] : "";
@@ -775,6 +782,12 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
connectionRecord.Inheritance.UserField = value;
}
if (headers.Contains("InheritEnvironmentTags"))
{
if (bool.TryParse(connectionCsv[headers.IndexOf("InheritEnvironmentTags")], out bool value))
connectionRecord.Inheritance.EnvironmentTags = value;
}
if (headers.Contains("InheritFavorite"))
{
if (bool.TryParse(connectionCsv[headers.IndexOf("InheritFavorite")], out bool value))

View File

@@ -50,7 +50,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
private void WriteCsvHeader(StringBuilder sb)
{
sb.Append("Name;Id;Parent;NodeType;Description;Icon;Panel;");
sb.Append("Name;Id;Parent;NodeType;Description;Icon;Panel;TabColor;ConnectionFrameColor;");
if (_saveFilter.SaveUsername)
sb.Append("Username;");
if (_saveFilter.SavePassword)
@@ -61,18 +61,18 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
sb.Append("Hostname;Port;VmId;Protocol;SSHTunnelConnectionName;OpeningCommand;SSHOptions;PuttySession;ConnectToConsole;UseCredSsp;UseRestrictedAdmin;UseRCG;UseVmId;UseEnhancedMode;RenderingEngine;RDPAuthenticationLevel;" +
"LoadBalanceInfo;Colors;Resolution;AutomaticResize;DisplayWallpaper;DisplayThemes;EnableFontSmoothing;EnableDesktopComposition;DisableFullWindowDrag;DisableMenuAnimations;DisableCursorShadow;DisableCursorBlinking;" +
"CacheBitmaps;RedirectDiskDrives;RedirectDiskDrivesCustomRedirectPorts;RedirectPrinters;RedirectClipboard;RedirectSmartCards;RedirectSound;RedirectKeys;" +
"PreExtApp;PostExtApp;MacAddress;UserField;ExtApp;Favorite;VNCCompression;VNCEncoding;VNCAuthMode;VNCProxyType;VNCProxyIP;" +
"PreExtApp;PostExtApp;MacAddress;UserField;EnvironmentTags;ExtApp;Favorite;VNCCompression;VNCEncoding;VNCAuthMode;VNCProxyType;VNCProxyIP;" +
"VNCProxyPort;VNCProxyUsername;VNCProxyPassword;VNCColors;VNCSmartSizeMode;VNCViewOnly;RDGatewayUsageMethod;RDGatewayHostname;" +
"RDGatewayUseConnectionCredentials;RDGatewayUsername;RDGatewayPassword;RDGatewayDomain;RDGatewayExternalCredentialProvider;RDGatewayUserViaAPI;RedirectAudioCapture;RdpVersion;RDPStartProgram;RDPStartProgramWorkDir;UserViaAPI;EC2InstanceId;EC2Region;ExternalCredentialProvider;ExternalAddressProvider;");
if (_saveFilter.SaveInheritance)
sb.Append("InheritCacheBitmaps;InheritColors;InheritDescription;InheritDisplayThemes;InheritDisplayWallpaper;" +
"InheritEnableFontSmoothing;InheritEnableDesktopComposition;InheritDisableFullWindowDrag;InheritDisableMenuAnimations;InheritDisableCursorShadow;InheritDisableCursorBlinking;InheritDomain;InheritIcon;InheritPanel;InheritPassword;InheritPort;" +
"InheritEnableFontSmoothing;InheritEnableDesktopComposition;InheritDisableFullWindowDrag;InheritDisableMenuAnimations;InheritDisableCursorShadow;InheritDisableCursorBlinking;InheritDomain;InheritIcon;InheritPanel;InheritTabColor;InheritConnectionFrameColor;InheritPassword;InheritPort;" +
"InheritProtocol;InheritSSHTunnelConnectionName;InheritOpeningCommand;InheritSSHOptions;InheritPuttySession;InheritRedirectDiskDrives;InheritRedirectDiskDrivesCustom;InheritRedirectKeys;InheritRedirectPorts;InheritRedirectPrinters;" +
"InheritRedirectClipboard;InheritRedirectSmartCards;InheritRedirectSound;InheritResolution;InheritAutomaticResize;" +
"InheritUseConsoleSession;InheritUseCredSsp;InheritUseRestrictedAdmin;InheritUseRCG;InheritUseVmId;InheritUseEnhancedMode;InheritVmId;InheritRenderingEngine;InheritUsername;" +
"InheritRDPAuthenticationLevel;InheritLoadBalanceInfo;InheritPreExtApp;InheritPostExtApp;InheritMacAddress;InheritUserField;" +
"InheritFavorite;InheritExtApp;InheritVNCCompression;InheritVNCEncoding;InheritVNCAuthMode;InheritVNCProxyType;InheritVNCProxyIP;" +
"InheritEnvironmentTags;InheritFavorite;InheritExtApp;InheritVNCCompression;InheritVNCEncoding;InheritVNCAuthMode;InheritVNCProxyType;InheritVNCProxyIP;" +
"InheritVNCProxyPort;InheritVNCProxyUsername;InheritVNCProxyPassword;InheritVNCColors;InheritVNCSmartSizeMode;InheritVNCViewOnly;" +
"InheritRDGatewayUsageMethod;InheritRDGatewayHostname;InheritRDGatewayUseConnectionCredentials;InheritRDGatewayUsername;" +
"InheritRDGatewayPassword;InheritRDGatewayDomain;InheritRDGatewayExternalCredentialProvider;InheritRDGatewayUserViaAPI;InheritRDPAlertIdleTimeout;InheritRDPMinutesToIdleTimeout;InheritSoundQuality;InheritUserViaAPI;" +
@@ -106,13 +106,16 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
.Append(FormatForCsv(con.GetTreeNodeType()))
.Append(FormatForCsv(con.Description))
.Append(FormatForCsv(con.Icon))
.Append(FormatForCsv(con.Panel));
.Append(FormatForCsv(con.Panel))
.Append(FormatForCsv(con.TabColor))
.Append(FormatForCsv(con.ConnectionFrameColor));
if (_saveFilter.SaveUsername)
sb.Append(FormatForCsv(con.Username));
if (_saveFilter.SavePassword)
sb.Append(con.Password?.ConvertToUnsecureString() + ";");
//sb.Append(con.Password?.ConvertToUnsecureString() + ";");
sb.Append(con.Password + ";");
if (_saveFilter.SaveDomain)
sb.Append(FormatForCsv(con.Domain));
@@ -158,6 +161,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
.Append(FormatForCsv(con.PostExtApp))
.Append(FormatForCsv(con.MacAddress))
.Append(FormatForCsv(con.UserField))
.Append(FormatForCsv(con.EnvironmentTags))
.Append(FormatForCsv(con.ExtApp))
.Append(FormatForCsv(con.Favorite))
.Append(FormatForCsv(con.VNCCompression))
@@ -208,6 +212,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
.Append(FormatForCsv(con.Inheritance.Domain))
.Append(FormatForCsv(con.Inheritance.Icon))
.Append(FormatForCsv(con.Inheritance.Panel))
.Append(FormatForCsv(con.Inheritance.TabColor))
.Append(FormatForCsv(con.Inheritance.ConnectionFrameColor))
.Append(FormatForCsv(con.Inheritance.Password))
.Append(FormatForCsv(con.Inheritance.Port))
.Append(FormatForCsv(con.Inheritance.Protocol))
@@ -240,6 +246,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
.Append(FormatForCsv(con.Inheritance.PostExtApp))
.Append(FormatForCsv(con.Inheritance.MacAddress))
.Append(FormatForCsv(con.Inheritance.UserField))
.Append(FormatForCsv(con.Inheritance.EnvironmentTags))
.Append(FormatForCsv(con.Inheritance.Favorite))
.Append(FormatForCsv(con.Inheritance.ExtApp))
.Append(FormatForCsv(con.Inheritance.VNCCompression))

View File

@@ -131,7 +131,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv.RemoteDesktopMa
Hostname = hostString,
Port = port,
Username = username,
Password = password?.ConvertToSecureString(),
//Password = password?.ConvertToSecureString(),
Password = password,
Domain = domain,
Icon = connectionType.IconName ?? "mRemoteNG",
Description = description,

View File

@@ -21,16 +21,10 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
{
[SupportedOSPlatform("windows")]
public class DataTableDeserializer : IDeserializer<DataTable, ConnectionTreeModel>
public class DataTableDeserializer(ICryptographyProvider cryptographyProvider, SecureString decryptionKey) : IDeserializer<DataTable, ConnectionTreeModel>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _decryptionKey;
public DataTableDeserializer(ICryptographyProvider cryptographyProvider, SecureString decryptionKey)
{
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
_decryptionKey = decryptionKey.ThrowIfNull(nameof(decryptionKey));
}
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
private readonly SecureString _decryptionKey = decryptionKey.ThrowIfNull(nameof(decryptionKey));
public ConnectionTreeModel Deserialize(DataTable table)
{
@@ -113,7 +107,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
connectionInfo.OpeningCommand = (string)dataRow["OpeningCommand"];
connectionInfo.Panel = (string)dataRow["Panel"];
var pw = dataRow["Password"] as string;
connectionInfo.Password = DecryptValue(pw ?? "").ConvertToSecureString();
//connectionInfo.Password = DecryptValue(pw ?? "").ConvertToSecureString();
connectionInfo.Password = DecryptValue(pw ?? "");
connectionInfo.Port = (int)dataRow["Port"];
connectionInfo.PostExtApp = (string)dataRow["PostExtApp"];
connectionInfo.PreExtApp = (string)dataRow["PreExtApp"];
@@ -150,6 +145,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
connectionInfo.UseRCG = MiscTools.GetBooleanValue(dataRow["UseRCG"]);
connectionInfo.UseRestrictedAdmin = MiscTools.GetBooleanValue(dataRow["UseRestrictedAdmin"]);
connectionInfo.UserField = (string)dataRow["UserField"];
connectionInfo.EnvironmentTags = dataRow.Table.Columns.Contains("EnvironmentTags") ? (string)dataRow["EnvironmentTags"] : "";
connectionInfo.Username = (string)dataRow["Username"];
connectionInfo.UseVmId = MiscTools.GetBooleanValue(dataRow["UseVmId"]);
connectionInfo.VmId = (string)dataRow["VmId"];
@@ -229,6 +225,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
connectionInfo.Inheritance.UseRCG = MiscTools.GetBooleanValue(dataRow["InheritUseRCG"]);
connectionInfo.Inheritance.UseRestrictedAdmin = MiscTools.GetBooleanValue(dataRow["InheritUseRestrictedAdmin"]);
connectionInfo.Inheritance.UserField = MiscTools.GetBooleanValue(dataRow["InheritUserField"]);
if (dataRow.Table.Columns.Contains("InheritEnvironmentTags"))
connectionInfo.Inheritance.EnvironmentTags = MiscTools.GetBooleanValue(dataRow["InheritEnvironmentTags"]);
connectionInfo.Inheritance.Username = MiscTools.GetBooleanValue(dataRow["InheritUsername"]);
connectionInfo.Inheritance.UseVmId = MiscTools.GetBooleanValue(dataRow["InheritUseVmId"]);
connectionInfo.Inheritance.VmId = MiscTools.GetBooleanValue(dataRow["InheritVmId"]);

View File

@@ -14,27 +14,20 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
{
[SupportedOSPlatform("windows")]
public class DataTableSerializer : ISerializer<ConnectionInfo, DataTable>
public class DataTableSerializer(SaveFilter saveFilter, ICryptographyProvider cryptographyProvider, SecureString encryptionKey) : ISerializer<ConnectionInfo, DataTable>
{
private const int DELETE = 0;
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _encryptionKey;
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
private readonly SecureString _encryptionKey = encryptionKey.ThrowIfNull(nameof(encryptionKey));
private DataTable _dataTable;
private DataTable _sourceDataTable;
private readonly Dictionary<string, int> _sourcePrimaryKeyDict = [];
private const string TABLE_NAME = "tblCons";
private readonly SaveFilter _saveFilter;
private readonly SaveFilter _saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
private int _currentNodeIndex;
public Version Version { get; } = new Version(3, 0);
public DataTableSerializer(SaveFilter saveFilter, ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
{
_saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
_encryptionKey = encryptionKey.ThrowIfNull(nameof(encryptionKey));
}
public void SetSourceDataTable(DataTable sourceDataTable)
{
_sourceDataTable = sourceDataTable;
@@ -184,6 +177,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataTable.Columns.Add("InheritUseRestrictedAdmin", typeof(bool));
dataTable.Columns.Add("InheritUseVmId", typeof(bool));
dataTable.Columns.Add("InheritUserField", typeof(bool));
dataTable.Columns.Add("InheritEnvironmentTags", typeof(bool));
dataTable.Columns.Add("InheritUserViaAPI", typeof(bool));
dataTable.Columns.Add("InheritUsername", typeof(bool));
dataTable.Columns.Add("InheritVNCAuthMode", typeof(bool));
@@ -247,6 +241,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataTable.Columns.Add("UseRestrictedAdmin", typeof(bool));
dataTable.Columns.Add("UseVmId", typeof(bool));
dataTable.Columns.Add("UserField", typeof(string));
dataTable.Columns.Add("EnvironmentTags", typeof(string));
dataTable.Columns.Add("UserViaAPI", typeof(string));
dataTable.Columns.Add("Username", typeof(string));
dataTable.Columns.Add("VNCAuthMode", typeof(string));
@@ -519,7 +514,10 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["InheritVNCViewOnly"].Equals(false);
}
bool pwd = dataRow["Password"].Equals(_saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "") &&
//bool pwd = dataRow["Password"].Equals(_saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "") &&
// dataRow["VNCProxyPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey)) &&
// dataRow["RDGatewayPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey));
bool pwd = dataRow["Password"].Equals(_saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey) : "") &&
dataRow["VNCProxyPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey)) &&
dataRow["RDGatewayPassword"].Equals(_cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey));
return !(pwd && isFieldNotChange && isInheritanceFieldNotChange);
@@ -572,10 +570,11 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["MacAddress"] = connectionInfo.MacAddress;
dataRow["Name"] = connectionInfo.Name;
dataRow["OpeningCommand"] = connectionInfo.OpeningCommand;
dataRow["OpeningCommand"] = connectionInfo.OpeningCommand;
// dataRow["OpeningCommand"] = connectionInfo.OpeningCommand; dublicate?
dataRow["Panel"] = connectionInfo.Panel;
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
dataRow["Password"] = _saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "";
//dataRow["Password"] = _saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey) : "";
dataRow["Password"] = _saveFilter.SavePassword ? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey) : "";
dataRow["Port"] = connectionInfo.Port;
dataRow["PositionID"] = _currentNodeIndex;
dataRow["PostExtApp"] = connectionInfo.PostExtApp;
@@ -615,6 +614,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["UseRestrictedAdmin"] = connectionInfo.UseRestrictedAdmin;
dataRow["UseVmId"] = connectionInfo.UseVmId;
dataRow["UserField"] = connectionInfo.UserField;
dataRow["EnvironmentTags"] = connectionInfo.EnvironmentTags;
dataRow["Username"] = _saveFilter.SaveUsername ? connectionInfo.Username : "";
dataRow["VNCAuthMode"] = connectionInfo.VNCAuthMode;
dataRow["VNCColors"] = connectionInfo.VNCColors;
@@ -693,6 +693,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["InheritUseRestrictedAdmin"] = connectionInfo.Inheritance.UseRestrictedAdmin;
dataRow["InheritUseVmId"] = connectionInfo.Inheritance.UseVmId;
dataRow["InheritUserField"] = connectionInfo.Inheritance.UserField;
dataRow["InheritEnvironmentTags"] = connectionInfo.Inheritance.EnvironmentTags;
dataRow["InheritUserViaAPI"] = connectionInfo.Inheritance.UserViaAPI;
dataRow["InheritUsername"] = connectionInfo.Inheritance.Username;
dataRow["InheritVNCAuthMode"] = connectionInfo.Inheritance.VNCAuthMode;
@@ -770,6 +771,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
dataRow["InheritUseRCG"] = false;
dataRow["InheritUseRestrictedAdmin"] = false;
dataRow["InheritUserField"] = false;
dataRow["InheritEnvironmentTags"] = false;
dataRow["InheritUserViaAPI"] = false;
dataRow["InheritUsername"] = false;
dataRow["InheritVNCAuthMode"] = false;

View File

@@ -99,9 +99,22 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
if (rootTreeNode != null)
{
cmd = databaseConnector.DbCommand(
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES('" +
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "', 0, '" + strProtected + "','" +
ConnectionsFileInfo.ConnectionFileVersion + "')");
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(@Name, 0, @Protected, @ConfVersion)");
DbParameter nameParam = cmd.CreateParameter();
nameParam.ParameterName = "@Name";
nameParam.Value = rootTreeNode.Name;
cmd.Parameters.Add(nameParam);
DbParameter protectedParam = cmd.CreateParameter();
protectedParam.ParameterName = "@Protected";
protectedParam.Value = strProtected;
cmd.Parameters.Add(protectedParam);
DbParameter confVersionParam = cmd.CreateParameter();
confVersionParam.ParameterName = "@ConfVersion";
confVersionParam.Value = ConnectionsFileInfo.ConnectionFileVersion.ToString();
cmd.Parameters.Add(confVersionParam);
cmd.ExecuteNonQuery();
}
@@ -111,6 +124,22 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
}
}
private bool IsValidTableName(string tableName)
{
// Table names should only contain alphanumeric characters and underscores
// This prevents SQL injection when table names must be used directly in queries
if (string.IsNullOrWhiteSpace(tableName))
return false;
foreach (char c in tableName)
{
if (!char.IsLetterOrDigit(c) && c != '_')
return false;
}
return true;
}
private bool DoesDbTableExist(IDatabaseConnector databaseConnector, string tableName)
{
bool exists;
@@ -119,7 +148,18 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
{
// ANSI SQL way. Works in PostgreSQL, MSSQL, MySQL.
string database_name = Properties.OptionsDBsPage.Default.SQLDatabaseName;
DbCommand cmd = databaseConnector.DbCommand("select case when exists((select * from information_schema.tables where table_name = '" + tableName + "' and table_schema='"+ database_name + "')) then 1 else 0 end");
DbCommand cmd = databaseConnector.DbCommand("select case when exists((select * from information_schema.tables where table_name = @TableName and table_schema = @DatabaseName)) then 1 else 0 end");
DbParameter tableNameParam = cmd.CreateParameter();
tableNameParam.ParameterName = "@TableName";
tableNameParam.Value = tableName;
cmd.Parameters.Add(tableNameParam);
DbParameter databaseNameParam = cmd.CreateParameter();
databaseNameParam.ParameterName = "@DatabaseName";
databaseNameParam.Value = database_name;
cmd.Parameters.Add(databaseNameParam);
short cmdResult = Convert.ToInt16(cmd.ExecuteScalar());
exists = (cmdResult == 1);
}
@@ -128,9 +168,18 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Sql
try
{
// Other RDBMS. Graceful degradation
exists = true;
DbCommand cmdOthers = databaseConnector.DbCommand("select 1 from " + tableName + " where 1 = 0");
cmdOthers.ExecuteNonQuery();
// Note: Table names cannot be parameterized in standard SQL.
// Validate tableName to prevent SQL injection
if (!IsValidTableName(tableName))
{
exists = false;
}
else
{
exists = true;
DbCommand cmdOthers = databaseConnector.DbCommand($"select 1 from {tableName} where 1 = 0");
cmdOthers.ExecuteNonQuery();
}
}
catch
{

View File

@@ -61,7 +61,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
//element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));

View File

@@ -11,23 +11,16 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
// ReSharper disable once InconsistentNaming
[SupportedOSPlatform("windows")]
public class XmlConnectionNodeSerializer27 : ISerializer<ConnectionInfo, XElement>
public class XmlConnectionNodeSerializer27(ICryptographyProvider cryptographyProvider,
SecureString encryptionKey,
SaveFilter saveFilter) : ISerializer<ConnectionInfo, XElement>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _encryptionKey;
private readonly SaveFilter _saveFilter;
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
private readonly SecureString _encryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
private readonly SaveFilter _saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
public Version Version { get; } = new Version(2, 7);
public XmlConnectionNodeSerializer27(ICryptographyProvider cryptographyProvider,
SecureString encryptionKey,
SaveFilter saveFilter)
{
_cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
_encryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
_saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
}
public XElement Serialize(ConnectionInfo connectionInfo)
{
XElement element = new(XName.Get("Node", ""));
@@ -62,7 +55,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
//element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password.ConvertToUnsecureString(), _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));
}

View File

@@ -11,23 +11,16 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
// ReSharper disable once InconsistentNaming
[SupportedOSPlatform("windows")]
public class XmlConnectionNodeSerializer28 : ISerializer<ConnectionInfo, XElement>
public class XmlConnectionNodeSerializer28(ICryptographyProvider cryptographyProvider,
SecureString encryptionKey,
SaveFilter saveFilter) : ISerializer<ConnectionInfo, XElement>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _encryptionKey;
private readonly SaveFilter _saveFilter;
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
private readonly SecureString _encryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
private readonly SaveFilter _saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
public Version Version { get; } = new Version(2, 8);
public XmlConnectionNodeSerializer28(ICryptographyProvider cryptographyProvider,
SecureString encryptionKey,
SaveFilter saveFilter)
{
_cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
_encryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
_saveFilter = saveFilter ?? throw new ArgumentNullException(nameof(saveFilter));
}
public XElement Serialize(ConnectionInfo connectionInfo)
{
XElement element = new(XName.Get("Node", ""));
@@ -49,6 +42,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
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("TabColor", connectionInfo.TabColor));
element.Add(new XAttribute("ConnectionFrameColor", connectionInfo.ConnectionFrameColor));
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
if (!Runtime.UseCredentialManager)
@@ -62,7 +57,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey)));
//element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password?.ConvertToUnsecureString(), _encryptionKey)));
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));
}
@@ -109,6 +105,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("PostExtApp", connectionInfo.PostExtApp));
element.Add(new XAttribute("MacAddress", connectionInfo.MacAddress));
element.Add(new XAttribute("UserField", connectionInfo.UserField));
element.Add(new XAttribute("EnvironmentTags", connectionInfo.EnvironmentTags));
element.Add(new XAttribute("Favorite", connectionInfo.Favorite));
element.Add(new XAttribute("ExtApp", connectionInfo.ExtApp));
element.Add(new XAttribute("StartProgram", connectionInfo.RDPStartProgram));
@@ -157,6 +154,11 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("EC2Region", connectionInfo.EC2Region));
element.Add(new XAttribute("ExternalCredentialProvider", connectionInfo.ExternalCredentialProvider));
element.Add(new XAttribute("ExternalAddressProvider", connectionInfo.ExternalAddressProvider));
// Vault/OpenBao specific
element.Add(new XAttribute("VaultOpenbaoMount", connectionInfo.VaultOpenbaoMount ?? string.Empty));
element.Add(new XAttribute("VaultOpenbaoRole", connectionInfo.VaultOpenbaoRole ?? string.Empty));
element.Add(new XAttribute("VaultOpenbaoSecretEngine", connectionInfo.VaultOpenbaoSecretEngine));
}
private void SetInheritanceAttributes(XContainer element, IInheritable connectionInfo)
@@ -193,6 +195,10 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("InheritIcon", inheritance.Icon.ToString().ToLowerInvariant()));
if (inheritance.Panel)
element.Add(new XAttribute("InheritPanel", inheritance.Panel.ToString().ToLowerInvariant()));
if (inheritance.TabColor)
element.Add(new XAttribute("InheritTabColor", inheritance.TabColor.ToString().ToLowerInvariant()));
if (inheritance.ConnectionFrameColor)
element.Add(new XAttribute("InheritConnectionFrameColor", inheritance.ConnectionFrameColor.ToString().ToLowerInvariant()));
if (inheritance.Password)
element.Add(new XAttribute("InheritPassword", inheritance.Password.ToString().ToLowerInvariant()));
if (inheritance.Port)
@@ -257,6 +263,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("InheritMacAddress", inheritance.MacAddress.ToString().ToLowerInvariant()));
if (inheritance.UserField)
element.Add(new XAttribute("InheritUserField", inheritance.UserField.ToString().ToLowerInvariant()));
if (inheritance.EnvironmentTags)
element.Add(new XAttribute("InheritEnvironmentTags", inheritance.EnvironmentTags.ToString().ToLowerInvariant()));
if (inheritance.Favorite)
element.Add(new XAttribute("InheritFavorite", inheritance.Favorite.ToString().ToLowerInvariant()));
if (inheritance.ExtApp)

View File

@@ -94,8 +94,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connections = _decryptor.LegacyFullFileDecrypt(connections);
if (connections != "")
{
_xmlDocument = new XmlDocument();
_xmlDocument.LoadXml(connections);
_xmlDocument = SecureXmlHelper.LoadXmlFromString(connections);
}
}
@@ -120,8 +119,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
private void InitializeRootNode(XmlElement connectionsRootElement)
{
string rootNodeName = connectionsRootElement?.Attributes["Name"]?.Value.Trim();
_rootNodeInfo.Name = rootNodeName;
_rootNodeInfo.Name = connectionsRootElement?.Attributes["Name"]?.Value.Trim();
}
private void CreateDecryptor(RootNodeInfo rootNodeInfo, XmlElement connectionsRootElement = null)
@@ -217,8 +215,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
if (!Runtime.UseCredentialManager || _confVersion <= 2.6) // 0.2 - 2.6
{
connectionInfo.Username = xmlnode.GetAttributeAsString("Username");
//connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password"));
connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password")).ConvertToSecureString();
connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password"));
//connectionInfo.Password = _decryptor.Decrypt(xmlnode.GetAttributeAsString("Password")).ConvertToSecureString();
connectionInfo.Domain = xmlnode.GetAttributeAsString("Domain");
}
}
@@ -329,6 +327,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.Inheritance.DisplayWallpaper = xmlnode.GetAttributeAsBool("InheritDisplayWallpaper");
connectionInfo.Inheritance.Icon = xmlnode.GetAttributeAsBool("InheritIcon");
connectionInfo.Inheritance.Panel = xmlnode.GetAttributeAsBool("InheritPanel");
connectionInfo.Inheritance.TabColor = xmlnode.GetAttributeAsBool("InheritTabColor");
connectionInfo.Inheritance.ConnectionFrameColor = xmlnode.GetAttributeAsBool("InheritConnectionFrameColor");
connectionInfo.Inheritance.Port = xmlnode.GetAttributeAsBool("InheritPort");
connectionInfo.Inheritance.Protocol = xmlnode.GetAttributeAsBool("InheritProtocol");
connectionInfo.Inheritance.PuttySession = xmlnode.GetAttributeAsBool("InheritPuttySession");
@@ -351,6 +351,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.Icon = xmlnode.GetAttributeAsString("Icon");
connectionInfo.Panel = xmlnode.GetAttributeAsString("Panel");
connectionInfo.TabColor = xmlnode.GetAttributeAsString("TabColor");
connectionInfo.ConnectionFrameColor = xmlnode.GetAttributeAsEnum<ConnectionFrameColor>("ConnectionFrameColor");
}
else
{
@@ -516,6 +518,9 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.UserViaAPI = xmlnode.GetAttributeAsString("UserViaAPI");
connectionInfo.Inheritance.UserViaAPI = xmlnode.GetAttributeAsBool("InheritUserViaAPI");
connectionInfo.ExternalAddressProvider = xmlnode.GetAttributeAsEnum("ExternalAddressProvider", ExternalAddressProvider.None);
connectionInfo.VaultOpenbaoMount = xmlnode.GetAttributeAsString("VaultOpenbaoMount");
connectionInfo.VaultOpenbaoRole = xmlnode.GetAttributeAsString("VaultOpenbaoRole");
connectionInfo.VaultOpenbaoSecretEngine = xmlnode.GetAttributeAsEnum("VaultOpenbaoSecretEngine", VaultOpenbaoSecretEngine.Kv);
connectionInfo.EC2InstanceId = xmlnode.GetAttributeAsString("EC2InstanceId");
connectionInfo.EC2Region = xmlnode.GetAttributeAsString("EC2Region");
connectionInfo.UseRestrictedAdmin = xmlnode.GetAttributeAsBool("UseRestrictedAdmin");
@@ -534,6 +539,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.RedirectDiskDrives = xmlnode.GetAttributeAsEnum<RDPDiskDrives>("RedirectDiskDrives");
connectionInfo.RedirectDiskDrivesCustom = xmlnode.GetAttributeAsString("RedirectDiskDrivesCustom");
connectionInfo.Inheritance.RedirectDiskDrivesCustom = xmlnode.GetAttributeAsBool("InheritRedirectDiskDrivesCustom");
connectionInfo.EnvironmentTags = xmlnode.GetAttributeAsString("EnvironmentTags");
connectionInfo.Inheritance.EnvironmentTags = xmlnode.GetAttributeAsBool("InheritEnvironmentTags");
break;
case >= 0.5:

View File

@@ -12,17 +12,11 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
[SupportedOSPlatform("windows")]
public class XmlConnectionsDocumentCompiler
public class XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, ISerializer<ConnectionInfo, XElement> connectionNodeSerializer)
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
private SecureString _encryptionKey;
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer;
public XmlConnectionsDocumentCompiler(ICryptographyProvider cryptographyProvider, ISerializer<ConnectionInfo, XElement> connectionNodeSerializer)
{
_cryptographyProvider = cryptographyProvider ?? throw new ArgumentNullException(nameof(cryptographyProvider));
_connectionNodeSerializer = connectionNodeSerializer ?? throw new ArgumentNullException(nameof(connectionNodeSerializer));
}
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer = connectionNodeSerializer ?? throw new ArgumentNullException(nameof(connectionNodeSerializer));
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption)
{

View File

@@ -4,14 +4,9 @@ using mRemoteNG.Security;
namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
public class XmlConnectionsDocumentEncryptor
public class XmlConnectionsDocumentEncryptor(ICryptographyProvider cryptographyProvider)
{
private readonly ICryptographyProvider _cryptographyProvider;
public XmlConnectionsDocumentEncryptor(ICryptographyProvider cryptographyProvider)
{
_cryptographyProvider = cryptographyProvider;
}
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider;
public XDocument EncryptDocument(XDocument documentToEncrypt, SecureString encryptionKey)
{

View File

@@ -14,22 +14,16 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
{
[SupportedOSPlatform("windows")]
public class XmlConnectionsSerializer : ISerializer<ConnectionTreeModel, string>,
public class XmlConnectionsSerializer(ICryptographyProvider cryptographyProvider,
ISerializer<ConnectionInfo, XElement> connectionNodeSerializer) : ISerializer<ConnectionTreeModel, string>,
ISerializer<ConnectionInfo, string>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer;
private readonly ICryptographyProvider _cryptographyProvider = cryptographyProvider;
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer = connectionNodeSerializer;
public Version Version => _connectionNodeSerializer.Version;
public bool UseFullEncryption { get; set; }
public XmlConnectionsSerializer(ICryptographyProvider cryptographyProvider,
ISerializer<ConnectionInfo, XElement> connectionNodeSerializer)
{
_cryptographyProvider = cryptographyProvider;
_connectionNodeSerializer = connectionNodeSerializer;
}
public string Serialize(ConnectionTreeModel connectionTreeModel)
{
RootNodeInfo rootNode = (RootNodeInfo)connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);

View File

@@ -28,7 +28,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider)
{
XAttribute attribute = new(XName.Get("Protected"), "");
string plainText = rootNodeInfo.Password ? "ThisIsProtected" : "ThisIsNotProtected";
string plainText = (rootNodeInfo.PasswordString != rootNodeInfo.DefaultPassword) ? "ThisIsProtected" : "ThisIsNotProtected";
System.Security.SecureString encryptionPassword = rootNodeInfo.PasswordString.ConvertToSecureString();
attribute.Value = cryptographyProvider.Encrypt(plainText, encryptionPassword);
return attribute;

View File

@@ -10,20 +10,54 @@ using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.Resources.Language;
using mRemoteNG.Security;
using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.MiscSerializers
{
[SupportedOSPlatform("windows")]
public class ActiveDirectoryDeserializer
public class ActiveDirectoryDeserializer(string ldapPath, bool importSubOu)
{
private readonly string _ldapPath;
private readonly bool _importSubOu;
private readonly string _ldapPath = SanitizeLdapPath(ldapPath.ThrowIfNullOrEmpty(nameof(ldapPath)));
private readonly bool _importSubOu = importSubOu;
public ActiveDirectoryDeserializer(string ldapPath, bool importSubOu)
private static string SanitizeLdapPath(string ldapPath)
{
_ldapPath = ldapPath.ThrowIfNullOrEmpty(nameof(ldapPath));
_importSubOu = importSubOu;
// Validate the LDAP path format
if (!LdapPathSanitizer.IsValidDistinguishedNameFormat(ldapPath))
{
throw new ArgumentException("Invalid LDAP path format", nameof(ldapPath));
}
// For LDAP paths (URIs like LDAP://...), we need to sanitize the DN portion
// If it starts with LDAP:// or LDAPS://, extract and sanitize the DN part
if (ldapPath.StartsWith("LDAP://", StringComparison.OrdinalIgnoreCase) ||
ldapPath.StartsWith("LDAPS://", StringComparison.OrdinalIgnoreCase))
{
int schemeEndIndex = ldapPath.IndexOf("://", StringComparison.OrdinalIgnoreCase) + 3;
if (schemeEndIndex < ldapPath.Length)
{
// Find the server/domain part (before the first /)
int pathStartIndex = ldapPath.IndexOf('/', schemeEndIndex);
if (pathStartIndex > 0)
{
string scheme = ldapPath.Substring(0, schemeEndIndex);
string serverPart = ldapPath.Substring(schemeEndIndex, pathStartIndex - schemeEndIndex);
string dnPart = ldapPath.Substring(pathStartIndex + 1);
// Sanitize the DN part
string sanitizedDn = LdapPathSanitizer.SanitizeDistinguishedName(dnPart);
return scheme + serverPart + "/" + sanitizedDn;
}
}
// If no DN part found, return the path as-is (just the server)
return ldapPath;
}
else
{
// For plain DN strings, sanitize directly
return LdapPathSanitizer.SanitizeDistinguishedName(ldapPath);
}
}
public ConnectionTreeModel Deserialize()

View File

@@ -10,14 +10,9 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.MiscSerializers
{
[SupportedOSPlatform("windows")]
public class PortScanDeserializer : IDeserializer<IEnumerable<ScanHost>, ConnectionTreeModel>
public class PortScanDeserializer(ProtocolType targetProtocolType) : IDeserializer<IEnumerable<ScanHost>, ConnectionTreeModel>
{
private readonly ProtocolType _targetProtocolType;
public PortScanDeserializer(ProtocolType targetProtocolType)
{
_targetProtocolType = targetProtocolType;
}
private readonly ProtocolType _targetProtocolType = targetProtocolType;
public ConnectionTreeModel Deserialize(IEnumerable<ScanHost> scannedHosts)
{
@@ -66,6 +61,10 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
if (host.Vnc)
finalProtocol = ProtocolType.VNC;
break;
case ProtocolType.ARD:
if (host.Vnc)
finalProtocol = ProtocolType.ARD;
break;
default:
protocolValid = false;
break;

View File

@@ -20,8 +20,7 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
RootNodeInfo root = new(RootNodeType.Connection);
connectionTreeModel.AddRootNode(root);
XmlDocument xmlDocument = new();
xmlDocument.LoadXml(puttycmConnectionsXml);
XmlDocument xmlDocument = SecureXmlHelper.LoadXmlFromString(puttycmConnectionsXml);
XmlNode configurationNode = xmlDocument.SelectSingleNode("/configuration");
@@ -134,7 +133,8 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
XmlNode loginNode = xmlNode.SelectSingleNode("./login");
connectionInfo.Username = loginNode?.SelectSingleNode("login")?.InnerText;
connectionInfo.Password = loginNode?.SelectSingleNode("password")?.InnerText.ConvertToSecureString();
//connectionInfo.Password = loginNode?.SelectSingleNode("password")?.InnerText.ConvertToSecureString();
connectionInfo.Password = loginNode?.SelectSingleNode("password")?.InnerText;
// ./prompt
// ./timeout/connectiontimeout

View File

@@ -101,6 +101,9 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
case "allow desktop composition":
connectionInfo.EnableDesktopComposition = value == "1";
break;
case "keyboardhook":
connectionInfo.RedirectKeys = value == "1";
break;
case "redirectsmartcards":
connectionInfo.RedirectSmartCards = value == "1";
break;
@@ -156,6 +159,34 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
case "gatewayhostname":
connectionInfo.RDGatewayHostname = value;
break;
case "gatewaycredentialssource":
switch(value)
{
case "0":
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.ExternalCredentialProvider;
break;
case "1":
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.SmartCard;
break;
case "2":
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.Yes;
break;
case "3":
// Both 3 and 4 require that the user enter gateway credentials manually
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.No;
break;
case "4":
// Both 3 and 4 require that the user enter gateway credentials manually
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.No;
break;
case "5":
connectionInfo.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.AccessToken;
break;
}
break;
case "gatewayaccesstoken":
connectionInfo.RDGatewayAccessToken = value;
break;
case "alternate shell":
connectionInfo.RDPStartProgram = value;
break;

View File

@@ -26,9 +26,7 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
ConnectionTreeModel connectionTreeModel = new();
RootNodeInfo root = new(RootNodeType.Connection);
XmlDocument xmlDocument = new();
xmlDocument.LoadXml(rdcmConnectionsXml);
XmlDocument xmlDocument = SecureXmlHelper.LoadXmlFromString(rdcmConnectionsXml);
XmlNode rdcManNode = xmlDocument.SelectSingleNode("/RDCMan");
VerifySchemaVersion(rdcManNode);
@@ -164,12 +162,15 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
if (_schemaVersion == 1) // Version 2.2 allows clear text passwords
{
connectionInfo.Password = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True"
? passwordNode.InnerText.ConvertToSecureString()
: DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
//? passwordNode.InnerText.ConvertToSecureString()
//: DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
? passwordNode.InnerText
: DecryptRdcManPassword(passwordNode?.InnerText);
}
else
{
connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
//connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText).ConvertToSecureString();
connectionInfo.Password = DecryptRdcManPassword(passwordNode?.InnerText);
}
connectionInfo.Domain = logonCredentialsNode.SelectSingleNode("./domain")?.InnerText ?? string.Empty;

View File

@@ -2,6 +2,7 @@
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using System;
@@ -22,8 +23,7 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
RootNodeInfo root = new(RootNodeType.Connection);
connectionTreeModel.AddRootNode(root);
XmlDocument xmlDocument = new();
xmlDocument.LoadXml(content);
XmlDocument xmlDocument = SecureXmlHelper.LoadXmlFromString(content);
XmlNode sessionsNode = xmlDocument.SelectSingleNode("/VanDyke/key[@name=\"Sessions\"]");

View File

@@ -9,16 +9,11 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlDatabaseVersionVerifier
public class SqlDatabaseVersionVerifier(IDatabaseConnector databaseConnector)
{
private readonly Version _currentSupportedVersion = new(3, 0);
private readonly IDatabaseConnector _databaseConnector;
public SqlDatabaseVersionVerifier(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool VerifyDatabaseVersion(Version dbVersion)
{

View File

@@ -7,14 +7,9 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion22To23Upgrader : IVersionUpgrader
public class SqlVersion22To23Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion22To23Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -7,14 +7,9 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion23To24Upgrader : IVersionUpgrader
public class SqlVersion23To24Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion23To24Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -7,14 +7,9 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion24To25Upgrader : IVersionUpgrader
public class SqlVersion24To25Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion24To25Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -7,14 +7,9 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion25To26Upgrader : IVersionUpgrader
public class SqlVersion25To26Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion25To26Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -2,20 +2,15 @@
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using System;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion26To27Upgrader : IVersionUpgrader
public class SqlVersion26To27Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion26To27Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -3,20 +3,15 @@ using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using System;
using System.Data.Common;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion27To28Upgrader : IVersionUpgrader
public class SqlVersion27To28Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion27To28Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -8,15 +8,10 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion28To29Upgrader : IVersionUpgrader
public class SqlVersion28To29Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly Version _version = new(2, 9);
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion28To29Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

View File

@@ -8,15 +8,10 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Config.Serializers.Versioning
{
[SupportedOSPlatform("windows")]
public class SqlVersion29To30Upgrader : IVersionUpgrader
public class SqlVersion29To30Upgrader(IDatabaseConnector databaseConnector) : IVersionUpgrader
{
private readonly Version _version = new(3, 0);
private readonly IDatabaseConnector _databaseConnector;
public SqlVersion29To30Upgrader(IDatabaseConnector databaseConnector)
{
_databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
}
private readonly IDatabaseConnector _databaseConnector = databaseConnector ?? throw new ArgumentNullException(nameof(databaseConnector));
public bool CanUpgrade(Version currentVersion)
{

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