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;
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.