Твикер своими руками

Часть вторая

Мы с вами продолжим писать собственный твикер - утилиту для тонкой настройки системы. В этой части статьи вас ждут дальнейшие разбирательства с кодом твикера на языке 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]

Версия для печатиВерсия для печати

Номер: 

21 за 2008 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя ёклмн
пачынаючыя лісперы спачатку пішуць інтэрптэтатар ліспа, пачынаючыя бадлакодэры - твікеры рэестра