Windows Management Instrumentation - инфраструктура управления операционной системой, страница 13

private void radioCurrent_CheckedChanged (object sender, System.EventArgs e)

{

      // Создайте массив ссылок на 6 элементов управления

  foreach (Для каждого элемента c из массива ссылок)

     c.Visible = логическое выражение, зависящее от состояния переключателя

}

Вы, вероятно, еще помните про вспомогательную функцию UpdateStatusBar, которая была в предыдущем компоненте. Ее цель — генерировать событие типа UpdateStatus для того, чтобы клиентское приложение могло вывести в строку состояния посылаемое нами сообщение. Новый компонент также должен иметь возможность оповещать клиентское приложение о задержках, связанных с поиском информации. Поэтому введите в класс SysInfoControl событие и делегатный тип StatusHandler.

public event StatusHandler UpdateStatus;  // Возбуждаемое нами событие "Изменения состояния",

public delegate void StatusHandler (string msg); // Делегат события "Изменения состояния"

Добавьте также функцию UpdateStatusBar, она должна иметь точно такой же вид, как и в первом компоненте. Для обновления информации о системе предусмотрена кнопка Refresh. Логика обработки ее нажатия достаточно проста. Вот она.

private void bRefresh_Click (object sender, EventArgs e)

{

  Cursor = Cursors.WaitCursor;

  tree.Nodes.Clear();

  GetSysInfo();

  Cursor = Cursors.Default;

}

Конечно, основная логика получения системной информации спрятана в методе GetSysInfo, обсуждением которого мы и займемся. Перед тем, как начать опрос системы, используя язык WQL и возможности класса ManagementObjectSearcher, следует обеспечить доступ к информации конкретного (локального или удаленного) компьютера. Как вы помните, доступ к WMI-классам обеспечивает класс ManagementScope. Конструируя объект этого класса, мы должны знать имя или IP-адрес исследуемого компьютера. К этому имени надо пристыковать пространство имен root\cimv2. Полученная таким образом текстовая строка, используется как адрес пространства имен, где обитает нужный нам класс WMI. Далее алгоритм прозрачен, он повторяется столько раз, сколько классов WMI мы решили задействовать при опросе базы данных.

¨  Создаем объект класса ManagementObjectSearcher, который учитывает адрес пространства имен и строку запроса,

¨  Создаем узел дерева, текст которого отражает суть запроса. Он почти совпадает с именем класса WMI.

¨  Получаем ссылку на коллекцию объектов класса ManagementObject, которую возвращает метод Get класса ManagementObjectSearcher, Эта коллекция — есть ни что иное, как RecordSet, то есть множество строк таблицы базы данных, полученной в результате запроса.

¨  В цикле по всему множеству строк получаем интересующие нас данные, создаем узел дерева с текстом, соответствующим полученной информации,

¨  Вкладываем этот узел внутрь узла, соответствующего запросу.

Учитывая сказанное, внесите изменения в начальную заготовку функции GetSysInfo.

private void GetSysInfo()

{

  string sMachine = // В зависимости от состояния кнопки radioCurrent создаем имя компьютера

  if (sMachine.Trim().Equals (string.Empty))

  {

     MessageBox.Show ("Machine IP address or name is needed");

     return;

  }

  ConnectionOptions co = new ConnectionOptions();

  if (textUserID.Text.Trim().Length > 0)

  {

     co.Username = // IP-адрес или имя машины

     co.Password = // Пароль

  }

//====== Начало блока, который будет повторяться для каждого класса WMI

  ManagementScope ms = new ManagementScope("\\\\" + sMachine+ "\\root\\cimv2", co);

      // Создайте сообщение, которое появится в статус строке. Например: "Getting Computer Information"

  // Создайте сообщение объект класса ManagementObjectSearcher

  // (2-й параметр типа ObjectQuery  должен содержать строку запроса с именем класса (Win32_ComputerSystem)

  TreeNode node = // Создайте узел с именем "Computer System" и индексами иконок 0, 1

  // Вставьте узел в дерево

  TreeNodeCollection nodes = // Получаем ссылку на множество вложенных узлов

  foreach (объект из searcher.Get())

  {

     try

     {

       nodes.Add (Новый узел с текстом "Computer Name: " + mo["Name"], 0, 1));

       string size = string.Format ("{0:f1}  Mb",

         (int.Parse (mo["TotalPhysicalMemory"].ToString())) / (1024.0 * 1024.0));

       nodes.Add (new TreeNode ("Total Physical Memory: " + size, 0, 1));

       // Продолжайте в том же духе

    }

     catch (Exception e) { MessageBox.Show(e.Message); }

}

//====== Конец блока, который должен повторяться для каждого класса WMI

  // Продолжайте в том же духе

}

Повторяйте блок команд, но изменяйте суть запросов (классы WMI). Приведем примерный перечень: Win32_Processor, Win32_LogicalMemoryConfiguration, Win32_LogicalDisk, Win32_VideoController, Win32_OperatingSystem, Win32_TimeZone, Win32_Bios, Win32_NetworkConnection. Не забывайте изменять индексы иконок, которые вы должны вставить в ImageList, соответствующий нашему дереву. В заключение приведу вспомогательную функцию, которая может понадобиться для повышения читабельности.

private string KiloToMegaBytes (object o)

{

return string.Format ("{0:f1}  Mb", Int64.Parse(o.ToString()) / 1024.0);

}

Мне захотелось создать такую функцию, чтобы многократно не повторять одни и те же преобразования. Кроме того, я использовал выражения вида:

string size = string.Format ("{0:f1}  Mb",

  (int.Parse (mo["TotalPhysicalMemory"].ToString())) / (1024.0 * 1024.0));

При решении задачи напрашивается обобщающий прием вида:

foreach (PropertyData data in mo.Properties)

nodes.Add (new TreeNode (data.Name + ": " + mo[data.Name], 2, 3));

и он очень полезен с познавательной точки зрения (обязательно исследуйте его), но с практической точки зрения он создает массу ненужных строк, забивающих эфир (jamming the air).