/// <summary> /// Gets the class of the given file extension, optionally creating it if it does not exist. /// </summary> /// <param name="classesKey">The classes key (HKEY_CLASSES_ROOT).</param> /// <param name="fileExtension">The file extension, with a leading dot.</param> /// <param name="createIfMissing">if set to <c>true</c> then if no class exists, one will be created.</param> /// <returns></returns> /// <exception cref="InvalidOperationException">Thrown if the extension is invalid.</exception> public static string Get(IRegistryKey classesKey, string fileExtension, bool createIfMissing) { // Make sure that we have a file extension, a string which starts with a dot and // has at least one character following it. if (string.IsNullOrEmpty(fileExtension) || fileExtension.StartsWith(".") == false || fileExtension.Length < 2) { throw new InvalidOperationException($@"'{fileExtension}' does not appear to be a valid file extension class."); } // We will need the extension with no leading dot later. var extension = fileExtension.Substring(1); // Open or create the file extension key. using (var fileExtensionClassKey = classesKey.CreateSubKey(fileExtension, RegistryKeyPermissionCheck.ReadWriteSubTree)) { // Get the class, which is the 'default' value. If we've got a value, we're done. var fileExtensionClassName = fileExtensionClassKey.GetValue(null) as string; if (!string.IsNullOrEmpty(fileExtensionClassName)) { return(fileExtensionClassName); } // We don't have a class for the extension. If we are *not* creating missing ones, we're done. if (!createIfMissing) { return(null); } // There is no file extension class name, so we'll have to create one. Set the desired class name. fileExtensionClassName = $"{extension}.1"; // e.g. 'dllfile', 'mytypefile' // If the desired class name exists, we're going to have to bail out (we could try and find another // name, but that starts to get difficult for users to reason about). using (var fileExtensionClassNameKey = classesKey.OpenSubKey(fileExtensionClassName)) { if (fileExtensionClassNameKey != null) { var applicationName = fileExtensionClassNameKey.GetValue(null) as string; throw new InvalidOperationException( $@"Unable to create a new class '{fileExtensionClassName}' for extension '{fileExtension}'. That class is already in use by application '{applicationName}'."); } } // Create the file extension class name key, point the file extension to it, set a sensible name for the application and we're done. using (var fileExtensionClassNameKey = classesKey.CreateSubKey(fileExtensionClassName, RegistryKeyPermissionCheck.ReadWriteSubTree)) { fileExtensionClassKey.SetValue(null, fileExtensionClassName); fileExtensionClassNameKey.SetValue(null, $"{extension} Application"); return(fileExtensionClassName); } } }
/// <summary> /// Sets the icon handler default icon, enabling an icon handler extension. /// </summary> /// <param name="classesKey">The classes key.</param> /// <param name="className">Name of the class.</param> private static void SetIconHandlerDefaultIcon(IRegistryKey classesKey, string className) { // Open the class. using (var classKey = classesKey.OpenSubKey(className)) { // Check we have the class. if (classKey == null) { throw new InvalidOperationException("Cannot open class " + className); } // Open the default icon. using (var defaultIconKey = classKey.OpenSubKey(KeyName_DefaultIcon, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ReadKey | RegistryRights.WriteKey)) { // Check we have the key. if (defaultIconKey == null) { // if not, we create the key. var tempDefaultIconKey = classesKey.CreateSubKey(className + @"\" + KeyName_DefaultIcon, RegistryKeyPermissionCheck.ReadWriteSubTree); tempDefaultIconKey.SetValue(null, "%1"); } else { // Get the default icon. var defaultIcon = defaultIconKey.GetValue(null, string.Empty).ToString(); // Save the default icon. defaultIconKey.SetValue(ValueName_DefaultIconBackup, defaultIcon); defaultIconKey.SetValue(null, "%1"); } } } }
public IRegistryKey CreateKey(string keyPath, RegistryKeyPermissionCheck permissionCheck = default) { IRegistryKey cleanUpKey = null; if (!keyPath.Contains(RegistryPathDelimiter)) { throw new ArgumentException("Can not create a root key itself", nameof(keyPath)); } try { IRegistryKey root = GetCorrespondingRoot(keyPath); string openKeyName = keyPath.MustEndWith(RegistryPathDelimiter).Remove(root.Name.MustEndWith(RegistryPathDelimiter)); cleanUpKey = root; if (openKeyName.IsNullOrWhitespace()) { throw new ArgumentException("Can not create a root key itself", nameof(keyPath)); } IRegistryKey key = root.CreateSubKey(openKeyName, permissionCheck); return(key); } finally { cleanUpKey?.Dispose(); } }
private IRegistryKey?OpenKey(string rootName, string keyPath, bool writing = false) { IRegistryKey root = GetRootKey(rootName, this.registry); return(writing ? root.CreateSubKey(keyPath) : root.OpenSubKey(keyPath)); }
/// <summary> /// Copy a registry key. The parentKey must be writeable. /// </summary> /// <param name="parentKey"></param> /// <param name="keyNameToCopy"></param> /// <param name="newKeyName"></param> /// <returns></returns> public bool CopyKey(IRegistryKey parentKey, string keyNameToCopy, string newKeyName) { //Create new key var destinationKey = parentKey.CreateSubKey(newKeyName); //Open the sourceKey we are copying from var sourceKey = parentKey.OpenSubKey(keyNameToCopy); RecurseCopyKey(sourceKey, destinationKey); return(true); }
private static void AddValue(IRegistryKey baseKey, bool policy, object value) { if (string.IsNullOrEmpty(value.ToString())) { return; } const string zoneKeyTemplate = @"SOFTWARE\{0}Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1"; var zoneKey = string.Format(zoneKeyTemplate, policy ? @"Policies\" : ""); var key = baseKey.CreateSubKey(zoneKey); key.SetValue("2500", value, RegistryValueKind.DWord); }
private void RecurseCopyKey(IRegistryKey sourceKey, IRegistryKey destinationKey) { //copy all the values foreach (var valueName in sourceKey.GetValueNames()) { var objValue = sourceKey.GetValue(valueName); var valKind = sourceKey.GetValueKind(valueName); destinationKey.SetValue(valueName, objValue, valKind); } //For Each subKey //Create a new subKey in destinationKey //Call myself foreach (var sourceSubKeyName in sourceKey.GetSubKeyNames()) { var sourceSubKey = sourceKey.OpenSubKey(sourceSubKeyName); var destSubKey = destinationKey.CreateSubKey(sourceSubKeyName); RecurseCopyKey(sourceSubKey, destSubKey); } }
/// <summary> /// Saves the active changes to the current theme. /// /// This is needed to be performed before enabling high-contrast because when high-contrast is de-activated it /// loads the settings (such as the wallpaper) from the last used .theme file, rather than the applied settings. /// /// These means, any unsaved theme customisations will be lost. /// /// Theme files are described in https://docs.microsoft.com/en-us/windows/desktop/controls/themesfileformat-overview /// </summary> /// <param name="currentThemeFile"> /// The current theme file used by the OS. This will be used as a base to create a new theme file, and currently /// applied settings will be added to it.</param> /// <param name="saveAs">The file to write the saved theme to.</param> private async Task SaveCurrentTheme(string currentThemeFile, string saveAs) { this.logger.LogInformation($"Saving current theme, using {currentThemeFile}."); bool isValid = false; Dictionary <string, string>?themeData = null; try { // Read the .theme file that's currently being used. Ini themeReader = new(); await themeReader.ReadFile(currentThemeFile); themeData = themeReader.ReadData(); isValid = themeData.ContainsKey("MasterThemeSelector.MTSM"); } catch (IOException e) { this.logger.LogInformation(e, $"Unable to read {currentThemeFile}."); } if (!isValid || themeData is null) { string defaultTheme = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "resources\\Themes\\aero.theme"); if (currentThemeFile != defaultTheme) { // OBSERVATION: this code is re-entrant; also note that if the aero.theme file is corrupt...this might reenter infinitely until the stack was full await this.SaveCurrentTheme(defaultTheme, saveAs); } return; } else if (themeData.ContainsKey("VisualStyles.HighContrast")) { // Only save the current theme if it is not high-contrast. return; } using IRegistryKey hKeyCurrentUser = this.registry.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default); // Wallpaper using IRegistryKey desktopKey = hKeyCurrentUser.OpenSubKey(@"Control Panel\Desktop", false); themeData["Theme.DisplayName"] = "morphic"; themeData["Control Panel\\Desktop.Wallpaper"] = desktopKey.GetValue("WallPaper")?.ToString() ?? string.Empty; themeData["Control Panel\\Desktop.TileWallpaper"] = desktopKey.GetValue("TileWallPaper")?.ToString() ?? string.Empty; themeData["Control Panel\\Desktop.WallpaperStyle"] = desktopKey.GetValue("WallPaperStyle")?.ToString() ?? string.Empty; using IRegistryKey wallpapersKey = hKeyCurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers"); string?backgroundType = wallpapersKey.GetValue("backgroundType")?.ToString(); if (backgroundType != "2") { // It's not a slide-show, remove the entire section. themeData.Keys.Where(k => k.StartsWith("Slideshow")) .ToList() .ForEach(k => themeData.Remove(k)); } // Colours using IRegistryKey colorsKey = hKeyCurrentUser.OpenSubKey(@"Control Panel\Colors"); foreach (string valueName in colorsKey.GetValueNames()) { if (colorsKey.GetValue(valueName, null) is string value) { themeData[$"Control Panel\\Colors.{valueName}"] = value; } } // if the directory for the saveAs file doesn't exist, create it now var saveAsPath = Path.GetDirectoryName(saveAs); if (Directory.Exists(saveAsPath) == false) { Directory.CreateDirectory(saveAsPath); } Ini writer = new(); await writer.ReadFile(currentThemeFile); writer.WriteData(themeData !); await writer.WriteFile(saveAs); // Make windows use this theme file when restoring high-contrast. using IRegistryKey highContrastKey = hKeyCurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\HighContrast"); highContrastKey.SetValue("Pre-High Contrast Scheme", saveAs); }