Приветствую всех, сегодня поговорим об одной интересной теме, работа с реестром.
Реестр Windows или системный реестр (Windows Registry) — иерархически построенная база данных параметров и настроек в большинстве операционных систем Microsoft Windows.
Реестр содержит информацию и настройки для аппаратного обеспечения, программного обеспечения, профилей пользователей, пред установки. Большинство изменений в Панели
управления, ассоциации файлов, системные политики, список установленного ПО фиксируются в реестре.
Windows хранит море информации о системе, настройках программ, пользователях и множество других данных в специальном хранилище— реестре. Существует возможность улучшить работу программ путем изменения параметров, содержащихся в реестре. В Интернете можно найти целый класс программ, называемых твикерами, в которых собраны различные полезные и интересные настройки, которые можно поменять в реестре, чтобы изменить функциональность программ. Не представляет труда самому написать такой
твикер при помощи управляемого кода.
Разделы реестра
- HKEY_CLASSES_ROOT – содержит информацию о ассоциациях расширения файлов и зарегистрированных COM объектах.
- HKEY_CURRENT_USER – содержит настройки для текущего пользователя.
- HKEY_LOCAL_MACHINE – содержит настройки локального компьютера.
- HKEY_USERS – содержит настройки пользователя по умолчанию.
- HKEY_CURRENT_CONFIG – содержит информацию о настройках, которые не являются специфическими для пользователя.
- HKEY_PERFORMANCE_DATA – содержит информацию о производительности программных компонентов.
- HKEY_DYN_DATA – содержит динамические изменяемые данные реестра, на данный момент является устаревшим.
Пространство имен для работы с реестром using Microsoft.Win32;
Registry — это статический класс, предоставляющий эксклюзивный доступ к ключам реестра для простых операций.
Registry — этот класс предоставляет набор стандартных корневых разделов, находящихся в реестре компьютеров, работающих под управлением Windows. Реестр является средством хранения сведений о приложениях, пользователях и стандартных системных параметрах. Например, приложения используют реестр для хранения сведений, которые необходимо сохранить после закрытия приложения и к которым необходимо получать доступ при перезагрузке приложения. Например, можно сохранять цветовые настройки, положение или размер окна. Для разных пользователей эти сведения могут сохраняться в различных местах реестра.
Класс Registry предоставляет доступ к следующим разделам:
CurrentUser – Сохраняет сведения о пользовательских параметрах.
LocalMachine – Сохраняет сведения о конфигурации для локального компьютера
ClassesRoot – Сохраняет сведения о типах (и классах) и их свойствах.
Users – Сохраняет сведения о стандартной пользовательской конфигурации.
PerformanceData – Сохраняет сведения о производительности программных компонентов.
CurrentConfig – Сохраняет сведения об оборудовании, не являющемся специфическим для пользователя.
DynData – Сохраняет динамические данные (Считается устаревшим).
RegistryKey — класс реализует методы для просмотра дочерних ключей, создания новых или чтения и модификации существующих, включая установку уровней безопасности для них.
Чтение из реестра осуществляется при помощи метода GetValue, узел должен быть предварительно открыт при помощи метода OpenSubKey.
Запись данных в реестр осуществляется при помощи метода SetValue, узел должен существовать и быть предварительно открытым при помощи метода OpenSubKey с указанием признака «открытие для записи».
Выводим информацию о структуре реестра:
static void Main()
{
// Registry - это класс, предоставляющий эксклюзивный доступ к ключам реестра для простых операций.
// RegistryKey - класс реализует методы для просмотра дочерних ключей, создания новых или чтения и модификации существующих,
// включая установку уровней безопасности для них.
RegistryKey[] regKeyArray = new RegistryKey[] { Registry.ClassesRoot,
Registry.CurrentUser,
Registry.LocalMachine,
Registry.Users,
Registry.CurrentConfig,
Registry.PerformanceData
// Registry.DynData // Устарел.
};
foreach (RegistryKey regKey in regKeyArray)
{
Console.WriteLine("{0} - всего элементов: {1}.", regKey.Name, regKey.SubKeyCount);
}
// Задержка на экране.
Console.ReadKey();
}
Навигация по реестру:
static void Main()
{
// Процесс получения ссылки на объект RegistryKey называется открытием ключа.
RegistryKey myKey = Registry.LocalMachine;
RegistryKey software = myKey.OpenSubKey("Software");
RegistryKey microsoft = software.OpenSubKey("Microsoft");
// software.Close();
Console.WriteLine("{0} - всего элементов: {1}.", microsoft.Name, microsoft.SubKeyCount);
microsoft.Close();
// Попытка открыть несуществующий ключ. Переменной будет присвоено значение NULL.
software = myKey.OpenSubKey("nookery");
// В блоке try совершается попытка обратится к переменной, значение которой не присвоено.
try
{
Console.WriteLine("Открыли узел: {0}.", software.Name);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.GetType());
}
// Задержка на экране.
Console.ReadKey();
}
Редактирование реестра.
Добавляем запись.
static void Main()
{
// В этот раз открываем специально для записи.
RegistryKey myKey = Registry.CurrentUser;
// Второй аргумент (true) говорит о том, что будет совершаться запись.
RegistryKey wKey = myKey.OpenSubKey("Software", true);
try
{
Console.WriteLine("Всего записей в {0}: {1}.", wKey.Name, wKey.SubKeyCount);
// пытаемся создать новый ключ.
RegistryKey newKey = wKey.CreateSubKey("nookery.ru");
// Запись прошла успешно в HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node
Console.WriteLine("Запись \'{0}\' успешно внесена в реестр!", newKey.Name);
Console.WriteLine("Теперь записей стало: {0}.", wKey.SubKeyCount);
}
catch (Exception e)
{
// Если возникает проблема - выводим сообщение о ней на экран.
Console.WriteLine(e.Message);
}
finally
{
// Закрыть ключ нужно обязательно.
myKey.Close();
}
// Задержка на экране.
Console.ReadKey();
}
Удаляем запись
static void Main()
{
RegistryKey myKey = Registry.CurrentUser;
// Для удаления тоже нужно иметь права редактирования.
RegistryKey wKey = myKey.OpenSubKey("Software", true);
// Вывод на экран всего содержимого ключа поименно.
string[] keyNameArray = wKey.GetSubKeyNames();
foreach (string name in keyNameArray)
{
Console.ForegroundColor = ConsoleColor.Gray;
if (name.Contains("nookery"))
{
Console.ForegroundColor = ConsoleColor.Red;
}
Console.WriteLine(new string(' ', 5) + name);
}
// Теперь пытаемся удалить ключ.
try
{
Console.WriteLine("Всего записей в {0}: {1}.", wKey.Name, wKey.SubKeyCount);
wKey.DeleteSubKey("nookery");
Console.WriteLine("Запись \'nookery\' успешно удалена из реестра!");
Console.WriteLine("Теперь записей стало: {0}.", wKey.SubKeyCount);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
wKey.Close();
}
// Задержка на экране.
Console.ReadKey();
}
Читаем ключи реестра:
static void Main()
{
// Совершаем навигацию по реестру и открываем ключ для чтения,
// можно сразу указать весь путь, а не совершать навигацию поэтапно.
RegistryKey myKey = Registry.CurrentUser;
RegistryKey wKey = myKey.OpenSubKey(@"Software\nookery");
// Читаем данные и конвертируем в нужный формат.
string Str = wKey.GetValue("TheStringName") as string;
int Int = Convert.ToInt32(wKey.GetValue("TheInt32Name"));
int Ant = Convert.ToInt32(wKey.GetValue("AnotherName"));
wKey.Close();
// Покажем содержимое, чтобы убедиться в том, что чтение прошло успешно.
Console.WriteLine("String: {0}\nInt32: {1}\nAnother: {2}", Str, Int, Ant);
// Задержка.
Console.ReadKey();
}
Пример добавления программы в автозагрузку:
RegistryKey myKey =
Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
myKey.SetValue("MyProgram", Application.ExecutablePath);
Стоит также уделить больше внимания удалению, метод DeleteSubKey не имеет рекурсивного вызова, это означает что вам придется в начале удалить подраздел, а уже потом сам раздел.
string registryLocation = @"Software\Microsoft\Windows\CurrentVersion\Uninstall";
RegistryKey regKey = (Registry.LocalMachine).OpenSubKey(registryLocation, true);
RegistryKey progKey = regKey.OpenSubKey(progName);
// Если у нас такая ветка реестра есть
if (progKey != null)
{
// Удаляем данные о программе
regKey.DeleteSubKey(progName);
}
Пример поиска по реестру параметра по разделам с помощью рекурсии, к сожалению доступ к некоторым веткам запрещен, да же под админом, пришлось использовать try cath
//Этот блок кода у меня находится в LoadForm
//RegistryKey[] key = {Registry.ClassesRoot,Registry.CurrentConfig,
// Registry.LocalMachine, Registry.CurrentUser,Registry.Users};
/// comboBox1.DataSource = key;
/// <summary>
/// запуск поиска параметра
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void BtnSearchValue_Click(object sender, EventArgs e)
{
RegistryKey key = (RegistryKey)comboBox1.SelectedItem;
txtPath.Text = await Task.Run(() => Find(key));
}
/// <summary>
/// передача сообщения в lable
/// </summary>
/// <param name="ctrl"></param>
/// <param name="execute"></param>
void MarshalToUIThread(Control ctrl, Action execute)
{
ctrl.BeginInvoke(execute);
}
/// <summary>
/// Метод поиска по параметру среди всех разделов, рекурсивным вызовом
/// </summary>
/// <param name="oneKey"></param>
/// <returns></returns>
private string Find(RegistryKey oneKey)
{
foreach (var item in oneKey.GetSubKeyNames())
{
try
{
RegistryKey twoKey = oneKey.OpenSubKey(item, false);
string[] nameArgs = twoKey.GetSubKeyNames();
var valNameOne = twoKey.GetValueNames();
MarshalToUIThread(lbInfo, () => { lbInfo.Text = twoKey.Name; });
for (int i = 0; i < valNameOne.Length; i++)
{
if (valNameOne[i] == txtArgs2.Text)
{
var rr = twoKey.GetSubKeyNames();
}
}
for (int i = 0; i < nameArgs.Length; i++)
{
try
{
RegistryKey three = twoKey.OpenSubKey(nameArgs[i], false);
var valNameTwo = three?.GetValueNames();
MarshalToUIThread(lbInfo, () => { lbInfo.Text = twoKey.Name; });
for (int q = 0; q < valNameTwo.Length; q++)
{
if (valNameTwo[q] == txtArgs2.Text)
{
return three.Name;
}
}
Find(three);
}
catch { }
}
}
catch { }
}
return "Не найдено";
}
Начиная с выходом windows 8 ограничили права приложений с работой реестра, в целях безопасности и теперь для того что бы ваша приложения внесла какие либо изменения необходимо ее запускать с правами администратора.
Можно пойти 3 путями:
- Приобрести сертификат, который будет выдан вам как разработчику и вы будете зарегистрированы.
- Продолжать запуск программ от имени администратора.
- Создать манифест, который будет сообщать пользователю при попытки запуска программы о том что ее надо запустить от имении администратора.
Как создать такой манифест читать <тут>
Еще очень важный момент если у вас 64бит система то путь сохранения будет отличатся от 32бит к примеру к разделу software, так как данные будут хранится в разделе Software\WOW6432Node. Что бы программа сохраняло по пути Software , можно использовать следующий код:
var hkcu = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
