├── img
└── remoteDesktopWindow.png
├── src
├── .editorconfig
├── RdpProtocolHandler
│ ├── test.reg
│ ├── Properties
│ │ ├── PublishProfiles
│ │ │ └── FolderProfile.pubxml
│ │ └── AssemblyInfo.cs
│ ├── NLog.config
│ ├── RdpProtocolHandler.csproj
│ ├── ConsoleWrapper.cs
│ ├── LoggerHelper.cs
│ ├── RdpHandler.cs
│ ├── Program.cs
│ └── Installer.cs
└── RdpProtocolHandler.sln
├── LICENSE
├── README.md
├── .github
└── workflows
│ └── dotnet.yml
└── .gitignore
/img/remoteDesktopWindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konradsikorski/RdpProtocolHandler/HEAD/img/remoteDesktopWindow.png
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # IDE0063: Use simple 'using' statement
4 | csharp_prefer_simple_using_statement = false
5 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/test.reg:
--------------------------------------------------------------------------------
1 | REGEDIT4
2 |
3 | [HKEY_CLASSES_ROOT\RDP-Protocol]
4 | @="rdp:Remote Desktop Protocol"
5 | "URL Protocol"=""
6 |
7 | [HKEY_CLASSES_ROOT\RDP-Protocol\DefaultIcon]
8 | @="\"C:\\Windows\\System32\\mstsc.exe\""
9 |
10 | [HKEY_CLASSES_ROOT\RDP-Protocol\shell]
11 |
12 | [HKEY_CLASSES_ROOT\RDP-Protocol\shell\open]
13 |
14 | [HKEY_CLASSES_ROOT\RDP-Protocol\shell\open\command]
15 | @="\"C:\\Windows\\System32\\rdphandler.exe\" \"%1\""
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/Properties/PublishProfiles/FolderProfile.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | Release
8 | Any CPU
9 | publish\win-x64\
10 | FileSystem
11 | <_TargetId>Folder
12 | net7.0
13 | win-x64
14 | false
15 | false
16 |
17 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/RdpProtocolHandler.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net7.0
4 | WinExe
5 | KonradSikorski.Tools.RdpProtocolHandler
6 | false
7 | true
8 | true
9 | win-x64
10 | embedded
11 |
12 |
13 |
14 |
15 | true
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Konrad Sikorski
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.33326.253
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RdpProtocolHandler", "RdpProtocolHandler\RdpProtocolHandler.csproj", "{9BCAEE56-8E0E-4156-9FB8-A1203E2001F9}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FC47C625-8A77-4C95-81BB-F869C794327F}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | README.md = README.md
12 | EndProjectSection
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {9BCAEE56-8E0E-4156-9FB8-A1203E2001F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {9BCAEE56-8E0E-4156-9FB8-A1203E2001F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {9BCAEE56-8E0E-4156-9FB8-A1203E2001F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {9BCAEE56-8E0E-4156-9FB8-A1203E2001F9}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/ConsoleWrapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace KonradSikorski.Tools.RdpProtocolHandler
5 | {
6 | public static partial class ConsoleWrapper
7 | {
8 | public static bool Initialized { get; private set; }
9 |
10 | [LibraryImport("kernel32.dll", SetLastError = true)]
11 | [return: MarshalAs(UnmanagedType.Bool)]
12 | private static partial bool AllocConsole();
13 |
14 | public static void Alloc()
15 | {
16 | if (Initialized) return;
17 |
18 | AllocConsole();
19 | Initialized = true;
20 | }
21 |
22 | public static ConsoleColor ForegroundColor
23 | {
24 | get
25 | {
26 | Alloc();
27 | return Console.ForegroundColor;
28 | }
29 | set
30 | {
31 | Alloc();
32 | Console.ForegroundColor = value;
33 | }
34 | }
35 |
36 | public static void WriteLine(string format)
37 | {
38 | Alloc();
39 | Console.WriteLine(format);
40 | }
41 |
42 | public static void WaitForClose()
43 | {
44 | if (!Initialized) return;
45 |
46 | Console.WriteLine("Press any key to close...");
47 | Console.ReadKey();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/LoggerHelper.cs:
--------------------------------------------------------------------------------
1 | using NLog.Config;
2 | using NLog.Targets;
3 | using NLog;
4 | using System;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.Linq;
8 |
9 | namespace KonradSikorski.Tools.RdpProtocolHandler
10 | {
11 | internal static class LoggerHelper
12 | {
13 | internal static void ConfigureNLog()
14 | {
15 | if (LogManager.Configuration != null) return;
16 |
17 | var logConfiguration = new LoggingConfiguration();
18 | var fileTarget = new FileTarget("file")
19 | {
20 | Layout = "${longdate} ${uppercase:${level}} ${message}",
21 | FileName = Path.Combine(Path.GetTempPath(), @"rdppotocolhandler-logs\${shortdate}.log")
22 | };
23 |
24 | var rule = new LoggingRule("*", LogLevel.Debug, fileTarget);
25 | logConfiguration.LoggingRules.Add(rule);
26 |
27 | LogManager.Configuration = logConfiguration;
28 | }
29 |
30 | internal static void OpenLogFile()
31 | {
32 | var fileTarget = LogManager.Configuration.AllTargets.OfType().FirstOrDefault();
33 |
34 | if (fileTarget == null) return;
35 |
36 | var logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now };
37 | var fileName = fileTarget.FileName.Render(logEventInfo);
38 | if (File.Exists(fileName))
39 | Process.Start(fileName);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/RdpHandler.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using System;
3 | using System.Diagnostics;
4 |
5 | namespace KonradSikorski.Tools.RdpProtocolHandler
6 | {
7 | internal static class RdpHandler
8 | {
9 | private static readonly Logger Log = LogManager.GetCurrentClassLogger();
10 |
11 | internal static void Run(string parameter)
12 | {
13 | Log.Debug("Start RDP: " + parameter);
14 |
15 | var rdpAppPath = GetPathToRemoteDesktopApp();
16 | var rdpParametersChain = BuildParameters(parameter);
17 |
18 | Process.Start(rdpAppPath, rdpParametersChain);
19 | Log.Debug("End RDP");
20 | }
21 |
22 | private static string GetPathToRemoteDesktopApp()
23 | {
24 | return $"{Environment.GetEnvironmentVariable("systemroot")}\\system32\\mstsc.exe";
25 | }
26 |
27 | private static string BuildParameters(string parameter)
28 | {
29 | var uri = parameter.Substring("rdp://".Length).TrimEnd('/');
30 | var rdpParameters = uri.Split(',');
31 |
32 | rdpParameters[0] = $"/v:{rdpParameters[0]}";
33 | for (int i = 1; i < rdpParameters.Length; i++)
34 | {
35 | var rdpParam = rdpParameters[i];
36 | if (!string.IsNullOrWhiteSpace(rdpParam)) rdpParameters[i] = "/" + rdpParam;
37 | }
38 |
39 | var rdpParametersChain = string.Join(" ", rdpParameters);
40 | Log.Debug("rdpParametersChain: " + rdpParametersChain);
41 | return rdpParametersChain;
42 | }
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Rdp Protocol Handler")]
8 | [assembly: AssemblyDescription("Handle rdp:// uri in the system and start Remote Desktop Connection")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("Konrad Sikorski")]
11 | [assembly: AssemblyProduct("Rdp Protocol Handler")]
12 | [assembly: AssemblyCopyright("Copyright © Konrad Sikorski 2017")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("9bcaee56-8e0e-4156-9fb8-a1203e2001f9")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("2.1.0.0")]
35 | [assembly: AssemblyFileVersion("2.1.0.0")]
36 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Runtime.Versioning;
4 | using NLog;
5 |
6 | namespace KonradSikorski.Tools.RdpProtocolHandler
7 | {
8 | [SupportedOSPlatform("windows")]
9 | static class Program
10 | {
11 | private static readonly Logger Log = LogManager.GetCurrentClassLogger();
12 |
13 | [RequiresAssemblyFiles("Calls KonradSikorski.Tools.RdpProtocolHandler.Installer.Install(Boolean)")]
14 | static void Main(string[] args)
15 | {
16 | AppDomain.CurrentDomain.UnhandledException += UnhandledException;
17 | LoggerHelper.ConfigureNLog();
18 | Log.Info($"{string.Join(" | ", args)}");
19 |
20 | if (args.Length == 0) Installer.Install();
21 | else
22 | {
23 | var parameter = args[0];
24 | switch (parameter.ToLower())
25 | {
26 | case "/uninstall": Installer.Uninstall(); break;
27 | case "/install": Installer.Install(); break;
28 | case "/log": LoggerHelper.OpenLogFile(); break;
29 | case "/help":
30 | case "/?":
31 | Help();
32 | break;
33 | default:
34 | RdpHandler.Run(parameter);
35 | break;
36 | }
37 | }
38 |
39 | ConsoleWrapper.WaitForClose();
40 | }
41 |
42 | private static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
43 | {
44 | ConsoleWrapper.Alloc();
45 | Log.Error(e.ExceptionObject);
46 | ConsoleWrapper.WriteLine("Error occurred. Please check the log file for details");
47 | Environment.Exit(1);
48 | }
49 |
50 | private static void Help()
51 | {
52 | ConsoleWrapper.Alloc();
53 | ConsoleWrapper.WriteLine("For help go to: https://github.com/konradsikorski/RdpProtocolHandler");
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RDP Protocol Handler
2 | This simple app allows you to use `rdp://` uri to start remote desktop session. So you can use uri like this:
3 |
4 | `rdp://remote.server.address`
5 |
6 | and you will see Remote Desktop Connection window if you do not have saved credentials, otherwise you will be automatically connected.
7 |
8 | 
9 |
10 | ### [Release Notes and Download](https://github.com/konradsikorski/RdpProtocolHandler/releases)
11 |
12 | ## How to install
13 | Place the `.exe` file in desired location on your PC, then run it **as administrator** with `/install` parameter like this:
14 |
15 | `rdpProtocoleHandler.exe /install`
16 |
17 | After installation do not move the `.exe` file to other location. When you change the file location the protocol handler will not work until you run it again with `/install` parameter.
18 |
19 | ## How to use
20 | Just open uri which start with `rdp://` using browser or any other way.
21 |
22 | ### Uri format
23 | The uri format used by application is as following:
24 |
25 | `rdp://,,,...`
26 |
27 | Each parameter in the uri is separated by comma `,`. First parameter is always the remote server address. Other parameters are exactly the same which mstsc.exe use (except the rdp file path). To see all parameters for mstsc.exe run following command:
28 |
29 | `mstsc /?`
30 |
31 | #### Examples
32 | Run Remote Desktop with specific window width and high
33 |
34 | `rdp://remote.server.address,/w:600,/h:400`
35 |
36 | Run Remote Desktop using all monitors
37 |
38 | `rdp://remote.server.address,/multimon`
39 |
40 | ## RDP Protocol Handler parameters
41 | `rdpProtocoleHandler.exe [/install] [/uninstall] [/log] [/help] [/?]`
42 |
43 | Parameter | Description
44 | -------------- | -------------
45 | /install | Run the installation procedure and register the rdp uri handler. **Require administration privileges**
46 | /uninstall | Run the uninstallation procedure and unregister the rdp uri handler. **Require administration privileges**
47 | /log | Open the log file
48 | /help | Open the help
49 | /? | Open the help
50 |
51 | #### Examples
52 | Install rdp uri handler
53 |
54 | `rdpProtocoleHandler.exe /install`
55 |
56 | Uninstall rdp uri handler
57 |
58 | `rdpProtocoleHandler.exe /uninstall`
59 |
60 | ## Log file
61 | The app logs its usages to file using [NLog](http://nlog-project.org). By default, log file is created in `C:\Users\\AppData\Local\Temp\rdppotocolhandler-logs`. You can change the logging behavior by creating the NLog.config file (for details go to NLog documentation).
62 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 |
11 | build:
12 |
13 | strategy:
14 | matrix:
15 | configuration: [Release] # [Debug, Release]
16 |
17 | runs-on: windows-latest # For a list of available runner types, refer to
18 | # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
19 |
20 | env:
21 | SOLUTION_PATH: src/RdpProtocolHandler.sln
22 |
23 | steps:
24 | - name: Checkout
25 | uses: actions/checkout@v3
26 | with:
27 | fetch-depth: 0
28 |
29 | # Install the .NET Core workload
30 | - name: Install .NET Core
31 | uses: actions/setup-dotnet@v3
32 | with:
33 | dotnet-version: 7.0.x
34 |
35 | - name: Restore dependencies
36 | run: dotnet restore ${{ env.SOLUTION_PATH }}
37 |
38 | - name: Build application
39 | run: dotnet build ${{ env.SOLUTION_PATH }} --no-restore --configuration ${{ env.Configuration }}
40 | env:
41 | Configuration: ${{ matrix.configuration }}
42 |
43 | - name: Check code formatting
44 | run: dotnet format ${{ env.SOLUTION_PATH }} --severity warn --include-generated --verify-no-changes
45 |
46 | - name: Set up JDK 11
47 | uses: actions/setup-java@v3
48 | with:
49 | java-version: 11
50 | distribution: 'zulu' # Alternative distribution options are available.
51 | - uses: actions/checkout@v3
52 | with:
53 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
54 |
55 | - name: Cache SonarCloud packages
56 | uses: actions/cache@v3
57 | with:
58 | path: ~\sonar\cache
59 | key: ${{ runner.os }}-sonar
60 | restore-keys: ${{ runner.os }}-sonar
61 |
62 | - name: Cache SonarCloud scanner
63 | id: cache-sonar-scanner
64 | uses: actions/cache@v3
65 | with:
66 | path: .\.sonar\scanner
67 | key: ${{ runner.os }}-sonar-scanner
68 | restore-keys: ${{ runner.os }}-sonar-scanner
69 |
70 | - name: Install SonarCloud scanner
71 | if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
72 | shell: powershell
73 | run: |
74 | New-Item -Path .\.sonar\scanner -ItemType Directory
75 | dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
76 |
77 | - name: Build and analyze
78 | env:
79 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
80 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
81 | shell: powershell
82 | run: |
83 | .\.sonar\scanner\dotnet-sonarscanner begin /k:"konradsikorski_RdpProtocolHandler" /o:"konrad" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
84 | dotnet build ${{ env.SOLUTION_PATH }}
85 | .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
86 |
--------------------------------------------------------------------------------
/src/RdpProtocolHandler/Installer.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using NLog;
3 | using System;
4 | using System.Diagnostics;
5 | using System.Diagnostics.CodeAnalysis;
6 | using System.IO;
7 | using System.Reflection;
8 | using System.Runtime.Versioning;
9 | using System.Security.Principal;
10 |
11 | namespace KonradSikorski.Tools.RdpProtocolHandler
12 | {
13 | [SupportedOSPlatform("windows")]
14 | internal static class Installer
15 | {
16 | private static readonly Logger Log = LogManager.GetCurrentClassLogger();
17 | private const string REGISTRY_KEY_NAME = "RDP";
18 |
19 | internal static void Uninstall()
20 | {
21 | ConsoleWrapper.Alloc();
22 | if (!RequireAdministratorPrivileges()) return;
23 |
24 | Registry.ClassesRoot.DeleteSubKeyTree(REGISTRY_KEY_NAME, false);
25 | ConsoleWrapper.WriteLine("RDP Protocol Handler uninstalled.");
26 | Log.Info("RDP Protocol Handler uninstalled.");
27 | }
28 |
29 | [RequiresAssemblyFiles("Calls System.Reflection.Assembly.Location")]
30 | internal static void Install()
31 | {
32 | ConsoleWrapper.Alloc();
33 |
34 | if (!RequireAdministratorPrivileges()) return;
35 |
36 | Uninstall();
37 |
38 | //-- get assembly info
39 | var handlerLocation = GetAppPath();
40 |
41 | //-- create registry structure
42 | var rootKey = Registry.ClassesRoot.CreateSubKey(REGISTRY_KEY_NAME);
43 | var defaultIconKey = rootKey?.CreateSubKey("DefaultIcon");
44 | var commandKey = rootKey?.CreateSubKey("shell")?.CreateSubKey("open")?.CreateSubKey("command");
45 |
46 | rootKey?.SetValue("", "rdp:Remote Desktop Protocol");
47 | rootKey?.SetValue("URL Protocol", "");
48 | defaultIconKey?.SetValue("", @"C:\Windows\System32\mstsc.exe");
49 | commandKey?.SetValue("", $@"""{handlerLocation}"" ""%1""");
50 |
51 | //--
52 | Log.Info("RDP Protocol Handler installed");
53 | ConsoleWrapper.WriteLine("RDP Protocol Handler installed");
54 | ConsoleWrapper.WriteLine($"WARNING: Do not move this file '{handlerLocation}' to other location, otherwise handler will not work. If you change the location run installation process again.");
55 | }
56 |
57 | private static string GetAppPath()
58 | {
59 | // Get filename
60 | string fileName = Process.GetCurrentProcess().MainModule.FileName;
61 |
62 | // If published as single file, the fileName will be the temp path to the actual binary
63 | // You can use Path.GetFileName to get the executable name and combine it with AppContext.BaseDirectory
64 | if (fileName.StartsWith(Path.GetTempPath()))
65 | {
66 | var directory = AppContext.BaseDirectory;
67 | fileName = Path.Combine(directory, Path.GetFileName(fileName));
68 | }
69 |
70 | return fileName;
71 | }
72 |
73 | private static bool RequireAdministratorPrivileges()
74 | {
75 | var isAdmin = IsUserAdministrator();
76 |
77 | if (!isAdmin)
78 | {
79 | var oldColor = ConsoleWrapper.ForegroundColor;
80 | ConsoleWrapper.ForegroundColor = ConsoleColor.Red;
81 | ConsoleWrapper.WriteLine("You must be system administrator");
82 | ConsoleWrapper.ForegroundColor = oldColor;
83 | Log.Error("You must be system administrator");
84 | }
85 |
86 | return isAdmin;
87 | }
88 |
89 | private static bool IsUserAdministrator()
90 | {
91 | using (var user = WindowsIdentity.GetCurrent())
92 | {
93 | try
94 | {
95 | //get the currently logged in user
96 | var principal = new WindowsPrincipal(user);
97 | return principal.IsInRole(WindowsBuiltInRole.Administrator);
98 | }
99 | catch (UnauthorizedAccessException)
100 | {
101 | return false;
102 | }
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio.
3 | ################################################################################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 | ##
8 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
9 |
10 | # User-specific files
11 | *.rsuser
12 | *.suo
13 | *.user
14 | *.userosscache
15 | *.sln.docstates
16 |
17 | # User-specific files (MonoDevelop/Xamarin Studio)
18 | *.userprefs
19 |
20 | # Mono auto generated files
21 | mono_crash.*
22 |
23 | # Build results
24 | [Dd]ebug/
25 | [Dd]ebugPublic/
26 | [Rr]elease/
27 | [Rr]eleases/
28 | x64/
29 | x86/
30 | [Ww][Ii][Nn]32/
31 | [Aa][Rr][Mm]/
32 | [Aa][Rr][Mm]64/
33 | bld/
34 | [Bb]in/
35 | [Oo]bj/
36 | [Ll]og/
37 | [Ll]ogs/
38 | [Pp]ublish
39 |
40 | # Visual Studio 2015/2017 cache/options directory
41 | .vs/
42 | # Uncomment if you have tasks that create the project's static files in wwwroot
43 | #wwwroot/
44 |
45 | # Visual Studio 2017 auto generated files
46 | Generated\ Files/
47 |
48 | # MSTest test Results
49 | [Tt]est[Rr]esult*/
50 | [Bb]uild[Ll]og.*
51 |
52 | # NUnit
53 | *.VisualState.xml
54 | TestResult.xml
55 | nunit-*.xml
56 |
57 | # Build Results of an ATL Project
58 | [Dd]ebugPS/
59 | [Rr]eleasePS/
60 | dlldata.c
61 |
62 | # Benchmark Results
63 | BenchmarkDotNet.Artifacts/
64 |
65 | # .NET Core
66 | project.lock.json
67 | project.fragment.lock.json
68 | artifacts/
69 |
70 | # ASP.NET Scaffolding
71 | ScaffoldingReadMe.txt
72 |
73 | # StyleCop
74 | StyleCopReport.xml
75 |
76 | # Files built by Visual Studio
77 | *_i.c
78 | *_p.c
79 | *_h.h
80 | *.ilk
81 | *.meta
82 | *.obj
83 | *.iobj
84 | *.pch
85 | *.pdb
86 | *.ipdb
87 | *.pgc
88 | *.pgd
89 | *.rsp
90 | *.sbr
91 | *.tlb
92 | *.tli
93 | *.tlh
94 | *.tmp
95 | *.tmp_proj
96 | *_wpftmp.csproj
97 | *.log
98 | *.tlog
99 | *.vspscc
100 | *.vssscc
101 | .builds
102 | *.pidb
103 | *.svclog
104 | *.scc
105 |
106 | # Chutzpah Test files
107 | _Chutzpah*
108 |
109 | # Visual C++ cache files
110 | ipch/
111 | *.aps
112 | *.ncb
113 | *.opendb
114 | *.opensdf
115 | *.sdf
116 | *.cachefile
117 | *.VC.db
118 | *.VC.VC.opendb
119 |
120 | # Visual Studio profiler
121 | *.psess
122 | *.vsp
123 | *.vspx
124 | *.sap
125 |
126 | # Visual Studio Trace Files
127 | *.e2e
128 |
129 | # TFS 2012 Local Workspace
130 | $tf/
131 |
132 | # Guidance Automation Toolkit
133 | *.gpState
134 |
135 | # ReSharper is a .NET coding add-in
136 | _ReSharper*/
137 | *.[Rr]e[Ss]harper
138 | *.DotSettings.user
139 |
140 | # TeamCity is a build add-in
141 | _TeamCity*
142 |
143 | # DotCover is a Code Coverage Tool
144 | *.dotCover
145 |
146 | # AxoCover is a Code Coverage Tool
147 | .axoCover/*
148 | !.axoCover/settings.json
149 |
150 | # Coverlet is a free, cross platform Code Coverage Tool
151 | coverage*.json
152 | coverage*.xml
153 | coverage*.info
154 |
155 | # Visual Studio code coverage results
156 | *.coverage
157 | *.coveragexml
158 |
159 | # NCrunch
160 | _NCrunch_*
161 | .*crunch*.local.xml
162 | nCrunchTemp_*
163 |
164 | # MightyMoose
165 | *.mm.*
166 | AutoTest.Net/
167 |
168 | # Web workbench (sass)
169 | .sass-cache/
170 |
171 | # Installshield output folder
172 | [Ee]xpress/
173 |
174 | # DocProject is a documentation generator add-in
175 | DocProject/buildhelp/
176 | DocProject/Help/*.HxT
177 | DocProject/Help/*.HxC
178 | DocProject/Help/*.hhc
179 | DocProject/Help/*.hhk
180 | DocProject/Help/*.hhp
181 | DocProject/Help/Html2
182 | DocProject/Help/html
183 |
184 | # Click-Once directory
185 | publish/
186 |
187 | # Publish Web Output
188 | *.[Pp]ublish.xml
189 | *.azurePubxml
190 | # Note: Comment the next line if you want to checkin your web deploy settings,
191 | # but database connection strings (with potential passwords) will be unencrypted
192 | *.pubxml
193 | *.publishproj
194 |
195 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
196 | # checkin your Azure Web App publish settings, but sensitive information contained
197 | # in these scripts will be unencrypted
198 | PublishScripts/
199 |
200 | # NuGet Packages
201 | *.nupkg
202 | # NuGet Symbol Packages
203 | *.snupkg
204 | # The packages folder can be ignored because of Package Restore
205 | **/[Pp]ackages/*
206 | # except build/, which is used as an MSBuild target.
207 | !**/[Pp]ackages/build/
208 | # Uncomment if necessary however generally it will be regenerated when needed
209 | #!**/[Pp]ackages/repositories.config
210 | # NuGet v3's project.json files produces more ignorable files
211 | *.nuget.props
212 | *.nuget.targets
213 |
214 | # Microsoft Azure Build Output
215 | csx/
216 | *.build.csdef
217 |
218 | # Microsoft Azure Emulator
219 | ecf/
220 | rcf/
221 |
222 | # Windows Store app package directories and files
223 | AppPackages/
224 | BundleArtifacts/
225 | Package.StoreAssociation.xml
226 | _pkginfo.txt
227 | *.appx
228 | *.appxbundle
229 | *.appxupload
230 |
231 | # Visual Studio cache files
232 | # files ending in .cache can be ignored
233 | *.[Cc]ache
234 | # but keep track of directories ending in .cache
235 | !?*.[Cc]ache/
236 |
237 | # Others
238 | ClientBin/
239 | ~$*
240 | *~
241 | *.dbmdl
242 | *.dbproj.schemaview
243 | *.jfm
244 | *.pfx
245 | *.publishsettings
246 | orleans.codegen.cs
247 |
248 | # Including strong name files can present a security risk
249 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
250 | #*.snk
251 |
252 | # Since there are multiple workflows, uncomment next line to ignore bower_components
253 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
254 | #bower_components/
255 |
256 | # RIA/Silverlight projects
257 | Generated_Code/
258 |
259 | # Backup & report files from converting an old project file
260 | # to a newer Visual Studio version. Backup files are not needed,
261 | # because we have git ;-)
262 | _UpgradeReport_Files/
263 | Backup*/
264 | UpgradeLog*.XML
265 | UpgradeLog*.htm
266 | ServiceFabricBackup/
267 | *.rptproj.bak
268 |
269 | # SQL Server files
270 | *.mdf
271 | *.ldf
272 | *.ndf
273 |
274 | # Business Intelligence projects
275 | *.rdl.data
276 | *.bim.layout
277 | *.bim_*.settings
278 | *.rptproj.rsuser
279 | *- [Bb]ackup.rdl
280 | *- [Bb]ackup ([0-9]).rdl
281 | *- [Bb]ackup ([0-9][0-9]).rdl
282 |
283 | # Microsoft Fakes
284 | FakesAssemblies/
285 |
286 | # GhostDoc plugin setting file
287 | *.GhostDoc.xml
288 |
289 | # Node.js Tools for Visual Studio
290 | .ntvs_analysis.dat
291 | node_modules/
292 |
293 | # Visual Studio 6 build log
294 | *.plg
295 |
296 | # Visual Studio 6 workspace options file
297 | *.opt
298 |
299 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
300 | *.vbw
301 |
302 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
303 | *.vbp
304 |
305 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
306 | *.dsw
307 | *.dsp
308 |
309 | # Visual Studio 6 technical files
310 | *.ncb
311 | *.aps
312 |
313 | # Visual Studio LightSwitch build output
314 | **/*.HTMLClient/GeneratedArtifacts
315 | **/*.DesktopClient/GeneratedArtifacts
316 | **/*.DesktopClient/ModelManifest.xml
317 | **/*.Server/GeneratedArtifacts
318 | **/*.Server/ModelManifest.xml
319 | _Pvt_Extensions
320 |
321 | # Paket dependency manager
322 | .paket/paket.exe
323 | paket-files/
324 |
325 | # FAKE - F# Make
326 | .fake/
327 |
328 | # CodeRush personal settings
329 | .cr/personal
330 |
331 | # Python Tools for Visual Studio (PTVS)
332 | __pycache__/
333 | *.pyc
334 |
335 | # Cake - Uncomment if you are using it
336 | # tools/**
337 | # !tools/packages.config
338 |
339 | # Tabs Studio
340 | *.tss
341 |
342 | # Telerik's JustMock configuration file
343 | *.jmconfig
344 |
345 | # BizTalk build output
346 | *.btp.cs
347 | *.btm.cs
348 | *.odx.cs
349 | *.xsd.cs
350 |
351 | # OpenCover UI analysis results
352 | OpenCover/
353 |
354 | # Azure Stream Analytics local run output
355 | ASALocalRun/
356 |
357 | # MSBuild Binary and Structured Log
358 | *.binlog
359 |
360 | # NVidia Nsight GPU debugger configuration file
361 | *.nvuser
362 |
363 | # MFractors (Xamarin productivity tool) working folder
364 | .mfractor/
365 |
366 | # Local History for Visual Studio
367 | .localhistory/
368 |
369 | # Visual Studio History (VSHistory) files
370 | .vshistory/
371 |
372 | # BeatPulse healthcheck temp database
373 | healthchecksdb
374 |
375 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
376 | MigrationBackup/
377 |
378 | # Ionide (cross platform F# VS Code tools) working folder
379 | .ionide/
380 |
381 | # Fody - auto-generated XML schema
382 | FodyWeavers.xsd
383 |
384 | # VS Code files for those working on multiple tools
385 | .vscode/*
386 | !.vscode/settings.json
387 | !.vscode/tasks.json
388 | !.vscode/launch.json
389 | !.vscode/extensions.json
390 | *.code-workspace
391 |
392 | # Local History for Visual Studio Code
393 | .history/
394 |
395 | # Windows Installer files from build outputs
396 | *.cab
397 | *.msi
398 | *.msix
399 | *.msm
400 | *.msp
401 |
402 | # JetBrains Rider
403 | *.sln.iml
404 |
--------------------------------------------------------------------------------