Compare commits

...

137 Commits

Author SHA1 Message Date
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
155 changed files with 7379 additions and 6249 deletions

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

@@ -0,0 +1,136 @@
name: Build_and_Release_mR-NB
on:
push:
branches:
- v1.78.2-dev
permissions:
contents: write
jobs:
NB-Build-and-Release:
strategy:
matrix:
include:
- runner: windows-latest
platform: x64
arch: x64
- runner: windows-11-arm
platform: ARM64
arch: arm64
runs-on: ${{ matrix.runner }}
steps:
- name: (01) Checkout Repository
uses: actions/checkout@v4
- name: (02) Setup MSBuild
uses: microsoft/setup-msbuild@v2
with:
vs-version: '17.14.12'
- name: (03) Install and run dotnet-t4 to transform T4 templates
shell: pwsh
run: |
dotnet tool install --global dotnet-t4
$ttFile = "$env:GITHUB_WORKSPACE\mRemoteNG\Properties\AssemblyInfo.tt"
t4 $ttFile
- name: (04) Cache NuGet Packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-${{ matrix.arch }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-nuget-
- name: (05) Restore NuGet Packages
shell: pwsh
run: dotnet restore
- name: (06) Build Release
shell: pwsh
run: |
msbuild "$Env:GITHUB_WORKSPACE\mRemoteNG.sln" -p:Configuration="Release" -p:Platform=${{ matrix.platform }} /verbosity:minimal
- name: (07) 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 }}.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
$version = "${{ steps.version.outputs.version }}"
- name: (08) 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
echo "log=$escaped"
- name: (09) 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 }}"
- name: (10) Create release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ steps.version.outputs.tag }}
name: "mRemoteNG ${{ steps.version.outputs.version }} NB ${{ steps.version.outputs.build }}"
files: ${{ steps.version.outputs.zipname }}
body: |
Changes in this Release:
${{ steps.changelog.outputs.log }}
Last Commit Message:
${{ steps.version.outputs.message }}
draft: false
prerelease: true

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,24 @@
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
- #2715: Disable WinForms analyzers and suppress WFO1000 build errors for ObjectListView
- #2712: VNCEvent_Disconnected send the ProtocolBase based object reference
- #2668: fix ssh quickconnect exception
- #2611: correct registry path
- #2496: use pwfile instead of cleartext password for putty connections
### Added
- #2723: Read keyboardhook, gatewayaccesstoken and gatewaycredentialssource from RDP File
- #2690: தமிழ் (ta) Translation update
- #2643: Registry Settings: enhancements and new settings implementation
- #2591: add Clickstudios Passwordstate API connector
### Updated
- #2597: Remember the opened connection file on relaunch
- #2502: Updated Polish translation
## [1.77.3.1784]
### Fixed
- #2362: Fix use of sql database

104
Directory.Packages.props Normal file
View File

@@ -0,0 +1,104 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AWSSDK.Core" Version="4.0.0.22" />
<PackageVersion Include="AWSSDK.EC2" Version="4.0.30" />
<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="6.0.4" />
<PackageVersion Include="Cucumber.Messages" Version="28.1.0" />
<PackageVersion Include="DockPanelSuite" Version="3.1.1" />
<PackageVersion Include="DockPanelSuite.ThemeVS2015" Version="3.1.1" />
<PackageVersion Include="Gherkin" Version="32.1.0" />
<PackageVersion Include="Google.Protobuf" Version="3.32.0" />
<PackageVersion Include="LiteDB" Version="5.0.21" />
<PackageVersion Include="log4net" Version="3.1.0" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.1" />
<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.Configuration.UserSecrets" Version="9.0.8" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="9.0.4" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.NETCore.Platforms" Version="7.0.4" />
<PackageVersion Include="Microsoft.NETCore.Targets" Version="5.0.0" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3405.78" />
<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.4.0" />
<PackageVersion Include="NETStandard.Library" Version="2.0.3" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Newtonsoft.Json.Schema" Version="4.0.1" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NUnit" Version="4.3.2" />
<PackageVersion Include="NUnit.Console" Version="3.20.0" />
<PackageVersion Include="NUnit.ConsoleRunner" Version="3.20.0" />
<PackageVersion Include="NUnit.Extension.TeamCityEventListener" Version="1.0.10" />
<PackageVersion Include="NUnit.Runners" Version="3.12.0" />
<PackageVersion Include="NUnit3TestAdapter" Version="5.0.0" />
<PackageVersion Include="OpenCover" Version="4.7.1221" />
<PackageVersion Include="Renci.SshNet.Async" Version="1.4.0" />
<PackageVersion Include="ReportGenerator" Version="5.4.12" />
<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="SpecFlow" Version="3.9.74" />
<PackageVersion Include="SpecFlow.NUnit" Version="3.9.74" />
<PackageVersion Include="SSH.NET" Version="2025.0.0" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.8" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.8" />
<PackageVersion Include="System.Console" Version="4.3.1" />
<PackageVersion Include="System.Data.Common" Version="4.3.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="9.0.8" />
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.8" />
<PackageVersion Include="System.DirectoryServices" Version="9.0.8" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.8" />
<PackageVersion Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageVersion Include="System.Formats.Asn1" Version="9.0.8" />
<PackageVersion Include="System.IO.Pipelines" Version="9.0.8" />
<PackageVersion Include="System.Management" Version="9.0.8" />
<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="9.0.8" />
<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="9.0.8" />
<PackageVersion Include="System.Security.Cryptography.X509Certificates" Version="4.3.2" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.8" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.8" />
<PackageVersion Include="System.Text.Json" Version="9.0.8" />
<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="9.0.8" />
<PackageVersion Include="System.Xml.ReaderWriter" Version="4.3.1" />
<PackageVersion Include="VncSharpCore" Version="1.2.1" />
<PackageVersion Include="ZstdSharp.Port" Version="0.8.6" />
</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,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<UseWindowsForms>True</UseWindowsForms>
<Platforms>x64</Platforms>
<Platforms>x64;arm64</Platforms>
<Configurations>Debug;Release;Debug Portable;Release Portable;Deploy to github</Configurations>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion>10.0.26100.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Portable|x64'">
<Optimize>True</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Portable|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" />
</ItemGroup>
<ItemGroup>
<Compile Update="AWS\AWSConnectionForm.cs" />
<Compile Update="CPS\CPSConnectionForm.cs" />
<Compile Update="DSS\SSConnectionForm.cs" />
</ItemGroup>
</Project>

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>net9.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,8 @@
<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" />
<PackageReference Include="System.Drawing.Common" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" />
</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.

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>

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

@@ -175,7 +175,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 +199,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

View File

@@ -5,21 +5,6 @@ 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}"
@@ -27,54 +12,61 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|arm64 = Debug|arm64
Release Installer and Portable|x64 = Release Installer and Portable|x64
Release Installer and Portable|arm64 = Release Installer and Portable|arm64
Release|x64 = Release|x64
Release|arm64 = Release|arm64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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}.Debug|arm64.ActiveCfg = Debug|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|arm64.Build.0 = Debug|arm64
{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 Installer and Portable|arm64.ActiveCfg = Release Portable|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer and Portable|arm64.Build.0 = Release Portable|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
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|arm64.ActiveCfg = Release|arm64
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|arm64.Build.0 = Release|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}.Debug|arm64.ActiveCfg = Debug|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Debug|arm64.Build.0 = Debug|arm64
{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 Installer and Portable|arm64.ActiveCfg = Release Portable|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release Installer and Portable|arm64.Build.0 = Release Portable|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|x64.ActiveCfg = Release|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|x64.Build.0 = Release|x64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|arm64.ActiveCfg = Release|arm64
{A56A2029-79B8-492A-ABE5-D2BFE05801BD}.Release|arm64.Build.0 = Release|arm64
{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}.Debug|arm64.ActiveCfg = Debug|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Debug|arm64.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 Installer and Portable|arm64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release Installer and Portable|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
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|arm64.ActiveCfg = Release|Any CPU
{5718734C-03AC-4954-89B1-1723CF03AF10}.Release|arm64.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

@@ -54,8 +54,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

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

@@ -8,6 +8,7 @@ using System.Threading;
using System.Windows.Forms;
using mRemoteNG.Config.Settings;
using mRemoteNG.UI.Forms;
using System.Runtime.InteropServices;
namespace mRemoteNG.App
{
@@ -45,6 +46,28 @@ namespace mRemoteNG.App
//Subscribe to AssemblyResolve event
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
//Check if needed runtime is installed
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
string runtimeVersion = RuntimeInformation.FrameworkDescription;
if (runtimeVersion.Contains(".NET 9.0.2"))
{
Console.WriteLine(".NET Desktop Runtime 9.0.2 is already installed.");
}
else
{
Console.WriteLine(".NET Desktop Runtime 9.0.2 is not installed. Please download and install it from the following link:");
Console.WriteLine("https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-9.0.2-windows-x64-installer");
Console.WriteLine("After installation, please restart the application.");
}
}
else
{
Console.WriteLine("This application requires the .NET Desktop Runtime 9.0.2 on Windows.");
}
//Check if local settings DB exist or accessible
CheckLockalDB();
@@ -62,7 +85,7 @@ namespace mRemoteNG.App
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)
{

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

@@ -23,18 +23,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 = "")
{

View File

@@ -6,15 +6,10 @@ using mRemoteNG.App;
namespace mRemoteNG.Config.DataProviders
{
[SupportedOSPlatform("windows")]
public class FileDataProvider : IDataProvider<string>
public class FileDataProvider(string filePath) : IDataProvider<string>
{
[SupportedOSPlatform("windows")]
public string FilePath { get; set; }
public FileDataProvider(string filePath)
{
FilePath = filePath;
}
public string FilePath { get; set; } = filePath;
public virtual string Load()
{

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,148 @@
using System;
using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using LiteDB;
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($"Platform error: {ex.Message}");
return ConnectionTestResult.UnknownError;
}
catch (DllNotFoundException ex)
{
// Handle missing native dependencies
Console.WriteLine($"Missing dependency: {ex.Message}");
return ConnectionTestResult.UnknownError;
}
catch (BadImageFormatException ex)
{
// Handle architecture mismatch in native libraries
Console.WriteLine($"Architecture mismatch: {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")]

View File

@@ -112,7 +112,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Csv
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));

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"];

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;
@@ -519,7 +512,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 +568,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;

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

@@ -217,8 +217,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");
}
}

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

@@ -15,16 +15,10 @@ 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;
public ActiveDirectoryDeserializer(string ldapPath, bool importSubOu)
{
_ldapPath = ldapPath.ThrowIfNullOrEmpty(nameof(ldapPath));
_importSubOu = importSubOu;
}
private readonly string _ldapPath = ldapPath.ThrowIfNullOrEmpty(nameof(ldapPath));
private readonly bool _importSubOu = importSubOu;
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)
{

View File

@@ -134,7 +134,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

@@ -164,12 +164,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

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

View File

@@ -2,12 +2,14 @@
using System.IO;
using System.Collections.Generic;
using System.Text.Json;
using System.Management;
using JsonSerializer = System.Text.Json.JsonSerializer;
using LiteDB;
using System.Linq;
using LiteDB;
using mRemoteNG.Config.MachineIdentifier;
using System.Runtime.Versioning;
public class LocalSettingsDBManager
[SupportedOSPlatform("windows")]
public class LocalDBManager
{
private readonly string _dbPath;
private readonly string _schemaPath;
@@ -21,12 +23,31 @@ public class LocalSettingsDBManager
/// <param name="dbPath">The path to the database file.</param>
/// <param name="useEncryption">Indicates whether to use encryption for the database. If null, no change is made to an existing database.</param>
/// <param name="schemaFilePath">Optional path to a schema file for creating the database structure.</param>
public LocalSettingsDBManager(string dbPath = null, bool? useEncryption = null, string schemaFilePath = null)
public LocalDBManager(string dbPath = null, bool? useEncryption = null, string schemaFilePath = null)
{
_dbPath = string.IsNullOrWhiteSpace(dbPath) ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mRemoteNG.appSettings") : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dbPath);
_schemaPath = string.IsNullOrWhiteSpace(schemaFilePath) ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Schemas\\mremoteng_default_settings_v1_0.json") : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, schemaFilePath);
_useEncryption = useEncryption;
_mRIdentifier = Convert.ToBase64String(System.Security.Cryptography.SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(GetDiskIdentifier() + "_" + Environment.MachineName)));
/// <summary>
/// Generate a unique identifier for the machine
/// </summary>
try
{
// Generate the machine identifier
_mRIdentifier = MachineIdentifierGenerator.GenerateMachineIdentifier();
Console.WriteLine($"Generated Identifier: {_mRIdentifier}");
}
catch (PlatformNotSupportedException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
// Check if disk identifier is empty and prevent database creation if true
if (string.IsNullOrEmpty(_mRIdentifier))
@@ -53,6 +74,7 @@ public class LocalSettingsDBManager
}
}
/// <summary>
/// Ensures default settings are imported if the database is empty.
/// </summary>
@@ -369,42 +391,6 @@ public void EncryptDatabase()
}
}
/// <summary>
/// Gets the unique machine identifier (serial number of the hard drive) combined with the machine name and encrypts it using SHA256.
/// </summary>
/// <returns>Unique machine identifier.</returns>
private static string GetDiskIdentifier()
{
if (OperatingSystem.IsWindows())
{
try
{
// Use ManagementObject to get the serial number of the hard drive
using (var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_DiskDrive"))
{
foreach (var disk in searcher.Get())
{
string sn = "" + disk["SerialNumber"]; // 2025-01-14 in .net8 this returns NULL in virtual machines
return sn.Trim();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error getting disk identifier: {ex.Message}");
throw new InvalidOperationException("Failed to retrieve disk identifier. Please ensure the disk information is accessible.");
}
}
else
{
throw new PlatformNotSupportedException("This method is only supported on Windows.");
}
// Return an empty string if no serial number is found
return string.Empty;
}
// Setting class
public class Setting

View File

@@ -1,4 +1,4 @@
// The MIT License (MIT)
// The MIT License (MIT)
//
// Copyright(c) crdx
//

View File

@@ -14,7 +14,7 @@ using System.Security;
namespace mRemoteNG.Connection
{
[SupportedOSPlatform("windows")]
public abstract class AbstractConnectionRecord : INotifyPropertyChanged
public abstract class AbstractConnectionRecord(string uniqueId) : INotifyPropertyChanged
{
#region Fields
@@ -30,7 +30,8 @@ namespace mRemoteNG.Connection
private ExternalCredentialProvider _externalCredentialProvider;
private string _userViaAPI = "";
private string _username = "";
private SecureString _password = null;
//private SecureString _password = null;
private string _password = null;
private string _domain = "";
private string _vmId = "";
private bool _useEnhancedMode;
@@ -214,7 +215,8 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionPassword)),
PasswordPropertyText(true),
AttributeUsedInAllProtocolsExcept(ProtocolType.Telnet, ProtocolType.Rlogin, ProtocolType.RAW)]
public virtual SecureString Password
//public virtual SecureString Password
public virtual string Password
{
get => GetPropertyValue("Password", _password);
set => SetField(ref _password, value, "Password");
@@ -827,7 +829,7 @@ namespace mRemoteNG.Connection
#region Misc
[Browsable(false)] public string ConstantID { get; }
[Browsable(false)] public string ConstantID { get; } = uniqueId.ThrowIfNullOrEmpty(nameof(uniqueId));
[LocalizedAttributes.LocalizedCategory(nameof(Language.Miscellaneous), 7),
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ExternalToolBefore)),
@@ -1030,20 +1032,14 @@ namespace mRemoteNG.Connection
}
#endregion
#endregion
protected AbstractConnectionRecord(string uniqueId)
{
ConstantID = uniqueId.ThrowIfNullOrEmpty(nameof(uniqueId));
}
protected virtual TPropertyType GetPropertyValue<TPropertyType>(string propertyName, TPropertyType value)
{
return (TPropertyType)GetType().GetProperty(propertyName)?.GetValue(this, null);
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void RaisePropertyChangedEvent(object sender, PropertyChangedEventArgs args)
{

View File

@@ -12,22 +12,22 @@ namespace mRemoteNG.Connection
{
public static string[] Icons = { };
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext? context)
{
return new StandardValuesCollection(Icons);
}
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;
}
public static System.Drawing.Icon FromString(string iconName)
public static System.Drawing.Icon? FromString(string iconName)
{
try
{
@@ -41,7 +41,7 @@ namespace mRemoteNG.Connection
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, $"Couldn\'t get Icon from String" + Environment.NewLine + ex.Message);
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, $"Couldn't get Icon from String" + Environment.NewLine + ex.Message);
}
return null;

View File

@@ -6,18 +6,17 @@ using System.Runtime.Versioning;
namespace mRemoteNG.Connection
{
[SupportedOSPlatform("windows")]
public class ConnectionInfoComparer<TProperty> : IComparer<ConnectionInfo> where TProperty : IComparable<TProperty>
public class ConnectionInfoComparer<TProperty>(Func<ConnectionInfo, TProperty> sortExpression) : IComparer<ConnectionInfo> where TProperty : IComparable<TProperty>
{
private readonly Func<ConnectionInfo, TProperty> _sortExpression;
private readonly Func<ConnectionInfo, TProperty> _sortExpression = sortExpression;
public ListSortDirection SortDirection { get; set; } = ListSortDirection.Ascending;
public ConnectionInfoComparer(Func<ConnectionInfo, TProperty> sortExpression)
public int Compare(ConnectionInfo? x, ConnectionInfo? y)
{
_sortExpression = sortExpression;
}
if (x == null && y == null) return 0;
if (x == null) return SortDirection == ListSortDirection.Ascending ? -1 : 1;
if (y == null) return SortDirection == ListSortDirection.Ascending ? 1 : -1;
public int Compare(ConnectionInfo x, ConnectionInfo y)
{
return SortDirection == ListSortDirection.Ascending ? CompareAscending(x, y) : CompareDescending(x, y);
}

View File

@@ -406,21 +406,16 @@ namespace mRemoteNG.Connection
try
{
ProtocolBase prot = (ProtocolBase)sender;
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.ConnenctionCloseEvent,
true);
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.ConnenctionCloseEvent, true);
string connDetail;
if (prot.InterfaceControl.OriginalInfo.Hostname == "" &&
prot.InterfaceControl.Info.Protocol == ProtocolType.IntApp)
if (prot.InterfaceControl.OriginalInfo.Hostname == "" && prot.InterfaceControl.Info.Protocol == ProtocolType.IntApp)
connDetail = prot.InterfaceControl.Info.ExtApp;
else if (prot.InterfaceControl.OriginalInfo.Hostname != "")
connDetail = prot.InterfaceControl.OriginalInfo.Hostname;
else
connDetail = "UNKNOWN";
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg,
string.Format(Language.ConnenctionClosedByUser, connDetail,
prot.InterfaceControl.Info.Protocol,
Environment.UserName));
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.ConnenctionClosedByUser, connDetail, prot.InterfaceControl.Info.Protocol, Environment.UserName));
prot.InterfaceControl.OriginalInfo.OpenConnections.Remove(prot);
if (_activeConnections.Contains(prot.InterfaceControl.Info.ConstantID))
_activeConnections.Remove(prot.InterfaceControl.Info.ConstantID);

View File

@@ -23,12 +23,12 @@ using mRemoteNG.Config.Serializers.ConnectionSerializers.Sql;
namespace mRemoteNG.Connection
{
[SupportedOSPlatform("windows")]
public class ConnectionsService
public class ConnectionsService(PuttySessionsManager puttySessionsManager)
{
private static readonly object SaveLock = new();
private readonly PuttySessionsManager _puttySessionsManager;
private readonly IDataProvider<string> _localConnectionPropertiesDataProvider;
private readonly LocalConnectionPropertiesXmlSerializer _localConnectionPropertiesSerializer;
private readonly PuttySessionsManager _puttySessionsManager = puttySessionsManager ?? throw new ArgumentNullException(nameof(puttySessionsManager));
private readonly IDataProvider<string> _localConnectionPropertiesDataProvider = new FileDataProvider(Path.Combine(SettingsFileInfo.SettingsPath, SettingsFileInfo.LocalConnectionProperties));
private readonly LocalConnectionPropertiesXmlSerializer _localConnectionPropertiesSerializer = new LocalConnectionPropertiesXmlSerializer();
private bool _batchingSaves = false;
private bool _saveRequested = false;
private bool _saveAsyncRequested = false;
@@ -42,13 +42,6 @@ namespace mRemoteNG.Connection
public ConnectionTreeModel ConnectionTreeModel { get; private set; }
public ConnectionsService(PuttySessionsManager puttySessionsManager)
{
_puttySessionsManager = puttySessionsManager ?? throw new ArgumentNullException(nameof(puttySessionsManager));
_localConnectionPropertiesDataProvider = new FileDataProvider(Path.Combine(SettingsFileInfo.SettingsPath, SettingsFileInfo.LocalConnectionProperties));
_localConnectionPropertiesSerializer = new LocalConnectionPropertiesXmlSerializer();
}
public void NewConnectionsFile(string filename)
{
try

View File

@@ -1,4 +1,4 @@
namespace mRemoteNG.Connection
namespace mRemoteNG.Connection
{
public sealed partial class InterfaceControl : System.Windows.Forms.Panel
{
@@ -21,14 +21,11 @@ namespace mRemoteNG.Connection
//Required by the Windows Form Designer
private System.ComponentModel.Container components = null;
//NOTE: The following procedure is required by the Windows Form Designer
//It can be modified using the Windows Form Designer.
//Do not modify it using the code editor.
[System.Diagnostics.DebuggerStepThrough()]
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
}
//NOTE: The following procedure is required by the Windows Form Designer
//It can be modified using the Windows Form Designer.
//Do not modify it using the code editor.
[System.Diagnostics.DebuggerStepThrough()]
private void InitializeComponent() => components = new System.ComponentModel.Container();
}
}

View File

@@ -1,11 +1,13 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.Versioning;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.Connection.Protocol
{
[SupportedOSPlatform("windows")]
public class ProtocolList : CollectionBase, INotifyCollectionChanged
{
public ProtocolBase this[object index]
@@ -23,7 +25,6 @@ namespace mRemoteNG.Connection.Protocol
public new int Count => List.Count;
public void Add(ProtocolBase cProt)
{
List.Add(cProt);
@@ -64,7 +65,7 @@ namespace mRemoteNG.Connection.Protocol
RaiseCollectionChangedEvent(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event NotifyCollectionChangedEventHandler? CollectionChanged; // Fix for CS8612: Declare the event as nullable to match the interface.
private void RaiseCollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs args)
{

View File

@@ -102,7 +102,8 @@ namespace mRemoteNG.Connection.Protocol
{
string username = InterfaceControl.Info?.Username ?? "";
string password = InterfaceControl.Info?.Password?.ConvertToUnsecureString() ?? "";
//string password = InterfaceControl.Info?.Password?.ConvertToUnsecureString() ?? "";
string password = InterfaceControl.Info?.Password ?? "";
string domain = InterfaceControl.Info?.Domain ?? "";
string UserViaAPI = InterfaceControl.Info?.UserViaAPI ?? "";
string privatekey = "";

View File

@@ -426,7 +426,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
{
case RDGatewayUseConnectionCredentials.Yes:
_rdpClient.TransportSettings2.GatewayUsername = connectionInfo.Username;
_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password.ConvertToUnsecureString();
//_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password.ConvertToUnsecureString();
_rdpClient.TransportSettings2.GatewayPassword = connectionInfo.Password;
_rdpClient.TransportSettings2.GatewayDomain = connectionInfo?.Domain;
break;
case RDGatewayUseConnectionCredentials.SmartCard:
@@ -540,7 +541,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
string domain = connectionInfo?.Domain ?? "";
string userViaApi = connectionInfo?.UserViaAPI ?? "";
string pkey = "";
string password = (connectionInfo?.Password?.ConvertToUnsecureString() ?? "");
//string password = (connectionInfo?.Password?.ConvertToUnsecureString() ?? "");
string password = (connectionInfo?.Password ?? "");
// access secret server api if necessary
if (InterfaceControl.Info.ExternalCredentialProvider == ExternalCredentialProvider.DelineaSecretServer)

View File

@@ -215,7 +215,7 @@ namespace mRemoteNG.Connection.Protocol.VNC
private void VNCEvent_Disconnected(object sender, EventArgs e)
{
FrmMain.ClipboardChanged -= VNCEvent_ClipboardChanged;
Event_Disconnected(sender, @"VncSharp Disconnected.", null);
Event_Disconnected(this, @"VncSharp Disconnected.", null);
Close();
}
@@ -226,7 +226,8 @@ namespace mRemoteNG.Connection.Protocol.VNC
private string VNCEvent_Authenticate()
{
return _info.Password.ConvertToUnsecureString();
//return _info.Password.ConvertToUnsecureString();
return _info.Password;
}
#endregion

View File

@@ -15,15 +15,14 @@ namespace mRemoteNG.Connection
[SupportedOSPlatform("windows")]
public sealed class PuttySessionInfo : ConnectionInfo, IComponent
{
#region Properties
[Browsable(false)]
public RootPuttySessionsNodeInfo RootRootPuttySessionsInfo { get; set; } = default!;
[Browsable(false)] public RootPuttySessionsNodeInfo RootRootPuttySessionsInfo { get; set; }
[ReadOnly(true)] public override string PuttySession { get; set; } = string.Empty;
[ReadOnly(true)] public override string PuttySession { get; set; }
[ReadOnly(true)] public override string Name { get; set; } = string.Empty;
[ReadOnly(true)] public override string Name { get; set; }
[ReadOnly(true), Browsable(false)] public override string Description { get; set; }
[ReadOnly(true), Browsable(false)] public override string Description { get; set; } = string.Empty;
[ReadOnly(true), Browsable(false)]
public override string Icon
@@ -35,29 +34,30 @@ namespace mRemoteNG.Connection
[ReadOnly(true), Browsable(false)]
public override string Panel
{
get => Parent?.Panel;
get => Parent?.Panel ?? string.Empty; // Provide a default value to handle null cases
set { }
}
[ReadOnly(true)] public override string Hostname { get; set; }
[ReadOnly(true)] public override string Hostname { get; set; } = string.Empty;
[ReadOnly(true)] public override string Username { get; set; }
[ReadOnly(true)] public override string Username { get; set; } = string.Empty;
[ReadOnly(true), Browsable(false)] public override SecureString Password { get; set; }
//[ReadOnly(true), Browsable(false)] public override SecureString Password { get; set; }
[ReadOnly(true), Browsable(false)] public override string Password { get; set; } = string.Empty;
[ReadOnly(true)] public override ProtocolType Protocol { get; set; }
[ReadOnly(true)] public override int Port { get; set; }
[ReadOnly(true), Browsable(false)] public override string PreExtApp { get; set; }
[ReadOnly(true), Browsable(false)] public override string PreExtApp { get; set; } = string.Empty;
[ReadOnly(true), Browsable(false)] public override string PostExtApp { get; set; }
[ReadOnly(true), Browsable(false)] public override string PostExtApp { get; set; } = string.Empty;
[ReadOnly(true), Browsable(false)] public override string MacAddress { get; set; }
[ReadOnly(true), Browsable(false)] public override string MacAddress { get; set; } = string.Empty;
[ReadOnly(true), Browsable(false)] public override string UserField { get; set; }
[ReadOnly(true), Browsable(false)] public override string UserField { get; set; } = string.Empty;
#endregion
[Command(), LocalizedAttributes.LocalizedDisplayName("strPuttySessionSettings")]
public void SessionSettings()

View File

@@ -313,7 +313,7 @@ namespace mRemoteNG.Container
childAsContainer.CollectionChanged -= RaiseCollectionChangedEvent;
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event NotifyCollectionChangedEventHandler? CollectionChanged;
private void RaiseCollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs args)
{

View File

@@ -1,18 +1,24 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Versioning;
namespace mRemoteNG.Credential
{
[SupportedOSPlatform("windows")]
public class CredentialDomainUserComparer : IComparer<ICredentialRecord>, IEqualityComparer<ICredentialRecord>
{
public int Compare(ICredentialRecord x, ICredentialRecord y)
public int Compare(ICredentialRecord? x, ICredentialRecord? y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
CaseInsensitiveComparer comparer = new();
return comparer.Compare($"{x.Domain}\\{x.Username}", $"{y.Domain}\\{y.Username}");
}
public bool Equals(ICredentialRecord x, ICredentialRecord y)
public bool Equals(ICredentialRecord? x, ICredentialRecord? y)
{
return Compare(x, y) == 0;
}

View File

@@ -76,7 +76,7 @@ namespace mRemoteNG.Credential
return Title;
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void RaisePropertyChangedEvent(string propertyName)
{

View File

@@ -11,17 +11,12 @@ namespace mRemoteNG.Credential
[SupportedOSPlatform("windows")]
public class CredentialRecordTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{
return sourceType == typeof(Guid) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(Guid) || destinationType == typeof(ICredentialRecord) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
{
if (value is ICredentialRecord && destinationType == typeof(Guid))
return ((ICredentialRecord)value).Id;
@@ -30,7 +25,7 @@ namespace mRemoteNG.Credential
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
if (!(value is Guid)) return base.ConvertFrom(context, culture, value);
ICredentialRecord[] matchedCredentials = Runtime.CredentialProviderCatalog.GetCredentialRecords()

View File

@@ -11,7 +11,7 @@ namespace mRemoteNG.Credential
[SupportedOSPlatform("windows")]
public class PlaceholderCredentialRecord(IEnumerable<Guid> id) : ICredentialRecord
{
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
public Guid Id { get; } = id.FirstOrDefault();

View File

@@ -4,7 +4,7 @@ using System.Security;
namespace mRemoteNG.Credential.Repositories
{
public class CredentialRepositoryConfig : ICredentialRepositoryConfig
public class CredentialRepositoryConfig(Guid id) : ICredentialRepositoryConfig
{
private string _title = "New Credential Repository";
private string _source = "";
@@ -12,7 +12,7 @@ namespace mRemoteNG.Credential.Repositories
private string _typeName = "";
private bool _loaded;
public Guid Id { get; }
public Guid Id { get; } = id;
public string Title
{
@@ -68,12 +68,7 @@ namespace mRemoteNG.Credential.Repositories
{
}
public CredentialRepositoryConfig(Guid id)
{
Id = id;
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void RaisePropertyChangedEvent(string propertyName)
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -39,9 +39,6 @@ namespace mRemoteNG.Resources.Language {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
//string resourceFilePath = "Languages/ru/mRemoteNG.resources.dll";
//global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(resourceFilePath, typeof(Language).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mRemoteNG.Language.Language", typeof(Language).Assembly);
resourceMan = temp;
}
@@ -6436,7 +6433,7 @@ namespace mRemoteNG.Resources.Language {
}
/// <summary>
/// Looks up a localized string similar to mRemoteNG requires an update.
/// Looks up a localized string similar to mRemoteNG available.
/// </summary>
internal static string UpdateAvailable {
get {
@@ -6689,7 +6686,7 @@ namespace mRemoteNG.Resources.Language {
}
/// <summary>
/// Looks up a localized string similar to Version.
/// Looks up a localized string similar to Current Version.
/// </summary>
internal static string Version {
get {

View File

@@ -1670,7 +1670,7 @@ If you run into such an error, please create a new connection file!</value>
<value>Uncheck the properties you want not to be saved!</value>
</data>
<data name="UpdateAvailable" xml:space="preserve">
<value>mRemoteNG requires an update</value>
<value>mRemoteNG available</value>
</data>
<data name="UpdateCheck" xml:space="preserve">
<value>mRemoteNG can periodically connect to the mRemoteNG website to check for updates.</value>
@@ -1719,7 +1719,7 @@ mRemoteNG will now quit and begin with the installation.</value>
<value>Use SQL Server to load &amp;&amp; save connections</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
<value>Current Version</value>
</data>
<data name="Vnc" xml:space="preserve">
<value>VNC</value>

View File

@@ -1,20 +1,12 @@
using System;
using System;
namespace mRemoteNG.Messages
{
public class Message : IMessage
public class Message(MessageClass messageClass, string messageText, bool onlyLog = false) : IMessage
{
public MessageClass Class { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
public bool OnlyLog { get; set; }
public Message(MessageClass messageClass, string messageText, bool onlyLog = false)
{
Class = messageClass;
Text = messageText;
Date = DateTime.Now;
OnlyLog = onlyLog;
}
public MessageClass Class { get; set; } = messageClass;
public string Text { get; set; } = messageText;
public DateTime Date { get; set; } = DateTime.Now;
public bool OnlyLog { get; set; } = onlyLog;
}
}

View File

@@ -63,7 +63,7 @@ namespace mRemoteNG.Messages
_messageList.Clear();
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event NotifyCollectionChangedEventHandler? CollectionChanged;
private void RaiseCollectionChangedEvent(NotifyCollectionChangedAction action, IList items)
{

View File

@@ -7,14 +7,9 @@ using mRemoteNG.UI.Window;
namespace mRemoteNG.Messages.MessageWriters
{
[SupportedOSPlatform("windows")]
public class NotificationPanelMessageWriter : IMessageWriter
public class NotificationPanelMessageWriter(ErrorAndInfoWindow messageWindow) : IMessageWriter
{
private readonly ErrorAndInfoWindow _messageWindow;
public NotificationPanelMessageWriter(ErrorAndInfoWindow messageWindow)
{
_messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow));
}
private readonly ErrorAndInfoWindow _messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow));
public void Write(IMessage message)
{

View File

@@ -5,14 +5,9 @@ using mRemoteNG.App;
namespace mRemoteNG.Messages.MessageWriters
{
[SupportedOSPlatform("windows")]
public class TextLogMessageWriter : IMessageWriter
public class TextLogMessageWriter(Logger logger) : IMessageWriter
{
private readonly Logger _logger;
public TextLogMessageWriter(Logger logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
private readonly Logger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
public void Write(IMessage message)
{

View File

@@ -11,20 +11,13 @@ using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.Messages.WriterDecorators
{
[SupportedOSPlatform("windows")]
public class MessageFocusDecorator : IMessageWriter
public class MessageFocusDecorator(ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter) : IMessageWriter
{
private readonly IMessageTypeFilteringOptions _filter;
private readonly IMessageWriter _decoratedWriter;
private readonly ErrorAndInfoWindow _messageWindow;
private readonly IMessageTypeFilteringOptions _filter = filter ?? throw new ArgumentNullException(nameof(filter));
private readonly IMessageWriter _decoratedWriter = decoratedWriter ?? throw new ArgumentNullException(nameof(decoratedWriter));
private readonly ErrorAndInfoWindow _messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow));
private readonly FrmMain _frmMain = FrmMain.Default;
public MessageFocusDecorator(ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter)
{
_filter = filter ?? throw new ArgumentNullException(nameof(filter));
_messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow));
_decoratedWriter = decoratedWriter ?? throw new ArgumentNullException(nameof(decoratedWriter));
}
public async void Write(IMessage message)
{
_decoratedWriter.Write(message);

View File

@@ -1,12 +1,12 @@
//
// This code was generated by a script. Any changes made manually will be lost
// the next time this code is regenerated.
//
using System.Reflection;
using System.Resources;
// Compute version values
// General Information
[assembly: AssemblyTitle("mRemoteNG")]
[assembly: AssemblyDescription("Multi-Remote Next Generation Connection Manager")]
@@ -18,11 +18,10 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.78.1.2873")]
[assembly: AssemblyFileVersion("1.78.1.2873")]
[assembly: AssemblyVersion("1.78.2.3120")]
[assembly: AssemblyFileVersion("1.78.2.3120")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
[assembly: AssemblyInformationalVersion("1.78.1 (Nightly Build 2873)")]
[assembly: AssemblyInformationalVersion("1.78.2 (Nightly Build 3120)")]
// Logging
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]

View File

@@ -1,50 +1,38 @@
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
//
// This code was generated by a script. Any changes made manually will be lost
// the next time this code is regenerated.
//
using System.Reflection;
using System.Resources;
// Compute version values
<#
int major = 1;
int minor = 78;
int revision = 2;
string channel = "Nightly Build";
DateTime lastReleaseDate = new DateTime(2019, 9, 2);
TimeSpan elapsed = DateTime.UtcNow - lastReleaseDate;
int build = (int)(elapsed.TotalMinutes / 1000);
#>
// General Information
[assembly: AssemblyTitle("mRemoteNG")]
[assembly: AssemblyDescription("Multi-Remote Next Generation Connection Manager")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Profi-KOM Ltd.")]
[assembly: AssemblyProduct("mRemoteNG Connection Manager")]
[assembly: AssemblyCopyright("(c) 2025 mRemoteNG")]
[assembly: AssemblyCopyright("(c) <#= DateTime.UtcNow.Year #> mRemoteNG")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[assembly: AssemblyFileVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[assembly: AssemblyVersion("<#= major #>.<#= minor #>.<#= revision #>.<#= build #>")]
[assembly: AssemblyFileVersion("<#= major #>.<#= minor #>.<#= revision #>.<#= build #>")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
[assembly: AssemblyInformationalVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #> (<#= this.channel #> <#= this.build #>)")]
[assembly: AssemblyInformationalVersion("<#= major #>.<#= minor #>.<#= revision #> (<#= channel #> <#= build #>)")]
// Logging
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
<#+
//build is a number of days from date of last release + curent hour + curent minute of build
int major = 1;
int minor = 78;
int revision = 1;
string channel = "Nightly Build";
DateTime lastReleaseDate = new DateTime(2019, 9, 2);
DateTime CurrentDate = DateTime.UtcNow;
TimeSpan elapsedTime;
double TotalMinutes;
int build;
public override void Initialize()
{
elapsedTime = CurrentDate.Subtract(lastReleaseDate);
TotalMinutes = elapsedTime.TotalMinutes;
build = (int)(TotalMinutes / 1000);
base.Initialize();
}
#>
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]

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