WMI-обозреватель
Что такое WMI?
Windows Management Instrumentation (WMI) в дословном переводе — это инструментарий управления Windows. Если говорить более развернуто, то WMI — это одна из базовых технологий для централизованного управления и слежения за работой различных частей компьютерной инфраструктуры под управлением платформы Windows. Звучит страшно, а на самом деле это достаточно богатый набор инструментов, основные функции которого:
- Получать данные о системах (диски, процессоры, процессы, журналы событий и многое-другое)
 - Выполнять широкий спектр административные задачи: от завершения процесса, до управления DHCP и DNS
 - Создавать скрипты, срабатывающие при наступлении каких-либо событий в системе
 - Получать данные счетчиков производительности
 
В WMI есть иерархическая адресация всех ресурсов - что-нибудь типа WinMgmts:{impersonationLevel=impersonate}!//myServer/root/cimv2:Win32_LogicalDisk), но вместе с иерархическим доступом к ресурсам есть и SQL-подобный язык получения данных. Этот язык обычно называется WQL и в сети есть множество примеров его использования. На инфостарте можно обратить внимание на следующие статьи:
- 1С:Системный Администратор 2.6 (WSH&WMI)
 - 1С и Windows Script Host (WSH) и Windows Management Instrumentation (WMI). ОТ ТЕОРИИ К ПРАКТИКЕ. Часть I
 - 1С и Windows Script Host (WSH) и Windows Management Instrumentation (WMI). ОТ ТЕОРИИ К ПРАКТИКЕ. Часть II
 - 1С и Windows Script Host (WSH) и Windows Management Instrumentation (WMI). ОТ ТЕОРИИ К ПРАКТИКЕ. Часть III
 
В MSDN можно ознакомиться начиная со следующих статей:
- Windows Management Instrumentation, корневая страница справки
 - WQL (SQL for WMI), страница описания языка запросов, он немного отличается от SQL
 - Creating WMI Clients, документация по созданию приложений, использующих WMI
 - Management Infrastructure Classes, важная часть справки, описание классов WMI, особенно Win32 Classes
 
Типичный запрос WQL выглядит так:
SELECT CommandLine, Handle, Name FROM Win32_Process
Результатом этого запроса будет табличка, начинающаяся примерно так:
| CommandLine | Handle | Name | 
| 0 | System Idle Process | |
| 4 | System | |
| 224 | smss.exe | |
| 320 | csrss.exe | |
| 372 | csrss.exe | |
| 380 | wininit.exe | |
| 412 | winlogon.exe | |
| 476 | services.exe | |
| 484 | lsass.exe | |
| 492 | lsm.exe | |
| 588 | svchost.exe | |
| 656 | svchost.exe | |
| 744 | svchost.exe | |
| 792 | svchost.exe | |
| 840 | svchost.exe | |
| 880 | svchost.exe | |
| 920 | svchost.exe | |
| 508 | svchost.exe | |
| 1096 | spoolsv.exe | |
| 1156 | hasplms.exe | |
| 1236 | svchost.exe | |
| 1316 | vmtoolsd.exe | |
| 1680 | TPAutoConnSvc.exe | |
| 1900 | dllhost.exe | |
| 1980 | msdtc.exe | |
| taskhost.exe | 1724 | taskhost.exe | 
| TPAutoConnect.exe -q -i vmware -a COM1 -F 30 | 616 | TPAutoConnect.exe | 
Зачем нужен WMI-обозреватель?
WMI документирована хорошо, но отлаживать WQL запросы непосредственно в 1С не было возможности, а пользоваться внешними утилитами ради пары строк запроса вовсе не хочется. Для этой цели я сделал простенький WMI-обозреватель.
Пользовательский интерфейс WMI-обозревателя
Интерфейс состоит из 2 закладок: Запрос и Настройки. На закладке Запрос есть только поле для ввода запроса. По умолчанию запрос выполняется на текущем ПК в файловой версии и на сервере предприятия (от имени rphost) в клиент-серверной версии. По кнопке "Выполнить запрос" появляется таблица с результатами.
Если настройки по умолчанию не устраивают, переходим на вторую закладку. Там можно настроить:
- Имя сервера с которого снимаются данные
 - Если установлен флажок "Собирать системные свойства", то в таблице будут выданы внутренние свойства каждой записи. Обычно это не требуется.
 - Если установлен флажок "Получать путь", то в таблице будут выдана колонка с иерархическим путём записи. Имеет смысл, если этот путь нужен для отладки запроса.
 - Если установлен флажок "Собирать методы", то в таблице первой колонкой будет поле "Methods". Если два раза кликнуть мышкой или нажать Enter на этой колонке, то будет выдан табличный документ с методами, которые можно применять в программном коде к значению WMI данной строки
 
Картинки:


Как можно использовать WMI-обозреватель?
Здесь я приведу просто набор запросов и пояснение, что можно получить этим запросом. Проверяйте, экспериментируйте.
| Запрос | Пояснение | 
| SELECT Handle, Name, VirtualSize FROM Win32_Process WHERE VirtualSize>100000000 AND CreationDate > "20130604000000.000000+420" | Выводится ID процесса, название процесса, размер адресуемого пространства для процессов, созданных позднее 4 июня 2013 года (в моём часовом поясе) | 
| SELECT * FROM Win32_Service WHERE PathName LIKE "%ragent%" | Все службы 1С со всеми данными по ним | 
| SELECT Name, Capacity, FreeSpace FROM Win32_Volume | Диски, их размер и свободное место | 
| SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfOS_Processor | Текущая загрузка процессора | 
| SELECT PercentDiskTime, AvgDiskQueueLength, DiskReadBytesPerSec, DiskWriteBytesPerSec FROM Win32_PerfFormattedData_PerfDisk_PhysicalDisk | Текущая загрузка диска | 
| Select * From meta_class | Выполняется долго, содержит очень много колонок! Выводит все классы WMI | 
Как устроен WMI-обозреватель?
Весь WMI обозреватель благополучно поместился в одну управляемую форму (прямо скажу - не сильно сложную). Если по каким-то причинам Вы не можете скачать решение, то программный код этой формы приведен ниже.
&НаКлиенте
 Процедура РезультатЗапросаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
     // При двойном клике на медоды, выводим их в табличный документ
     Если Поле.Имя = "РезультатЗапросаMethods" Тогда
         Методы = Элемент.ТекущиеДанные.Methods;
         Если Методы.Количество()>0 Тогда
             ТабличныйДокумент = Новый ТабличныйДокумент;
             СчСтрок = 1;
             Для каждого Метод Из Методы Цикл
                 ТабличныйДокумент.Область(СчСтрок, 1, СчСтрок, 1).Текст = Метод;
                 СчСтрок = СчСтрок + 1;
             КонецЦикла;
             ТабличныйДокумент.Показать();
         КонецЕсли;
     КонецЕсли;
 КонецПроцедуры
 
 &НаКлиенте
 Процедура ВыполнитьЗапрос(Команда)
     ВыполнитьЗапросНаСервере();
 КонецПроцедуры
 
 ////////////////////////////////////////////////////////////////////////////////
 // Серверные методы формы
 
 &НаСервере
 Процедура ВыполнитьЗапросНаСервере()
 
     WMIЗапрос = ПолучитьCOMОбъектWMI(Объект.ИмяСервера);
 
     // "*" желательно заменить для ускорения на конкретный список полей
     WMIРезультаты = WMIЗапрос.ExecQuery(Объект.ТекстЗапроса);
 
     РезультатЗапроса = ПреобразоватьРезультатыWMIвТаблицуЗначений(WMIРезультаты,
         Объект.СобиратьСистемныеСвойства,
         Объект.СобиратьМетоды,
         Объект.ПолучатьПуть,
         Ложь);
     //РезультатЗапроса.Колонки.Удалить("Значение"); // В ней содержатся "COMОбъект", которые не выводятся
 
     ВывестиТаблицуЗначений("РезультатЗапроса", РезультатЗапроса);
 
 КонецПроцедуры
 
 // Перезаполняет реквизит формы из таблицы значений.
 // Предполагается, что реквизит уже есть на форме. Перезаполнение происходит
 // полностью вместе с пересозданием колонок. Так медленнее, зато проще.
 //
 // Параметры:
 //  ИмяРеквизита - Строка - Имя заполняемого реквизита формы
 //  ЗначениеРеквизита -  ТаблицаЗначений - чем заполнять реквизит
 //
 &НаСервере
 Процедура ВывестиТаблицуЗначений(ИмяРеквизита, ЗначениеРеквизита)
 
     ЭлементФормы = Элементы[ИмяРеквизита];
     ПутьКДанным = ЭлементФормы.ПутьКДанным;
 
     МассивДобавляемыхРеквизитов = Новый Массив;
     МассивУдаляемыхРеквизитов = Новый Массив;
 
     Для каждого ТекРеквизит из ПолучитьРеквизиты(ПутьКДанным) Цикл
         МассивУдаляемыхРеквизитов.Добавить(ТекРеквизит.Путь + "." + ТекРеквизит.Имя);
         ИмяЭлементаВТаблице = ИмяРеквизита + ТекРеквизит.Имя;
         Элемент = Элементы.Найти(ИмяЭлементаВТаблице);
         Если не Элемент = Неопределено Тогда
             Элементы.Удалить(Элемент);
         КонецЕсли;
     КонецЦикла;
 
     Для Каждого Колонка Из ЗначениеРеквизита.Колонки Цикл
         ДобавляемыйРеквизит = Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, ПутьКДанным, Колонка.Имя);
         МассивДобавляемыхРеквизитов.Добавить(ДобавляемыйРеквизит);
     КонецЦикла;
 
     ИзменитьРеквизиты(МассивДобавляемыхРеквизитов,МассивУдаляемыхРеквизитов);
     ЗначениеВРеквизитФормы(ЗначениеРеквизита, ПутьКДанным);
 
     Для Каждого ТекРеквизит Из МассивДобавляемыхРеквизитов Цикл
 
         ИмяЭлементаВТаблице = ИмяРеквизита + ТекРеквизит.Имя;
         Элемент = Элементы.Добавить(ИмяЭлементаВТаблице, Тип("ПолеФормы"), ЭлементФормы);
         Элемент.Вид = ВидПоляФормы.ПолеВвода;
         Элемент.ПутьКДанным = ПутьКДанным + "." + ТекРеквизит.Имя;
         Элемент.ТолькоПросмотр = Истина;
 
     КонецЦикла;
 
 КонецПроцедуры
 
 ////////////////////////////////////////////////////////////////////////////////
 // Блок функций WMI, если хотите использовать их в своих программах, то лучше
 // вынести в отдельный модуль. Модуль лучше сделать серверным, потому что
 // используются таблицы значений. Не забудьте удалить директивы компиляции.
 
 // Возвращает настроенный COM-объект WMI
 //
 // Параметры:
 //  ИмяСервера - Строка, имя или IP-адрес компьютера с которого будут получаться
 //              значения счетчиков производительности. Можно не указывать, если
 //              значения получаются со своего компьютера
 //  ИмяСервераИсполнителя -  Строка, имя или IP-адрес компьютера на котором создаётся
 //              COM объект. Обычно можно не указывать
 //  ТочкаПодключения - Строка - по умолчанию "root\cimv2", но можно указать и своё
 //
 // Возвращаемое значение:
 //  COMОбъект - objWMIService
 //
 &НаСервереБезКонтекста
 Функция ПолучитьCOMОбъектWMI(Знач ИмяСервера = Неопределено, Знач ИмяСервераИсполнителя = Неопределено, Знач ТочкаПодключения = Неопределено) Экспорт
 
     //http://msdn.microsoft.com/en-us/library/windows/desktop/aa389763(v=vs.85).aspx
     Если Не ЗначениеЗаполнено(ИмяСервераИсполнителя) Тогда
         Locator = Новый COMОбъект("WbemScripting.SWbemLocator");
     Иначе
         Locator = Новый COMОбъект("WbemScripting.SWbemLocator", ИмяСервераИсполнителя);
     КонецЕсли;
 
     Если Не ЗначениеЗаполнено(ИмяСервера) Тогда
         ИмяСервера = ".";
     КонецЕсли;
 
     Если Не ЗначениеЗаполнено(ТочкаПодключения) Тогда
         ТочкаПодключения = "root\cimv2";
     КонецЕсли;
 
     objWMIService = Locator.ConnectServer(ИмяСервера, ТочкаПодключения);
     Возврат objWMIService;
 
 КонецФункции
 
 // Преобразует результаты WMI-запроса в таблицу значений
 //
 // Параметры:
 //  РезультатыWMI - COMОбъект - "сырые" результаты WMI-запроса
 //  СобиратьСистемныеСвойства - Булево - признак необходимости сбора системных свойств, необязательный, по умолчанию Ложь
 //  СобиратьМетоды - Булево - признак необходимости доступных методов, необязательный, по умолчанию Ложь
 //  ПолучатьПуть - Булево - получать или не получать колонку с полным путем к значению в терминах WMI, по умолчанию Истина.
 //  ПолучатьЗначениеWMI - Булево - получать или не получать колонку с самим значением WMI строки, по умолчанию Истина
 //
 // Возвращаемое значение:
 //  ТаблицаЗначений - Преобразованная таблица значений (нетипизированная, потому что добывать типы сложно)
 //
 // Примечание:
 // 1. ПолучатьЗначение следует устанавливать в Ложь, если планируется вывод на форму (COM-объект,
 // содержащийся в колонке нормально не выводится), в Истина, если планируется вызов методов или другая доп. логика
 // 2. ПолучатьПуть можно установить в Ложь, если нужно минимизировать передачу данных
 &НаСервереБезКонтекста
 Функция ПреобразоватьРезультатыWMIвТаблицуЗначений(РезультатыWMI,
         Знач СобиратьСистемныеСвойства = Ложь,
         Знач СобиратьМетоды = Ложь,
         Знач ПолучатьПуть = Истина,
         Знач ПолучатьЗначениеWMI = Истина) Экспорт
 
     ТаблицаWMI = Новый ТаблицаЗначений;
     Если ПолучатьЗначениеWMI Тогда
         ТаблицаWMI.Колонки.Добавить("Значение");
     КонецЕсли;
     Если ПолучатьПуть Тогда
         ТаблицаWMI.Колонки.Добавить("Path");
     КонецЕсли;
     Если СобиратьМетоды Тогда
         ТаблицаWMI.Колонки.Добавить("Methods");
     КонецЕсли;
 
     Для Каждого ЗначениеWMI Из РезультатыWMI Цикл
         СтрокаТаблицыWMI = ТаблицаWMI.Добавить();
         Если ПолучатьЗначениеWMI Тогда
             СтрокаТаблицыWMI.Значение = ЗначениеWMI;
         КонецЕсли;
         Свойства = ПолучитьСтруктуруИзЗначенияWMI(ЗначениеWMI.Properties_);
 
         ДобавитьСтруктуруВСтрокуТаблицаЗначений(СтрокаТаблицыWMI, Свойства);
         Если СобиратьСистемныеСвойства Тогда
             СистемныеСвойства = ПолучитьСтруктуруИзЗначенияWMI(ЗначениеWMI.SystemProperties_);
             ДобавитьСтруктуруВСтрокуТаблицаЗначений(СтрокаТаблицыWMI, СистемныеСвойства);
         КонецЕсли;
         Если ПолучатьПуть Тогда
             СтрокаТаблицыWMI.Path = ЗначениеWMI.Path_.Path;
         КонецЕсли;
 
         Если СобиратьМетоды Тогда
 
             СтрокаТаблицыWMI.Methods = Новый Массив;
 
             // Описания методов возвращаем для людей, поэтому описание "человеколюбивое"
             Для Каждого МетодWMI из ЗначениеWMI.Methods_ Цикл
 
                 ОписаниеМетода = "Метод: " + МетодWMI.Name;
                 Если МетодWMI.InParameters <> Неопределено Тогда
                     Для Каждого ПараметрWMI из МетодWMI.InParameters.Properties_ Цикл
                         КвалификаторыПраметра = ПолучитьСтруктуруИзЗначенияWMI(ПараметрWMI.Qualifiers_);
                         ОписаниеМетода = ОписаниеМетода + Символы.ПС + "Входной параметр: " + ПараметрWMI.Name;
                     КонецЦикла;
                 КонецЕсли;
 
                 Если МетодWMI.OutParameters <> Неопределено Тогда
                     Для Каждого ПараметрWMI из МетодWMI.OutParameters.Properties_ Цикл
                         КвалификаторыПраметра = ПолучитьСтруктуруИзЗначенияWMI(ПараметрWMI.Qualifiers_);
                         ОписаниеМетода = ОписаниеМетода + Символы.ПС + "Выходной параметр: " + ПараметрWMI.Name;
                     КонецЦикла;
                 КонецЕсли;
 
                 СтрокаТаблицыWMI.Methods.Добавить(ОписаниеМетода);
 
             КонецЦикла;
 
         КонецЕсли;
 
     КонецЦикла;
 
     Возврат ТаблицаWMI;
 
 КонецФункции
 
 // Преобразует строку результатов WMI в структуру
 //
 // Параметры:
 //  ЗначениеWMI - COMОбъект - строка результатов WMI-запроса
 //
 // Возвращаемое значение:
 //  Структура - Коллекция значнний строки результатов WMI-запроса
 //
 &НаСервереБезКонтекста
 Функция ПолучитьСтруктуруИзЗначенияWMI(ЗначениеWMI)
 
     Рез = Новый Структура;
     Для каждого СвойствоWMI из ЗначениеWMI Цикл
         Если ТипЗнч(СвойствоWMI.Value) = Тип("COMSafeArray") Тогда
             Рез.Вставить(СвойствоWMI.Name, СвойствоWMI.Value.Выгрузить());// возможно массив надо будет переделать
         Иначе
             Рез.Вставить(СвойствоWMI.Name, СвойствоWMI.Value);
         КонецЕсли
     КонецЦикла;
 
     Возврат Рез;
 
 КонецФункции
 
 // Добавляет все значения структуры в строку ТЗ. Если не хватает колонок - добавляет нетипизированную
 //
 // Параметры:
 //  ТекущаяСтрокаТаблицы - СтрокаТаблицыЗначений - Строка в которую записываются данные
 //  ДобавляемаяСтруктура - Структура - структура с значениями
 //
 // Возвращаемое значение:
 //  Структура - Коллекция значнний строки результатов WMI-запроса
 //
 &НаСервереБезКонтекста
 Процедура ДобавитьСтруктуруВСтрокуТаблицаЗначений(ТекущаяСтрокаТаблицы, ДобавляемаяСтруктура)
 
     ТаблицаЗначений = ТекущаяСтрокаТаблицы.Владелец();
     Колонки = ТаблицаЗначений.Колонки;
     Для Каждого ЭлементСтруктуры Из ДобавляемаяСтруктура Цикл
         Если Неопределено = Колонки.Найти(ЭлементСтруктуры.Ключ) Тогда
             Колонки.Добавить(ЭлементСтруктуры.Ключ);
         КонецЕсли;
         ТекущаяСтрокаТаблицы[ЭлементСтруктуры.Ключ] = ЭлементСтруктуры.Значение;
     КонецЦикла
 
 КонецПроцедуры
 
Напоследок
- Это не супер-пупер инструмент, а скорее наколеночная демонстрация работы с WMI, просто, к сожалению, я не нашёл аналога в существующих разработках.
 - Проверено в 1С 8.2 и 1С 8.3 в управляемых формах.
 - Очевидно, что при правильно настроенном rphost могут возникнуть проблемы с правами (rphost должен быть почти бесправен).
 - Код этой обработки можете свободно использовать в своих разработках.
 - Замечания и предложения принимаются :)
 
Вступайте в нашу телеграмм-группу Инфостарт