Классы и события управления в окне Server Explorer в Visual Studio
82Программы --- Visual Studio --- Классы и события управления в окне Server Explorer
Классы управления
На рисунке ниже приведен полный список классов управления, доступных в окне Server Explorer. Каждый узел означает набор функциональных возможностей, присущих данному устройству или приложению. Например, щелкнув правой кнопкой мыши на узле Printers, можно добавить новое соединение с принтером, щелкнув правой кнопкой мыши на узле My Computer, можно добавить компьютер в домен или рабочую группу. Все эти узлы обеспечивают строго типизированную оболочку вокруг инфраструктуры Windows Management Instrumentation (WMI).
В большинстве случаев достаточно перетащить на форму узел, представляющий информацию, которая интересует разработчика. После этого его программа получает доступ к этой информации и возможность ее перерабатывать.
Дли того чтобы получить представление о том, как можно использовать эту оболочку, покажем, как с помощью классов управления получить информации о компьютере. Под узлом My Computer расположен узел с именем локального компьютера. Выбрав этот узел и перетащив его на форму, мы получим компонент ComputerSystem, расположенный в невидимой части формы. Теперь добавим элементы управления Label, TextBox, Button и PropertyGrid на закладки All Windows Forms окна Toolbox и разместим их на форме, как показано на рисунке:
Если посмотреть на окно Solution Explorer, то можно увидеть, что в нем также появился специальный компонент root.CIMV2.Win32_ComputerSystem (или аналогичный, в зависимости от конфигурации компьютера). Он сгенерирован программой Managment Strongly Typed Class Generator и содержит класс ComputerSystem и другие классы, позволяющие получить информацию инфраструктуры WMI.
Если щелкнуть на объекте computerSystem1, расположенном на форме, в окне Properties отобразится информация об этом компьютере. Однако в данном приложении нас не интересует какой-то конкретный компьютер; этот компьютер был выбран как шаблон для создании класса ComputerSystem. Объект computerSystem1 можно удалить, но перед удалением следует обратить внимание на свойство Path этого объекта. Свойство Path в сочетании с именем компьютера внедрено в форму, показанную на рисунке выше, для того чтобы загрузить информацию об этом компьютере. Это легко увидеть в следующем коде, который является частью обработчика щелчка на кнопке Load:
private void button1_Click(object sender, EventArgs e)
{
const string compPath = "\\\\{0}\\root\\CIMV2:Win32_ComputerSystem.Name=\"{0}\"";
if (!string.IsNullOrEmpty(this.textBox1.Text))
{
string computerName = this.textBox1.Text;
string pathString = string.Format(compPath, computerName);
var path = new System.Management.ManagementPath(pathString);
ROOT.CIMV2.ComputerSystem cs = new ROOT.CIMV2.ComputerSystem(path);
this.propertyGrid1.SelectedObject = cs;
}
}
В этом примере свойство Path, полученное из объекта computerSystem1, использовалось в строковой константе вместе с маркером замены {0}, за которым должно следовать имя компьютера. После щелчка на кнопке имя компьютера, вставленное в текстовое поле, объединяется с данным путем с помощью метода String.Format, чтобы сгенерировать полный путь WMI. Затем этот путь используется для того, чтобы создать новый объект класса ComputerSystem, который в свою очередь передается элементу управления PropertyGrid. Результат этих действий, проявляющийся на этапе выполнения программы, показан на рисунке ниже:
Несмотря на то что большинство свойств являются "только для чтения", для полей, допускающих редактирование, изменения, внесенные в данном элементе PropertyGrid, немедленно передаются компьютеру. Этот сценарий можно изменить, заменив свойство AutoCommit в классе ComputerSystem.
События управления
В предыдущем разделе мы видели, как перетащить класс управления из окна Server Explorer на форму и затем работать со сгенерированными классами. Другой способ работы с интерфейсом WMI основывается на использовании узла Management Events. Событие управления позволяет отслеживать любой тип данных интерфейса WMI и генерировать событие при создании, модификации и удалении объектов такого типа. По умолчанию этот узел пуст, но разработчик может создать свой собственный, щелкнув на узле Management Events и выбрав команду Add Event Query, которая открывает окно, показанное на рисунке ниже:
С помощью этого окна можно найти тип данных WMI, интересующий разработчика. Поскольку этих типов буквально тысячи, полезно воспользоваться полем Find. На рисунке показано, что в поле поиска введен термин "process" и в результате был найден класс CIM Processes в узле root\CIMV2. Каждый экземпляр этого класса представляет отдельный процесс, выполняемый системой. Разработчик обычно хочет получать информацию, только когда создается новый процесс, поэтому следует выбрать команду Object Creation в выпадающем меню. После щелчка на кнопке ОК к узлу Management Events добавляется узел CIM Processes Event Query. Если разработчик откроет новый экземпляр приложения в своей системе, например Notepad или калькулятор, то увидит события, которые будут последовательно добавляться в этот узел. В диалоговом окне Build Management Event Query, показанном на рисунке выше, интервал опроса по умолчанию задан равным 60 секундам, поэтому, для того чтобы увидеть изменения, придется подождать минуту.
Как только событие в конце концов произойдет, оно появится вместе с данными и временем в окне Server Explorer и в окне Output, как показано на рисунке ниже снизу. Если выбрать это событие, то в окне Properties будет содержаться много свойств, не имеющих реального смысла. Однако если разработчик знает, какое свойство искать, то легко найдет его, отфильтрует и сгенерирует в ответ на события системы.
Чтобы продолжить пример, перетащим элементы управления CheckBox и ListBox с панели Toolbox на новую форму типа Windows Form. Затем перетащим узел CIM Processes Event Query из окна Server Explorer на новую форму. В результате будет сгенерирован экземпляр класса System.Management.ManagementEventWatcher, свойства которого настроены так, чтобы отслеживать создание нового процесса. Доступ к реальному запросу можно получить с помощью свойства QueryString вложенного объекта ManagementQuery. Как и большинство классов-наблюдателей, класс ManagementEventWatcher генерирует событие, когда выполняются конкретные условия, - в данном случае событие EventArrived. Для обработки этого события в программу добавляется следующий код:
private void managementEventWatcher1_EventArrived(object sender,
System.Management.EventArrivedEventArgs e)
{
foreach (System.Management.PropertyData p in e.NewEvent.Properties)
{
if (p.Name == "TargetInstance")
{
var mbo = (System.Management.ManagementBaseObject)p.Value;
string[] sCreatedProcess = {(string)mbo.Properties["Name"].Value,
(string)mbo.Properties["ExecutablePath"].Value };
this.BeginInvoke(new LogNewProcessDelegate(LogNewProcess),
sCreatedProcess);
}
}
}
delegate void LogNewProcessDelegate(string ProcessName, string ExePath);
private void LogNewProcess(string ProcessName, string ExePath)
{
this.listBox1.Items.Add(string.Format("{0}—{1}", ProcessName, ExePath));
}
private void checkBox1_CheckedChanged(System.Object sender, System.EventArgs e)
{
if (this.checkBox1.Checked)
{
this.managementEventWatcher1.Start();
}
else
{
this.managementEventWatcher1.Stop();
}
}
Обработчик события должен просмотреть коллекцию Properties, связанную с объектом NewEvent. Если объект был изменен, то возвращаются два экземпляра: PreviousInstance, в котором хранится состояние объекта в начале интервала опроса, и экземпляр TargetInstance, в котором хранится состояние в конце этого интервала. В течение интервала опроса состояние объекта может изменяться несколько раз. В этом случае событие может произойти, только если в конце периода оно отличается от состояния в начале периода. Например, если процесс начался и закончился в течение одного и того же интервала опроса, то событие не произойдет.
Обработчик событий создает новый объект ManagementBaseObject по значению, которое передается в качестве аргумента события, чтобы получить отображаемое имя и путь к исполняемому файл, запустившему процесс. Поскольку элементы управления пользовательского интерфейса можно обновить только с помощью потока пользовательского интерфейса, разработчик не может непосредственно обновить объект List Box. Вместо этого он должен вызвать метод BeginInvoke, чтобы применить функцию LogNewProcess к потоку пользовательского интерфейса. Состояние формы во время этого действия показано на рисунке ниже: