Windows Management Instrumentation. Опрос свойств, методов и описателей. Разработка компонента WMIControl, страница 35

watchUSB.EventArrived += new EventArrivedEventHandler(watchUSB_EventArrived);

watchUSB.Start();

watchCD = new ManagementEventWatcher(new WqlEventQuery(

"__InstanceModificationEvent", TimeSpan.FromSeconds(1),

"TargetInstance isa 'Win32_LogicalDisk'"));

watchCD.EventArrived += new EventArrivedEventHandler(watchCD_EventArrived);

watchCD.Start();

}

catch (ManagementException ex)

{

new FormMsg(null, "Win32_VolumeChangeEvent: " + ex.Message, 3000);

}

}

¨  Добавьте обработчик события Disposed, в котором надо остановить наблюдатели.

void FileSystemControl_Disposed(object sender, EventArgs e)

{

if (watchUSB != null)

{

watchUSB.Stop();

watchUSB.Dispose();

}

if (watchUSB != null)

{

watchCD.Stop();

watchCD.Dispose();

}

foreach (var w in watchers)

w.Dispose();

watchers.Clear();

}

¨  Добавьте обработку события EventArrived для наблюдателя за USB-устройствами.

void watchUSB_EventArrived(object sender, EventArrivedEventArgs e)

{

try

{

ManagementBaseObject mo = e.NewEvent as ManagementBaseObject;

ushort type = (ushort)mo["EventType"];

string name = mo["DriveName"].ToString(), msg = "";

switch (type)

{

case 1: msg = " Changed Configuration"; break;

case 2: msg = " added";

Invoke(new Action<string, string>(OnAddDisk), new object[] { "6", name });

break;

case 3: msg = " removed";

Invoke(new Action<string, string>(OnRemoveDisk), new object[] { "6", name });

break;

case 4: msg = " docking"; break;

}

msg = name + msg;

Invoke(new Action<string>(SetMessage), new object[] { msg });

}

catch (Exception ex) { new FormMsg(null, ex.Message, 4000); }

}

Спектр возможных значений для типа события (EventType) WMI-класса Win32_VolumeChangeEvent и смысл констант типа ushort вы можете увидеть в справке MSDN или правильно распорядиться возможностями уже разработанного нами WMIControl. Необходимость отложенной корректировки дерева объектов файловой системы (см. вызов Invoke) мы обсудили ранее. Задания делегатов типа Action<string>: методы OnAddDisk и OnRemoveDisk приведены ниже.

void OnAddDisk(string type, string name)

{

SetMessage("New drive " + name + " was attached.");

TreeNode node = null;

if (name.StartsWith("A:") || type == "5")

node = FindNode(name);

else

{

int id = GetImageID(type, name);

node = new TreeNode(name, id, id + 1);

int pos = FindNodeIndex(node);

root.Nodes.Insert(pos, node);

AddWatcher(type, name);

}

FillFolder(node, 2);

}

void OnRemoveDisk(string type, string name)

{

SetMessage("Disk " + name + " was removed.");

if (name.StartsWith("A:") || type == "5")

{

TreeNode node = FindNode(name);

node.Nodes.Clear();

node.Tag = null;

}

else

{

int pos = FindNodeIndex(name);

if (pos != -1)

{

FileSystemWatcher w = watchers.Find(c => c.Path.StartsWith(name));

if (w != null)

{

watchers.Remove(w);

w.Dispose();

}

root.Nodes.RemoveAt(pos);

}

}

}

Поиск удаляемого наблюдателя в generic-списке List<T> осуществляется с помощью Extension-метода Find и лямбда-выражения (λ-expression).

FileSystemWatcher w = watchers.Find(c => c.Path.StartsWith(name));

Эти новые реалии C# стали доступны в .NET Framework 3.5, они относятся к технологии LINQ (Language Integrated Query) и заслуживают отдельного рассмотрения, например, см. Секреты LINQ в папке с документами курса.

Две перегруженные версии вспомогательного метода FindNodeIndex понадобились для поиска удаляемого узла в дереве tree. Первая из них в данный момент не используется, но я оставил ее в учебных целях. Вторая — вызывается в методе OnAddDisk.

int FindNodeIndex(string name) // Not used now (maybe later...)

{

int pos = 0;

foreach (TreeNode n in root.Nodes)

{

if (name.CompareTo(n.Text) == 0)

break;

pos++;

}

return pos;

}

int FindNodeIndex(TreeNode node)

{

int pos = 0;

foreach (TreeNode n in root.Nodes)

{

if (node.Text.CompareTo(n.Text) < 0)

break;

pos++;

}

return pos;

}