Добавьте файлы проекта.
This commit is contained in:
430
ContextMenuRegistrar.cs
Normal file
430
ContextMenuRegistrar.cs
Normal file
@@ -0,0 +1,430 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using Microsoft.Win32;
|
||||
|
||||
/// <summary>
|
||||
/// Предоставляет методы для регистрации и удаления пунктов контекстного меню Windows.
|
||||
/// </summary>
|
||||
public static class ContextMenuRegistrar
|
||||
{
|
||||
#region Проверка прав администратора
|
||||
|
||||
private static void CheckAdministrator()
|
||||
{
|
||||
using WindowsIdentity identity = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(identity);
|
||||
if (!principal.IsInRole(WindowsBuiltInRole.Administrator))
|
||||
throw new UnauthorizedAccessException("Требуются права администратора.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Вспомогательный метод для регистрации с прямой командой
|
||||
|
||||
private static void RegisterWithCommand(string rootPath, string menuName, string command, List<string> createdKeys)
|
||||
{
|
||||
string shellPath = rootPath; // уже включает Shell, например @"SystemFileAssociations\.mp4\Shell"
|
||||
using (RegistryKey shellKey = Registry.ClassesRoot.CreateSubKey(shellPath))
|
||||
using (RegistryKey menuKey = shellKey.CreateSubKey(menuName))
|
||||
{
|
||||
menuKey.SetValue(null, menuName);
|
||||
using RegistryKey commandKey = menuKey.CreateSubKey("command");
|
||||
commandKey.SetValue(null, command);
|
||||
}
|
||||
createdKeys.Add($@"{shellPath}\{menuName}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Регистрация для файлов по расширениям
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для указанных расширений файлов, используя текущее приложение.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню (отображается в контекстном меню).</param>
|
||||
/// <param name="extensions">Коллекция расширений, например {".mp4", ".avi"}.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки, передаваемый перед именем файла.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или расширение.</exception>
|
||||
/// <exception cref="ArgumentNullException">extensions равно null.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации (выполнен откат).</exception>
|
||||
public static void RegisterFileExtensions(string menuName, IEnumerable<string> extensions, string commandPrefix = "")
|
||||
{
|
||||
string appPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
RegisterFileExtensionsForExe(menuName, extensions, appPath, commandPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для указанных расширений файлов с заданным исполняемым файлом.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="extensions">Коллекция расширений.</param>
|
||||
/// <param name="exePath">Полный путь к исполняемому файлу.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню, расширение или путь к exe.</exception>
|
||||
/// <exception cref="ArgumentNullException">extensions равно null.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации (выполнен откат).</exception>
|
||||
public static void RegisterFileExtensionsForExe(string menuName, IEnumerable<string> extensions, string exePath, string commandPrefix = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(exePath))
|
||||
throw new ArgumentException("Путь к исполняемому файлу не может быть пустым.", nameof(exePath));
|
||||
commandPrefix ??= "";
|
||||
string command = $"\"{exePath}\"{(string.IsNullOrEmpty(commandPrefix) ? "" : " " + commandPrefix)} \"%1\"";
|
||||
RegisterFileExtensionsCommand(menuName, extensions, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для указанных расширений файлов с заданной полной командой.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="extensions">Коллекция расширений.</param>
|
||||
/// <param name="command">Полная командная строка, которая будет записана в ключ "command".</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню, расширение или пустая команда.</exception>
|
||||
/// <exception cref="ArgumentNullException">extensions равно null.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации (выполнен откат).</exception>
|
||||
public static void RegisterFileExtensionsCommand(string menuName, IEnumerable<string> extensions, string command)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
if (extensions == null)
|
||||
throw new ArgumentNullException(nameof(extensions));
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
throw new ArgumentException("Команда не может быть пустой.", nameof(command));
|
||||
|
||||
List<string> createdKeys = [];
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string ext in extensions)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ext) || !ext.StartsWith("."))
|
||||
throw new ArgumentException($"Некорректное расширение: '{ext}'. Должно начинаться с точки.", nameof(extensions));
|
||||
|
||||
string shellPath = $@"SystemFileAssociations\{ext}\Shell";
|
||||
RegisterWithCommand(shellPath, menuName, command, createdKeys);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Откат: удаляем созданные ключи
|
||||
foreach (string keyPath in createdKeys)
|
||||
{
|
||||
try { Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false); } catch { }
|
||||
}
|
||||
throw new InvalidOperationException($"Ошибка при регистрации: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет ранее зарегистрированный пункт меню для указанных расширений файлов.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="extensions">Коллекция расширений.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или расширение.</exception>
|
||||
/// <exception cref="ArgumentNullException">extensions равно null.</exception>
|
||||
/// <exception cref="InvalidOperationException">Не удалось удалить одно или несколько расширений.</exception>
|
||||
public static void UnregisterFileExtensions(string menuName, IEnumerable<string> extensions)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
if (extensions == null)
|
||||
throw new ArgumentNullException(nameof(extensions));
|
||||
|
||||
List<string> errors = [];
|
||||
foreach (string ext in extensions)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ext) || !ext.StartsWith("."))
|
||||
throw new ArgumentException($"Некорректное расширение: '{ext}'. Должно начинаться с точки.", nameof(extensions));
|
||||
|
||||
string keyPath = $@"SystemFileAssociations\{ext}\Shell\{menuName}";
|
||||
try
|
||||
{
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false);
|
||||
}
|
||||
catch (ArgumentException) { /* ключ не существует – игнорируем */ }
|
||||
catch (Exception ex)
|
||||
{
|
||||
errors.Add($"{ext}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
if (errors.Any())
|
||||
throw new InvalidOperationException("Не удалось удалить некоторые расширения: " + string.Join("; ", errors));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Регистрация для всех файлов
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для всех файлов, используя текущее приложение.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterAllFiles(string menuName, string commandPrefix = "")
|
||||
{
|
||||
string appPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
RegisterAllFilesForExe(menuName, appPath, commandPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для всех файлов с заданным исполняемым файлом.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="exePath">Полный путь к исполняемому файлу.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или путь к exe.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterAllFilesForExe(string menuName, string exePath, string commandPrefix = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(exePath))
|
||||
throw new ArgumentException("Путь к исполняемому файлу не может быть пустым.", nameof(exePath));
|
||||
commandPrefix ??= "";
|
||||
string command = $"\"{exePath}\"{(string.IsNullOrEmpty(commandPrefix) ? "" : " " + commandPrefix)} \"%1\"";
|
||||
RegisterAllFilesCommand(menuName, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для всех файлов с заданной полной командой.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="command">Полная командная строка, которая будет записана в ключ "command".</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или пустая команда.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterAllFilesCommand(string menuName, string command)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
throw new ArgumentException("Команда не может быть пустой.", nameof(command));
|
||||
|
||||
List<string> createdKeys = [];
|
||||
try
|
||||
{
|
||||
string shellPath = @"*\Shell";
|
||||
RegisterWithCommand(shellPath, menuName, command, createdKeys);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (string keyPath in createdKeys)
|
||||
{
|
||||
try { Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false); } catch { }
|
||||
}
|
||||
throw new InvalidOperationException($"Ошибка при регистрации: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет пункт меню для всех файлов.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
public static void UnregisterAllFiles(string menuName)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
|
||||
string keyPath = $@"*\Shell\{menuName}";
|
||||
try
|
||||
{
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false);
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Регистрация для папок (щелчок на иконке папки)
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для папок (появляется при щелчке на иконке папки), используя текущее приложение.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderShell(string menuName, string commandPrefix = "")
|
||||
{
|
||||
string appPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
RegisterFolderShellForExe(menuName, appPath, commandPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для папок с заданным исполняемым файлом.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="exePath">Полный путь к исполняемому файлу.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или путь к exe.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderShellForExe(string menuName, string exePath, string commandPrefix = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(exePath))
|
||||
throw new ArgumentException("Путь к исполняемому файлу не может быть пустым.", nameof(exePath));
|
||||
commandPrefix ??= "";
|
||||
string command = $"\"{exePath}\"{(string.IsNullOrEmpty(commandPrefix) ? "" : " " + commandPrefix)} \"%1\"";
|
||||
RegisterFolderShellCommand(menuName, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для папок с заданной полной командой.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="command">Полная командная строка, которая будет записана в ключ "command".</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или пустая команда.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderShellCommand(string menuName, string command)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
throw new ArgumentException("Команда не может быть пустой.", nameof(command));
|
||||
|
||||
List<string> createdKeys = [];
|
||||
try
|
||||
{
|
||||
string shellPath = @"Directory\Shell";
|
||||
RegisterWithCommand(shellPath, menuName, command, createdKeys);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (string keyPath in createdKeys)
|
||||
{
|
||||
try { Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false); } catch { }
|
||||
}
|
||||
throw new InvalidOperationException($"Ошибка при регистрации: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет пункт меню для папок (из раздела Shell).
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
public static void UnregisterFolderShell(string menuName)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
|
||||
string keyPath = $@"Directory\Shell\{menuName}";
|
||||
try
|
||||
{
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false);
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Регистрация для фона папки (щелчок на свободном месте внутри папки)
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для фона папки (появляется при щелчке на свободном месте внутри открытой папки),
|
||||
/// используя текущее приложение. В команде рекомендуется использовать параметр "%V" для передачи пути к текущей папке.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderBackgroundShell(string menuName, string commandPrefix = "")
|
||||
{
|
||||
string appPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
RegisterFolderBackgroundShellForExe(menuName, appPath, commandPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для фона папки с заданным исполняемым файлом.
|
||||
/// В команде рекомендуется использовать параметр "%V" для передачи пути к текущей папке.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="exePath">Полный путь к исполняемому файлу.</param>
|
||||
/// <param name="commandPrefix">Необязательный префикс командной строки.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или путь к exe.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderBackgroundShellForExe(string menuName, string exePath, string commandPrefix = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(exePath))
|
||||
throw new ArgumentException("Путь к исполняемому файлу не может быть пустым.", nameof(exePath));
|
||||
commandPrefix ??= "";
|
||||
// Для фона папки рекомендуется %V
|
||||
string command = $"\"{exePath}\"{(string.IsNullOrEmpty(commandPrefix) ? "" : " " + commandPrefix)} \"%V\"";
|
||||
RegisterFolderBackgroundShellCommand(menuName, command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует пункт меню для фона папки с заданной полной командой.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <param name="command">Полная командная строка, которая будет записана в ключ "command". Рекомендуется использовать "%V".</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню или пустая команда.</exception>
|
||||
/// <exception cref="InvalidOperationException">Ошибка при регистрации.</exception>
|
||||
public static void RegisterFolderBackgroundShellCommand(string menuName, string command)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
throw new ArgumentException("Команда не может быть пустой.", nameof(command));
|
||||
|
||||
List<string> createdKeys = [];
|
||||
try
|
||||
{
|
||||
string shellPath = @"Directory\Background\Shell";
|
||||
RegisterWithCommand(shellPath, menuName, command, createdKeys);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (string keyPath in createdKeys)
|
||||
{
|
||||
try { Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false); } catch { }
|
||||
}
|
||||
throw new InvalidOperationException($"Ошибка при регистрации: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет пункт меню для фона папки.
|
||||
/// </summary>
|
||||
/// <param name="menuName">Имя пункта меню.</param>
|
||||
/// <exception cref="UnauthorizedAccessException">Приложение не запущено от имени администратора.</exception>
|
||||
/// <exception cref="ArgumentException">Некорректное имя меню.</exception>
|
||||
public static void UnregisterFolderBackgroundShell(string menuName)
|
||||
{
|
||||
CheckAdministrator();
|
||||
if (string.IsNullOrWhiteSpace(menuName))
|
||||
throw new ArgumentException("Имя пункта меню не может быть пустым.", nameof(menuName));
|
||||
|
||||
string keyPath = $@"Directory\Background\Shell\{menuName}";
|
||||
try
|
||||
{
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(keyPath, false);
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
13
ContextMenuRegistrar.csproj
Normal file
13
ContextMenuRegistrar.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
3
ContextMenuRegistrar.slnx
Normal file
3
ContextMenuRegistrar.slnx
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution>
|
||||
<Project Path="ContextMenuRegistrar.csproj" />
|
||||
</Solution>
|
||||
Reference in New Issue
Block a user