Часть вторая
Мы с вами продолжим писать собственный твикер - утилиту для тонкой настройки системы. В этой части статьи вас ждут дальнейшие разбирательства с кодом твикера на языке C#.
Прежде чем приступать непосредственно к продолжению нашего с вами разговора о написании этой утилиты, кратко напомню, так сказать, "содержание первой серии". А в первой части статьи я, на самом-то деле, успел рассказать совсем немного, поскольку занимался разъяснением того, для чего нужна каждая переменная в коде нашей с вами программы, и размышлениями о том, какой именно спецификатор доступа нужен для каждой из них. Также мы с вами успели рассмотреть код, ответственный за определение того, является ли один конкретный "твик" включенным, или же всё обстоит совершенно наоборот.
Что ж, в этой части статьи о твикере, надеюсь, на всякую мелочь будем тратить уже меньше времени - во-первых, потому что уже не надо будет останавливаться на объяснении назначения глобальных переменных, а во-вторых, потому что вступление в этой части статьи будет существенно короче. Оно, собственно говоря, уже закончилось - давайте уже, пожалуй, приступим к разбору программного кода.
Внесение изменений в реестр
С реестром в C# мы уже, по большому счёту, научились работать в первой части статьи. А если конкретнее, то в том методе, в котором мы читали значения ключей реестра и сравнивали их с эталонными значениями "твикаемых" параметров (если помните, метод этот имел название CheckEnabled). Теперь давайте разберёмся с кодом, который будет вносить изменения в реестр в соответствие с тем, какие "твики" пользователь решил разрешить, а какие - запретить.
public void WriteChanges()
{
if (IsChanged == false){
return;
}
String Root = "";
String str;
RegistryKey rk;
RegistryKey rk1;
int i = 0;
while (RegistryPath[i] != '\\') {
Root += RegistryPath[i];
i++;
};
Root = Root.ToUpper();
rk = Registry.CurrentUser;
// Здесь должен быть выбор раздела реестра
str = RegistryPath;
str = str.Remove(0, Root.Length + 1);
rk1 = rk.OpenSubKey(str, true);
String Val;
if (IsEnabled){
Val = EnabledValue;
}
else
{
Val = DisabledValue;
};
rk1.SetValue(KeyName, Val);
return Result;
}
Итак, давайте теперь разбираться с этим кодом. Первая осмысленная конструкция - это возврат из функции, если значение ключа не было изменено. Это ускоряет процесс внесения изменений в реестр при большом количестве "твиков" - однако при этом необходимо, чтобы реализация пользовательского интерфейса сама отлавливала, какие "твики" пользователь применяет, и устанавливала соответствующий флаг в поле IsChanged. Далее идёт кусок кода, определяющий, в какое именно место в реестре нужно писать изменения, связанные с "твиканьем" системы. Напомню, что у нас в свойствах каждого "твика" путь к нему в реестре хранится в следующем формате: "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\...". Ну, естественно, вместо HKEY_LOCAL_MACHINE может идти и любой другой корневой элемент реестра, как и вместо пути - любой другой путь к любому нужному для изменения каких-либо параметров ключу. Из-за того, что при работе с реестром в C# мы должны указывать корневой элемент в виде числовой константы, а не строки, необходимо выделять из всего пути эту часть и преобразовывать её в числовую константу. Часть кода, который за это дело отвечает, я пропустил (вместо него стоит комментарий "Здесь должен быть выбор раздела реестра"), потому что совершенно аналогичный код был приведен в предыдущей части статьи. Дальше мы открываем нужный ключ реестра, а потом занимаемся тем, что записываем в него нужное значение. Если "твик" выбран пользователем как разрешённый, в ключ записываем EnabledValue, в противном случае, само собой, пишем DisabledValue. Как видите, всё очень, очень просто.
Собственно, на этом методе разработка класса "твика" закончена. Дальше мы будем разрабатывать другой класс, который будет с "твиками" управляться. Я решил этот класс отдельно не выделять, а возложить обязанности по манипуляции с набором "твиков" на главный оконный класс приложения. Это, вообще говоря, не есть хорошо, потому что код интерфейса и бизнес-логику приложения всё же лучше разделять. Но, поскольку это просто пример, то для лучшего самостоятельного усвоения изложенного материала рекомендуется самостоятельно выделить класс для работы со списком "твиков".
Загрузка списка твиков: постановка
задачи
Этот раздел я, вообще-то, хотел отложить на потом, и на то имелась одна веская причина. Дело в том, что изначально взятый мною список "твиков" был скачан с какого-то сайта (не помню с какого - честно, а то сказал бы), где он был представлен в довольно интересном виде. Вот пример одного из этих "твиков" в его первозданном виде:
Disable "Screen Properties" If this option is enabled, Screen applet will be not avaliable from Control Panel. Requires reboot: yes Key: HKEY_CURRENT_USER\Software\Microsoft\ Windows\CurrentVersion\Policies\System\NoDispCPL Enabled: 1 Disabled: 0
В принципе, это уже довольно неплохо и практически пригодно для загрузки в программу. Тем не менее, буквально за пару минут можно сделать список, ещё более хорошо подходящий для загрузки нашим твикером. Вот как тот же самый "твик" будет выглядеть после небольшой переделки:
.Disable "Screen Properties" If this option is enabled, Screen applet will be not avaliable from Control Panel. Reboot HKEY_CURRENT_USER\Software\Microsoft\Windows\ CurrentVersion\Policies\System NoDispCPL Dword e=1 d=0 ,
Точка обозначает начало твика, запятая - это конец. Вместо Requires reboot: yes и Requires reboot: no лучше использовать Reboot и Noreboot, потому что тогда будет проще проводить парсинг файла со списком "твиков". То же относится и к разделению пути к ключу и самого ключа. Можно, конечно, было бы пойти ещё дальше и разделить также и путь с именем корневого раздела. Дам стандартную отмазку (э... рекомендацию) - лучше поэкспериментировать с этим самостоятельно, будет больше пользы.
Теперь, собственно, о том, что же меня здесь смущает. Дело в том, что лучше было бы записывать это всё не в таком странном формате, а в банальном, но более удобном XML. Кроме того, можно было бы продемонстрировать работу с XML, о которой Microsoft громко кричала ещё тогда, когда выпускала самый первый релиз платформы .NET. В общем, помучавшись немного сомнениями, решил я, что с XML'ем успеется. В крайнем случае, расскажу об этом в третьей части статьи - как об альтернативном способе записи "твиков".
Загрузка списка твиков: практика
Что ж, не буду дальше мучить вас неведением и приведу долгожданный программный код метода, загружающего "твики" в нашем твикере.
private void PrepareTweakingFeaturesList(string DataFile)
{
TweakerOption Opt_;
String str;
StreamReader fs = File.OpenText(DataFile);
int u = 0;
lst.Clear();
while ((str = fs.ReadLine()) != null) {
if (str == "") {
continue;
}
switch (str[0]) {
case ';':
break;
case '.':
str = str.Remove(0, 1);
u = 0;
Opt_ = new TweakerOption();
Opt_.OptionName = str;
u++;
break;
case ',':
lst.Add(Opt_);
u = 0;
break;
default:
switch (u) {
case 1:
Opt_.Description = str;
u++;
break;
case 2:
if (str.ToLower() == "reboot"){
Opt_.Reboot = true;
}
else {
Opt_.Reboot = false;
};
u++;
break;
case 3:
Opt_.RegistryPath = str;
u++;
break;
case 4:
Opt_.KeyName = str;
u++;
break;
case 5:
Opt_.KeyType = str.ToLower();
u++;
break;
case 6:
str = str.Remove(0, 2);
Opt_.EnabledValue = str;
u++;
break;
case 7:
str = str.Remove(0, 2);
Opt_.DisabledValue = str;
u++;
break;
case 8:
u = 0;
break;
default:
break;
}
break;
}
}
}
Ну что же, давайте разбираться с тем, что там написано. Во-первых, давайте разберёмся с переменными, используемыми в данном методе (не с глобальными, конечно, а с локальными). Opt_ - это текущий "твик", данные которого мы считываем из файла в цикле. Промежуточная переменная str используется в разных частях этого метода, поток ввода fs читает данные из нашего файла с описанием твиков, а u - это счётчик считанных строк, начиная от строки, которая начинается с символа ".".
Итак, что мы делаем? Считываем сначала строку и смотрим, что за она такая - если это ";", то ничего не делаем, если это "." - создаём новый экземпляр нашего "твикового" класса и записываем в его заголовок то, что следует за точкой. Дальше считываем по одной строке и, инкрементируя счётчик, определяем по нему, что за строку мы считали: то ли это пояснение к "твику", то ли путь в реестре, то ли значение ключа, когда "твик" включен... Здесь всё будет просто и понятно, если внимательно посмотреть на описание формата (вернее, на пример одного из "твиков") выше. "Твики" по мере считывания добавляются в глобальный список этих самых "твиков", который называется lst. Забегая наперёд, хочу сказать, что дальше мы этот список будем использовать, когда потребуется внести изменения в тот или иной "твик", т.е. включить или отключить его. Но это будет уже в следующей части статьи, которая, как я надеюсь, станет заключительной. На сегодня же, я так думаю, уже хватит - слишком много кода тоже не слишком полезно для газетной статьи.
Хочу теперь сказать пару слов в адрес любителей критики, которые найдутся и на нашем форуме, и среди читателей бумажной версии газеты. Код программы неидеален, но он и не создавался для того, чтобы быть эталонным. Он просто иллюстрирует две вещи: работу с языком программирования C# и платформой .NET Framework, на которой он выполняется, и одну идею, которая состоит в том, что написать собственный твикер - легче лёгкого. Для тех, кто только входит в удивительный мир программирования, эта статья должна быть полезной. А если вам она таковой не показалась - что ж, значит, ваш уровень уже выше.
Вадим СТАНКЕВИЧ,
[email protected]






Комментарии