├── .editorconfig
├── .gitattributes
├── .gitignore
├── DeviceId.sln
├── Directory.Build.props
├── build
├── build-alpha.cmd
├── build-alpha.ps1
├── build-release.cmd
├── build-release.ps1
├── push-to-nuget.cmd
└── push-to-nuget.ps1
├── license.txt
├── readme.md
├── src
├── DeviceId.Linux
│ ├── Components
│ │ ├── DockerContainerIdComponent.cs
│ │ └── LinuxRootDriveSerialNumberDeviceIdComponent.cs
│ ├── DeviceId.Linux.csproj
│ ├── DeviceIdBuilderExtensions.cs
│ ├── LinuxDeviceIdBuilder.cs
│ ├── LinuxDeviceIdBuilderExtensions.cs
│ ├── Serialization
│ │ ├── LsblkDevice.cs
│ │ ├── LsblkOutput.cs
│ │ └── SourceGenerationContext.cs
│ └── _InternalsVisibleTo.cs
├── DeviceId.Mac
│ ├── DeviceId.Mac.csproj
│ ├── DeviceIdBuilderExtensions.cs
│ ├── MacDeviceIdBuilder.cs
│ └── MacDeviceIdBuilderExtensions.cs
├── DeviceId.SqlServer
│ ├── DeviceId.SqlServer.csproj
│ ├── DeviceIdBuilderExtensions.cs
│ ├── SqlServerDeviceIdBuilder.cs
│ └── SqlServerDeviceIdBuilderExtensions.cs
├── DeviceId.Windows.Mmi
│ ├── Components
│ │ ├── MmiMacAddressDeviceIdComponent.cs
│ │ ├── MmiSystemDriveSerialNumberDeviceIdComponent.cs
│ │ └── MmiWqlDeviceIdComponent.cs
│ ├── DeviceId.Windows.Mmi.csproj
│ └── WindowsDeviceIdBuilderExtensions.cs
├── DeviceId.Windows.Wmi
│ ├── Components
│ │ ├── WmiDeviceIdComponent.cs
│ │ ├── WmiMacAddressDeviceIdComponent.cs
│ │ └── WmiSystemDriveSerialNumberDeviceIdComponent.cs
│ ├── DeviceId.Windows.Wmi.csproj
│ └── WindowsDeviceIdBuilderExtensions.cs
├── DeviceId.Windows.WmiLight
│ ├── Components
│ │ ├── WmiLightDeviceIdComponent.cs
│ │ ├── WmiLightMacAddressDeviceIdComponent.cs
│ │ └── WmiLightSystemDriveSerialNumberDeviceIdComponent.cs
│ ├── DeviceId.Windows.WmiLight.csproj
│ └── WindowsDeviceIdBuilderExtensions.cs
├── DeviceId.Windows
│ ├── Components
│ │ ├── RegistryValueDeviceIdComponent.cs
│ │ └── SystemIdDeviceIdComponent.cs
│ ├── DeviceId.Windows.csproj
│ ├── DeviceIdBuilderExtensions.cs
│ ├── WindowsDeviceIdBuilder.cs
│ └── WindowsDeviceIdBuilderExtensions.cs
├── DeviceId.snk
└── DeviceId
│ ├── CommandExecutors
│ ├── BashCommandExecutor.cs
│ ├── CommandExecutor.cs
│ ├── CommandExecutorBase.cs
│ ├── ICommandExecutor.cs
│ └── ShCommandExecutor.cs
│ ├── Components
│ ├── CommandComponent.cs
│ ├── DatabaseQueryDeviceIdComponent.cs
│ ├── DeviceIdComponent.cs
│ ├── FileContentsDeviceIdComponent.cs
│ ├── FileTokenDeviceIdComponent.cs
│ └── MacAddressDeviceIdComponent.cs
│ ├── DeviceId.csproj
│ ├── DeviceIdBuilder.cs
│ ├── DeviceIdBuilderExtensions.cs
│ ├── DeviceIdFormatters.cs
│ ├── DeviceIdManager.cs
│ ├── DeviceIdVersionEncoder.cs
│ ├── Encoders
│ ├── Base32ByteArrayEncoder.cs
│ ├── Base64ByteArrayEncoder.cs
│ ├── Base64UrlByteArrayEncoder.cs
│ ├── ByteArrayHasher.cs
│ ├── HashDeviceIdComponentEncoder.cs
│ ├── HexByteArrayEncoder.cs
│ └── PlainTextDeviceIdComponentEncoder.cs
│ ├── Formatters
│ ├── HashDeviceIdFormatter.cs
│ ├── StringDeviceIdFormatter.cs
│ └── XmlDeviceIdFormatter.cs
│ ├── IByteArrayEncoder.cs
│ ├── IByteArrayHasher.cs
│ ├── IDeviceIdComponent.cs
│ ├── IDeviceIdComponentEncoder.cs
│ ├── IDeviceIdFormatter.cs
│ ├── IDeviceIdVersionEncoder.cs
│ ├── Internal
│ ├── ByteArrayEncoders.cs
│ ├── ByteArrayHashers.cs
│ ├── MacAddressFormatter.cs
│ └── OS.cs
│ └── _InternalsVisibleTo.cs
└── test
└── DeviceId.Tests
├── Components
├── DockerContainerIdComponentTests.cs
├── LinuxRootDriveSerialNumberDeviceIdComponentTests.cs
├── SqlServerComponentTests.cs
└── WmiAndMmiDriveSerialNumberPerfTests.cs
├── DeviceId.Tests.csproj
├── DeviceId.Tests.snk
├── DeviceIdBuilderTests.cs
├── DeviceIdManagerTests.cs
├── Encoders
├── Base32ByteArrayEncoderTests.cs
├── Base64ByteArrayEncoderTests.cs
├── Base64UrlByteArrayEncoderTests.cs
├── HashDeviceIdComponentEncoderTests.cs
├── HexByteArrayEncoderTests.cs
└── PlainTextDeviceIdComponentEncoderTests.cs
├── Formatters
├── HashDeviceIdFormatterTests.cs
├── StringDeviceIdFormatterTests.cs
└── XmlDeviceIdFormatterTests.cs
├── Internal
└── MacAddressFormatterTests.cs
├── Linux_4.4.txt
├── Linux_4.8-4.13.txt
└── linux_nodocker.txt
/.editorconfig:
--------------------------------------------------------------------------------
1 | [root] = true
2 |
3 | [*]
4 | indent_style = space
5 | insert_final_newline = true
6 | trim_trailing_whitespace = true
7 |
8 | [*.csproj]
9 | indent_size = 2
10 |
11 | [*.cs]
12 | indent_size = 4
13 | csharp_style_namespace_declarations = file_scoped
14 | dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
15 | dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
16 | dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
17 | dotnet_naming_style.instance_field_style.capitalization = camel_case
18 | dotnet_naming_style.instance_field_style.required_prefix = _
19 | dotnet_naming_symbols.instance_fields.applicable_kinds = field
20 | dotnet_sort_system_directives_first = true
21 | dotnet_style_object_initializer = false
22 | dotnet_style_predefined_type_for_locals_parameters_members = true
23 | dotnet_style_predefined_type_for_member_access = false
24 | dotnet_style_prefer_inferred_anonymous_type_member_names = false
25 | dotnet_style_qualification_for_event = false
26 | dotnet_style_qualification_for_field = false
27 | dotnet_style_qualification_for_method = false
28 | dotnet_style_qualification_for_property = false
29 | dotnet_style_readonly_field = true
30 | dotnet_style_require_accessibility_modifiers = for_non_interface_members
31 | dotnet_diagnostic.IDE0005.severity = warning # Remove unnecessary import
32 | dotnet_diagnostic.IDE0017.severity = none # Use object initializers
33 | dotnet_diagnostic.IDE0161.severity = warning # File-scoped namespaces
34 |
35 | [Directory.Build.props]
36 | indent_size = 2
37 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | bin/
3 | obj/
4 | artifacts/
5 | *.user
6 | TestResults/
7 | *.nupkg
8 | *.snupkg
9 |
--------------------------------------------------------------------------------
/DeviceId.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31919.166
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BD122A91-437F-497E-80F1-F21BAD62C51F}"
7 | ProjectSection(SolutionItems) = preProject
8 | Directory.Build.props = Directory.Build.props
9 | EndProjectSection
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{5D030E54-9156-468B-9288-498DE74D8C61}"
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId", "src\DeviceId\DeviceId.csproj", "{02A96024-620B-4E75-AD22-439A7943BD4E}"
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Windows", "src\DeviceId.Windows\DeviceId.Windows.csproj", "{CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2}"
16 | EndProject
17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Windows.Wmi", "src\DeviceId.Windows.Wmi\DeviceId.Windows.Wmi.csproj", "{AAFA28A8-128B-4840-B38A-3D3408175C09}"
18 | EndProject
19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Windows.Mmi", "src\DeviceId.Windows.Mmi\DeviceId.Windows.Mmi.csproj", "{1C78A1BF-A91D-4280-978D-9FD8B497FEF0}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Linux", "src\DeviceId.Linux\DeviceId.Linux.csproj", "{48E205B2-5C2B-4F98-AAD9-B44398ABA5E2}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Mac", "src\DeviceId.Mac\DeviceId.Mac.csproj", "{865D5271-A21F-4F4B-8F57-7278FEC051AA}"
24 | EndProject
25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Tests", "test\DeviceId.Tests\DeviceId.Tests.csproj", "{C706C3B5-4912-41E6-9EF3-B8560464680A}"
26 | EndProject
27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceId.SqlServer", "src\DeviceId.SqlServer\DeviceId.SqlServer.csproj", "{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceId.Windows.WmiLight", "src\DeviceId.Windows.WmiLight\DeviceId.Windows.WmiLight.csproj", "{FA9327EF-BC7C-4237-8D6E-C81233362CEF}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {02A96024-620B-4E75-AD22-439A7943BD4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {02A96024-620B-4E75-AD22-439A7943BD4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {02A96024-620B-4E75-AD22-439A7943BD4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {02A96024-620B-4E75-AD22-439A7943BD4E}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {AAFA28A8-128B-4840-B38A-3D3408175C09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {AAFA28A8-128B-4840-B38A-3D3408175C09}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {AAFA28A8-128B-4840-B38A-3D3408175C09}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {AAFA28A8-128B-4840-B38A-3D3408175C09}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {1C78A1BF-A91D-4280-978D-9FD8B497FEF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {1C78A1BF-A91D-4280-978D-9FD8B497FEF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {1C78A1BF-A91D-4280-978D-9FD8B497FEF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {1C78A1BF-A91D-4280-978D-9FD8B497FEF0}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {48E205B2-5C2B-4F98-AAD9-B44398ABA5E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {48E205B2-5C2B-4F98-AAD9-B44398ABA5E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {48E205B2-5C2B-4F98-AAD9-B44398ABA5E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
56 | {48E205B2-5C2B-4F98-AAD9-B44398ABA5E2}.Release|Any CPU.Build.0 = Release|Any CPU
57 | {865D5271-A21F-4F4B-8F57-7278FEC051AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58 | {865D5271-A21F-4F4B-8F57-7278FEC051AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
59 | {865D5271-A21F-4F4B-8F57-7278FEC051AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {865D5271-A21F-4F4B-8F57-7278FEC051AA}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {C706C3B5-4912-41E6-9EF3-B8560464680A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {C706C3B5-4912-41E6-9EF3-B8560464680A}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {C706C3B5-4912-41E6-9EF3-B8560464680A}.Release|Any CPU.ActiveCfg = Release|Any CPU
64 | {C706C3B5-4912-41E6-9EF3-B8560464680A}.Release|Any CPU.Build.0 = Release|Any CPU
65 | {678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 | {678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 | {678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
68 | {678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Release|Any CPU.Build.0 = Release|Any CPU
69 | {FA9327EF-BC7C-4237-8D6E-C81233362CEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
70 | {FA9327EF-BC7C-4237-8D6E-C81233362CEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
71 | {FA9327EF-BC7C-4237-8D6E-C81233362CEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {FA9327EF-BC7C-4237-8D6E-C81233362CEF}.Release|Any CPU.Build.0 = Release|Any CPU
73 | EndGlobalSection
74 | GlobalSection(SolutionProperties) = preSolution
75 | HideSolutionNode = FALSE
76 | EndGlobalSection
77 | GlobalSection(NestedProjects) = preSolution
78 | {02A96024-620B-4E75-AD22-439A7943BD4E} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
79 | {CB8011DD-7FD1-4BA5-A63C-8CF11AD706E2} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
80 | {AAFA28A8-128B-4840-B38A-3D3408175C09} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
81 | {1C78A1BF-A91D-4280-978D-9FD8B497FEF0} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
82 | {48E205B2-5C2B-4F98-AAD9-B44398ABA5E2} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
83 | {865D5271-A21F-4F4B-8F57-7278FEC051AA} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
84 | {C706C3B5-4912-41E6-9EF3-B8560464680A} = {5D030E54-9156-468B-9288-498DE74D8C61}
85 | {678F5EAE-C13E-4EEC-A2F3-17F43CE099FE} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
86 | {FA9327EF-BC7C-4237-8D6E-C81233362CEF} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
87 | EndGlobalSection
88 | GlobalSection(ExtensibilityGlobals) = postSolution
89 | SolutionGuid = {702DF5F2-A40A-46BC-A155-7CEAF7F7AA93}
90 | EndGlobalSection
91 | EndGlobal
92 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Matthew King
5 | Copyright Matthew King.
6 | MIT
7 | https://github.com/MatthewKing/DeviceId
8 | https://github.com/MatthewKing/DeviceId
9 | git
10 | deviceid;unique;device;identifier
11 | readme.md
12 | 6.9.0
13 |
14 |
15 |
16 | true
17 | ..\DeviceId.snk
18 |
19 |
20 |
21 | true
22 | true
23 | true
24 | snupkg
25 |
26 |
27 |
28 |
29 | false
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/build/build-alpha.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0\build-alpha.ps1"
3 |
--------------------------------------------------------------------------------
/build/build-alpha.ps1:
--------------------------------------------------------------------------------
1 | $root = Resolve-Path (Join-Path $PSScriptRoot "..")
2 | $output = "$root/artifacts"
3 | $projects = @(
4 | "$root/src/DeviceId/DeviceId.csproj",
5 | "$root/src/DeviceId.Windows/DeviceId.Windows.csproj",
6 | "$root/src/DeviceId.Windows.Wmi/DeviceId.Windows.Wmi.csproj",
7 | "$root/src/DeviceId.Windows.Mmi/DeviceId.Windows.Mmi.csproj",
8 | "$root/src/DeviceId.SqlServer/DeviceId.SqlServer.csproj",
9 | "$root/src/DeviceId.Linux/DeviceId.Linux.csproj",
10 | "$root/src/DeviceId.Mac/DeviceId.Mac.csproj"
11 | )
12 |
13 | $timestamp = git log -1 --format=%ct
14 |
15 | foreach ($project in $projects) {
16 | dotnet pack $project --configuration Release --output $output --version-suffix "alpha.$timestamp" -p:ContinuousIntegrationBuild=true
17 | }
18 |
--------------------------------------------------------------------------------
/build/build-release.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0\build-release.ps1"
3 |
--------------------------------------------------------------------------------
/build/build-release.ps1:
--------------------------------------------------------------------------------
1 | $root = Resolve-Path (Join-Path $PSScriptRoot "..")
2 | $output = "$root/artifacts"
3 | $projects = @(
4 | "$root/src/DeviceId/DeviceId.csproj",
5 | "$root/src/DeviceId.Windows/DeviceId.Windows.csproj",
6 | "$root/src/DeviceId.Windows.Wmi/DeviceId.Windows.Wmi.csproj",
7 | "$root/src/DeviceId.Windows.WmiLight/DeviceId.Windows.WmiLight.csproj",
8 | "$root/src/DeviceId.Windows.Mmi/DeviceId.Windows.Mmi.csproj",
9 | "$root/src/DeviceId.SqlServer/DeviceId.SqlServer.csproj",
10 | "$root/src/DeviceId.Linux/DeviceId.Linux.csproj",
11 | "$root/src/DeviceId.Mac/DeviceId.Mac.csproj"
12 | )
13 |
14 | foreach ($project in $projects) {
15 | dotnet pack $project --configuration Release --output $output -p:ContinuousIntegrationBuild=true
16 | }
17 |
--------------------------------------------------------------------------------
/build/push-to-nuget.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0\push-to-nuget.ps1"
3 |
--------------------------------------------------------------------------------
/build/push-to-nuget.ps1:
--------------------------------------------------------------------------------
1 | $apiKey = Read-Host -Prompt "Enter your nuget.org API key"
2 |
3 | $root = Resolve-Path (Join-Path $PSScriptRoot "..")
4 | $output = "$root/artifacts"
5 | foreach ($package in Get-ChildItem -Path $output -Filter "*.nupkg") {
6 | dotnet nuget push $package.FullName --source https://api.nuget.org/v3/index.json --api-key $apiKey --skip-duplicate
7 | }
8 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2021 Matthew King
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/Components/DockerContainerIdComponent.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Text.RegularExpressions;
3 |
4 | namespace DeviceId.Linux.Components;
5 |
6 | ///
7 | /// An implementation of that uses the cgroup to read the Docker container id.
8 | ///
9 | public class DockerContainerIdComponent : IDeviceIdComponent
10 | {
11 | ///
12 | /// The cgroup file.
13 | ///
14 | private readonly string _cGroupFile;
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The cgroup file.
20 | public DockerContainerIdComponent(string cGroupFile)
21 | {
22 | _cGroupFile = cGroupFile;
23 | }
24 |
25 | ///
26 | /// Gets the component value.
27 | ///
28 | /// The component value.
29 | public string GetValue()
30 | {
31 | if (string.IsNullOrWhiteSpace(_cGroupFile) || !File.Exists(_cGroupFile))
32 | {
33 | return null;
34 | }
35 |
36 | using var file = File.OpenText(_cGroupFile);
37 |
38 | if (TryGetContainerId(file, out string containerId))
39 | {
40 | return containerId;
41 | }
42 |
43 | return null;
44 | }
45 |
46 | private static bool TryGetContainerId(StreamReader reader, out string containerId)
47 | {
48 | var regex = new Regex("(\\d)+\\:(.)+?\\:(/.+?)??(/docker[-/])([0-9a-f]+)");
49 |
50 | string line;
51 | while ((line = reader?.ReadLine()) != null)
52 | {
53 | var match = regex.Match(line);
54 | if (match.Success)
55 | {
56 | containerId = match.Groups[5].Value;
57 | return true;
58 | }
59 | }
60 |
61 | containerId = default;
62 | return false;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/Components/LinuxRootDriveSerialNumberDeviceIdComponent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Linq;
4 | using System.Text.Json;
5 | using DeviceId.CommandExecutors;
6 | using DeviceId.Linux.Serialization;
7 |
8 | namespace DeviceId.Linux.Components;
9 |
10 | ///
11 | /// An implementation of that uses the root drive's serial number.
12 | ///
13 | public class LinuxRootDriveSerialNumberDeviceIdComponent : IDeviceIdComponent
14 | {
15 | ///
16 | /// Command executor.
17 | ///
18 | private readonly ICommandExecutor _commandExecutor;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | [EditorBrowsable(EditorBrowsableState.Never)]
24 | [Obsolete("This constructor is obsolete and will be removed in a future version. Use the constructor that accepts an ICommandExecutor instead.")]
25 | public LinuxRootDriveSerialNumberDeviceIdComponent()
26 | : this(CommandExecutor.Bash) { }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The command executor to use.
32 | public LinuxRootDriveSerialNumberDeviceIdComponent(ICommandExecutor commandExecutor)
33 | {
34 | _commandExecutor = commandExecutor;
35 | }
36 |
37 | ///
38 | /// Gets the component value.
39 | ///
40 | /// The component value.
41 | public string GetValue()
42 | {
43 | var outputJson = _commandExecutor.Execute("lsblk -f -J");
44 | var output = JsonSerializer.Deserialize(outputJson, SourceGenerationContext.Default.LsblkOutput);
45 |
46 | var device = FindRootParent(output);
47 | if (device == null)
48 | {
49 | return null;
50 | }
51 |
52 | var udevInfo = _commandExecutor.Execute($"udevadm info --query=all --name=/dev/{device.Name} | grep ID_SERIAL=");
53 | if (udevInfo == null)
54 | {
55 | return null;
56 | }
57 |
58 | var components = udevInfo.Split('=');
59 | if (components.Length < 2)
60 | {
61 | return null;
62 | }
63 |
64 | return components[1];
65 | }
66 |
67 | private static LsblkDevice FindRootParent(LsblkOutput devices)
68 | {
69 | return devices.BlockDevices.FirstOrDefault(x => DeviceContainsRoot(x));
70 | }
71 |
72 | private static bool DeviceContainsRoot(LsblkDevice device)
73 | {
74 | if (device.MountPoint == "/")
75 | {
76 | return true;
77 | }
78 |
79 | if (device.Children == null || device.Children.Count == 0)
80 | {
81 | return false;
82 | }
83 |
84 | return device.Children.Any(x => DeviceContainsRoot(x));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/DeviceId.Linux.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DeviceId.Linux
5 | DeviceId (Linux)
6 | Provides Linux-specific components for the DeviceId package.
7 |
8 |
9 |
10 | netstandard2.0;net8.0;net9.0
11 | latest
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/DeviceIdBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using DeviceId.Internal;
3 |
4 | namespace DeviceId;
5 |
6 | ///
7 | /// Extension methods for .
8 | ///
9 | public static class DeviceIdBuilderExtensions
10 | {
11 | ///
12 | /// Adds Linux-specific components to the device ID.
13 | ///
14 | /// The device ID builder to add the components to.
15 | /// An action that adds the Linux-specific components.
16 | /// The device ID builder.
17 | public static DeviceIdBuilder OnLinux(this DeviceIdBuilder builder, Action linuxBuilderConfiguration)
18 | {
19 | if (OS.IsLinux && linuxBuilderConfiguration is not null)
20 | {
21 | var linuxBuilder = new LinuxDeviceIdBuilder(builder);
22 | linuxBuilderConfiguration.Invoke(linuxBuilder);
23 | }
24 |
25 | return builder;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/LinuxDeviceIdBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using DeviceId.Internal;
3 |
4 | namespace DeviceId;
5 |
6 | ///
7 | /// Provides a fluent interface for adding Linux-specific components to a device identifier.
8 | ///
9 | public class LinuxDeviceIdBuilder
10 | {
11 | ///
12 | /// The base device identifier builder.
13 | ///
14 | private readonly DeviceIdBuilder _baseBuilder;
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The base device identifier builder.
20 | public LinuxDeviceIdBuilder(DeviceIdBuilder baseBuilder)
21 | {
22 | _baseBuilder = baseBuilder ?? throw new ArgumentNullException(nameof(baseBuilder));
23 | }
24 |
25 | ///
26 | /// Adds a component to the device identifier.
27 | /// If a component with the specified name already exists, it will be replaced with this newly added component.
28 | ///
29 | /// The component name.
30 | /// The component to add.
31 | /// The builder instance.
32 | public LinuxDeviceIdBuilder AddComponent(string name, IDeviceIdComponent component)
33 | {
34 | if (OS.IsLinux)
35 | {
36 | _baseBuilder.AddComponent(name, component);
37 | }
38 |
39 | return this;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/LinuxDeviceIdBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using DeviceId.CommandExecutors;
2 | using DeviceId.Components;
3 | using DeviceId.Linux.Components;
4 |
5 | namespace DeviceId;
6 |
7 | ///
8 | /// Extension methods for .
9 | ///
10 | public static class LinuxDeviceIdBuilderExtensions
11 | {
12 | ///
13 | /// Adds the system drive serial number to the device identifier.
14 | ///
15 | /// The to add the component to.
16 | /// The instance.
17 | public static LinuxDeviceIdBuilder AddSystemDriveSerialNumber(this LinuxDeviceIdBuilder builder)
18 | {
19 | return AddSystemDriveSerialNumber(builder, CommandExecutor.Bash);
20 | }
21 |
22 | ///
23 | /// Adds the system drive serial number to the device identifier.
24 | ///
25 | /// The to add the component to.
26 | /// The command executor to use.
27 | /// The instance.
28 | public static LinuxDeviceIdBuilder AddSystemDriveSerialNumber(this LinuxDeviceIdBuilder builder, ICommandExecutor commandExecutor)
29 | {
30 | return builder.AddComponent("SystemDriveSerialNumber", new LinuxRootDriveSerialNumberDeviceIdComponent(commandExecutor));
31 | }
32 |
33 | ///
34 | /// Adds the docker container id to the device identifier.
35 | ///
36 | /// The to add the component to.
37 | /// The instance.
38 | public static LinuxDeviceIdBuilder AddDockerContainerId(this LinuxDeviceIdBuilder builder)
39 | {
40 | return builder.AddComponent("DockerContainerId", new DockerContainerIdComponent("/proc/1/cgroup"));
41 | }
42 |
43 | ///
44 | /// Adds the machine ID (from /var/lib/dbus/machine-id or /etc/machine-id) to the device identifier.
45 | ///
46 | /// The to add the component to.
47 | /// The instance.
48 | public static LinuxDeviceIdBuilder AddMachineId(this LinuxDeviceIdBuilder builder)
49 | {
50 | return builder.AddComponent("MachineID", new FileContentsDeviceIdComponent(new[] { "/var/lib/dbus/machine-id", "/etc/machine-id" }, false));
51 | }
52 |
53 | ///
54 | /// Adds the product UUID (from /sys/class/dmi/id/product_uuid) to the device identifier.
55 | ///
56 | /// The to add the component to.
57 | /// The instance.
58 | public static LinuxDeviceIdBuilder AddProductUuid(this LinuxDeviceIdBuilder builder)
59 | {
60 | return builder.AddComponent("ProductUUID", new FileContentsDeviceIdComponent("/sys/class/dmi/id/product_uuid", false));
61 | }
62 |
63 | ///
64 | /// Adds the CPU info (from /proc/cpuinfo) to the device identifier.
65 | ///
66 | /// The to add the component to.
67 | /// The instance.
68 | public static LinuxDeviceIdBuilder AddCpuInfo(this LinuxDeviceIdBuilder builder)
69 | {
70 | return builder.AddComponent("CPUInfo", new FileContentsDeviceIdComponent("/proc/cpuinfo", true));
71 | }
72 |
73 | ///
74 | /// Adds the motherboard serial number (from /sys/class/dmi/id/board_serial) to the device identifier.
75 | ///
76 | /// The to add the component to.
77 | /// The instance.
78 | public static LinuxDeviceIdBuilder AddMotherboardSerialNumber(this LinuxDeviceIdBuilder builder)
79 | {
80 | return builder.AddComponent("MotherboardSerialNumber", new FileContentsDeviceIdComponent("/sys/class/dmi/id/board_serial", false));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/Serialization/LsblkDevice.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace DeviceId.Linux.Serialization;
4 |
5 | internal sealed class LsblkDevice
6 | {
7 | public string Name { get; set; } = string.Empty;
8 | public string MountPoint { get; set; } = string.Empty;
9 | public List Children { get; set; } = new List();
10 | }
11 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/Serialization/LsblkOutput.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace DeviceId.Linux.Serialization;
4 |
5 | internal sealed class LsblkOutput
6 | {
7 | public List BlockDevices { get; set; } = new List();
8 | }
9 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/Serialization/SourceGenerationContext.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace DeviceId.Linux.Serialization;
4 |
5 | [JsonSerializable(typeof(LsblkDevice))]
6 | [JsonSerializable(typeof(LsblkOutput))]
7 | [JsonSourceGenerationOptions(PropertyNameCaseInsensitive = true)]
8 | internal partial class SourceGenerationContext : JsonSerializerContext { }
9 |
--------------------------------------------------------------------------------
/src/DeviceId.Linux/_InternalsVisibleTo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
4 | [assembly: InternalsVisibleTo("DeviceId.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001008906d2e5a92d72693cfdd24b29f9c3ea5ca51972be746724afef8a65000a1ebbc88aee54e4c9c3bef49c0e837702170e99919a8b8075cfd6ed8494c5f9cd1a640a57cc907a84861bfe7ecb877d475a94ec333c6c0a586b6f37a15e67431381cac046217c0fa570c3e8e140e733254686213b77ae53fccdc1f5b3ab806ac692c1")]
5 |
--------------------------------------------------------------------------------
/src/DeviceId.Mac/DeviceId.Mac.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DeviceId.Mac
5 | DeviceId (Mac)
6 | Provides Mac-specific components for the DeviceId package.
7 |
8 |
9 |
10 | netstandard2.0;net8.0;net9.0
11 | latest
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/DeviceId.Mac/DeviceIdBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using DeviceId.Internal;
3 |
4 | namespace DeviceId;
5 |
6 | ///
7 | /// Extension methods for .
8 | ///
9 | public static class DeviceIdBuilderExtensions
10 | {
11 | ///
12 | /// Adds Mac-specific components to the device ID.
13 | ///
14 | /// The device ID builder to add the components to.
15 | /// An action that adds the Mac-specific components.
16 | /// The device ID builder.
17 | public static DeviceIdBuilder OnMac(this DeviceIdBuilder builder, Action macBuilderConfiguration)
18 | {
19 | if (OS.IsMacOS && macBuilderConfiguration is not null)
20 | {
21 | var macBuilder = new MacDeviceIdBuilder(builder);
22 | macBuilderConfiguration.Invoke(macBuilder);
23 | }
24 |
25 | return builder;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DeviceId.Mac/MacDeviceIdBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using DeviceId.Internal;
3 |
4 | namespace DeviceId;
5 |
6 | ///
7 | /// Provides a fluent interface for adding Mac-specific components to a device identifier.
8 | ///
9 | public class MacDeviceIdBuilder
10 | {
11 | ///
12 | /// The base device identifier builder.
13 | ///
14 | private readonly DeviceIdBuilder _baseBuilder;
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The base device identifier builder.
20 | public MacDeviceIdBuilder(DeviceIdBuilder baseBuilder)
21 | {
22 | _baseBuilder = baseBuilder ?? throw new ArgumentNullException(nameof(baseBuilder));
23 | }
24 |
25 | ///
26 | /// Adds a component to the device identifier.
27 | /// If a component with the specified name already exists, it will be replaced with this newly added component.
28 | ///
29 | /// The component name.
30 | /// The component to add.
31 | /// The builder instance.
32 | public MacDeviceIdBuilder AddComponent(string name, IDeviceIdComponent component)
33 | {
34 | if (OS.IsMacOS)
35 | {
36 | _baseBuilder.AddComponent(name, component);
37 | }
38 |
39 | return this;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/DeviceId.Mac/MacDeviceIdBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using DeviceId.CommandExecutors;
2 | using DeviceId.Components;
3 |
4 | namespace DeviceId;
5 |
6 | ///
7 | /// Extension methods for .
8 | ///
9 | public static class MacDeviceIdBuilderExtensions
10 | {
11 | ///
12 | /// Adds the system drive serial number to the device identifier.
13 | ///
14 | /// The to add the component to.
15 | /// The instance.
16 | public static MacDeviceIdBuilder AddSystemDriveSerialNumber(this MacDeviceIdBuilder builder)
17 | {
18 | return AddSystemDriveSerialNumber(builder, CommandExecutor.Bash);
19 | }
20 |
21 | ///
22 | /// Adds the system drive serial number to the device identifier.
23 | ///
24 | /// The to add the component to.
25 | /// The command executor to use.
26 | /// The instance.
27 | public static MacDeviceIdBuilder AddSystemDriveSerialNumber(this MacDeviceIdBuilder builder, ICommandExecutor commandExecutor)
28 | {
29 | return builder.AddComponent("SystemDriveSerialNumber", new CommandComponent("system_profiler SPSerialATADataType | sed -En 's/.*Serial Number: ([\\d\\w]*)//p'", commandExecutor));
30 | }
31 |
32 | ///
33 | /// Adds the platform serial number to the device identifier.
34 | ///
35 | /// The to add the component to.
36 | /// The instance.
37 | public static MacDeviceIdBuilder AddPlatformSerialNumber(this MacDeviceIdBuilder builder)
38 | {
39 | return AddPlatformSerialNumber(builder, CommandExecutor.Bash);
40 | }
41 |
42 | ///
43 | /// Adds the platform serial number to the device identifier.
44 | ///
45 | /// The to add the component to.
46 | /// The command executor to use.
47 | /// The instance.
48 | public static MacDeviceIdBuilder AddPlatformSerialNumber(this MacDeviceIdBuilder builder, ICommandExecutor commandExecutor)
49 | {
50 | return builder.AddComponent("IOPlatformSerialNumber", new CommandComponent("ioreg -l | grep IOPlatformSerialNumber | sed 's/.*= //' | sed 's/\"//g'", commandExecutor));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/DeviceId.SqlServer/DeviceId.SqlServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DeviceId.SqlServer
5 | DeviceId (SQL Server)
6 | Provides SQL Server components for the DeviceId package.
7 |
8 |
9 |
10 | net35;net40;netstandard2.0;net8.0;net9.0
11 | latest
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/DeviceId.SqlServer/DeviceIdBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Common;
3 |
4 | namespace DeviceId.SqlServer;
5 |
6 | ///
7 | /// Extension methods for .
8 | ///
9 | public static class DeviceIdBuilderExtensions
10 | {
11 | ///
12 | /// Adds SQL Server components to the device ID.
13 | ///
14 | /// The device ID builder to add the components to.
15 | /// A connection to the SQL Server database.
16 | /// An action that adds the SQL Server components.
17 | /// The device ID builder.
18 | public static DeviceIdBuilder AddSqlServer(this DeviceIdBuilder builder, DbConnection connection, Action sqlServerBuilderConfiguration)
19 | {
20 | if (sqlServerBuilderConfiguration is not null)
21 | {
22 | var sqlServerBuilder = new SqlServerDeviceIdBuilder(builder, connection);
23 | sqlServerBuilderConfiguration.Invoke(sqlServerBuilder);
24 | }
25 |
26 | return builder;
27 | }
28 |
29 | ///
30 | /// Adds SQL Server components to the device ID.
31 | ///
32 | /// The device ID builder to add the components to.
33 | /// A factory used to get a connection to the SQL Server database.
34 | /// An action that adds the SQL Server components.
35 | /// The device ID builder.
36 | public static DeviceIdBuilder AddSqlServer(this DeviceIdBuilder builder, Func connectionFactory, Action sqlServerBuilderConfiguration)
37 | {
38 | if (sqlServerBuilderConfiguration is not null)
39 | {
40 | var sqlServerBuilder = new SqlServerDeviceIdBuilder(builder, connectionFactory);
41 | sqlServerBuilderConfiguration.Invoke(sqlServerBuilder);
42 | }
43 |
44 | return builder;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/DeviceId.SqlServer/SqlServerDeviceIdBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Common;
3 | using DeviceId.Components;
4 |
5 | namespace DeviceId.SqlServer;
6 |
7 | ///
8 | /// Provides a fluent interface for adding SQL Server components to a device identifier.
9 | ///
10 | public class SqlServerDeviceIdBuilder
11 | {
12 | ///
13 | /// The base device identifier builder.
14 | ///
15 | private readonly DeviceIdBuilder _baseBuilder;
16 |
17 | ///
18 | /// A factory used to get a connection to the SQL Server database.
19 | ///
20 | private readonly Func _connectionFactory;
21 |
22 | ///
23 | /// A value determining whether the connection should be disposed after use.
24 | ///
25 | private readonly bool _disposeConnection;
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | /// The base device identifier builder.
31 | /// A connection to the SQL Server database.
32 | public SqlServerDeviceIdBuilder(DeviceIdBuilder baseBuilder, DbConnection connection)
33 | {
34 | if (baseBuilder is null)
35 | {
36 | throw new ArgumentNullException(nameof(baseBuilder));
37 | }
38 |
39 | if (connection is null)
40 | {
41 | throw new ArgumentNullException(nameof(connection));
42 | }
43 |
44 | _baseBuilder = baseBuilder;
45 | _connectionFactory = () => connection;
46 | _disposeConnection = false;
47 | }
48 |
49 | ///
50 | /// Initializes a new instance of the class.
51 | ///
52 | /// The base device identifier builder.
53 | /// A factory used to get a connection to the SQL Server database.
54 | public SqlServerDeviceIdBuilder(DeviceIdBuilder baseBuilder, Func connectionFactory)
55 | {
56 | if (baseBuilder is null)
57 | {
58 | throw new ArgumentNullException(nameof(baseBuilder));
59 | }
60 |
61 | if (connectionFactory is null)
62 | {
63 | throw new ArgumentNullException(nameof(connectionFactory));
64 | }
65 |
66 | _baseBuilder = baseBuilder;
67 | _connectionFactory = connectionFactory;
68 | _disposeConnection = true;
69 | }
70 |
71 | ///
72 | /// Adds the result of a SQL query to the device identifier.
73 | ///
74 | /// The name of the component.
75 | /// SQL query that returns a single value to be added to the device identifier.
76 | /// The instance.
77 | public SqlServerDeviceIdBuilder AddQueryResult(string componentName, string sql)
78 | {
79 | return AddQueryResult(componentName, sql, x => x.ToString());
80 | }
81 |
82 | ///
83 | /// Adds the result of a SQL query to the device identifier.
84 | ///
85 | /// The name of the component.
86 | /// SQL query that returns a single value to be added to the device identifier.
87 | /// A function that transforms the result of the query into a string.
88 | /// The instance.
89 | public SqlServerDeviceIdBuilder AddQueryResult(string componentName, string sql, Func