Удивительно то, что по умолчанию разработчики в компонентах не дополняют свойство номера используемого процесса, хотя это было-бы полезно. Поэтому как видим на рисунке вопрос о номере двусторонний. Ни одно из приложений не знает под каким ИД оно находится, приходится изощряться применяя сторонние языки программирования.
Итак, приступим. Пример использования.
Если указать команду:
Excel=Новый COMОбъект("Excel.Application");
То сможем узнать его номер процесса. По этому номеру, например, можно процесс выгрузить, если он по какой-то причине остался.
Подготовим инструменты функций для поставленной задачи (3 функции)
Функция №1 получения таблицы значений всех запущенных процессов, чтобы отслеживать указанный процесс в параметре можно указать любой из них, например приложение Excel
//Функция получения таблицы значений всех запущенных процессов
//Параметры
//ПоФильтруПриложения - Строка -Указать имя приложения. Например "EXCEL.EXE"
//-Если не указано тогда по всем процессам
//Возвращаемое значение
//ТаблицаЗначений с именами колонок
// -Приложение - Строка
// -ИД - Число
// -РодительскийИД - Число
Функция ТабЗнач_ПолучитьВсеПроцессы(Знач ПоФильтруПриложения="") Экспорт
ПоФильтруПриложения=НРег(ПоФильтруПриложения);
ТабЗн=Новый ТаблицаЗначений;
ТабЗн.Колонки.Добавить("Приложение");
ТабЗн.Колонки.Добавить("ИД");
ТабЗн.Колонки.Добавить("РодительскийИД");
Локатор=Новый COMОбъект("wbemscripting.swbemlocator");
Сервис=Локатор.ConnectServer(".", "\root\cimv2");
ComputerSystems = Сервис.ExecQuery("Select * from Win32_Process");
Для Каждого ComputerSystem Из ComputerSystems Цикл
ИмяПриложения=ComputerSystem.Name;
Если ПоФильтруПриложения="" ИЛИ НРег(ИмяПриложения)=ПоФильтруПриложения Тогда
СтрТаб=ТабЗн.Добавить();
СтрТаб.Приложение=ИмяПриложения;
СтрТаб.ИД=ComputerSystem.ProcessID;
СтрТаб.РодительскийИД=ComputerSystem.ParentProcessID;
КонецЕсли;
КонецЦикла;
Возврат ТабЗн
КонецФункции
Функция №2 по объединению таблиц
//Объединяет две таблицы в одну (Необходимо чтобы имена колонок обеих таблиц были идентичными)
//Параметры
//Таблица1 - ТаблицаЗначений - Таблица значения (Будет скопирована для пополнения)
//Таблица2 - ТаблицаЗначений - Таблица значений как добавляемая
//Возвращаемое значение
//Таблица значений - Новая (Объединённая)
Функция ТабЗнач_ОбъединитьТаблицы(Таблица1, Таблица2) Экспорт
Таблица=Таблица1.Скопировать();
Для Каждого СтрТаб Из Таблица2 Цикл
ЗаполнитьЗначенияСвойств(Таблица.Добавить(), СтрТаб);
КонецЦикла;
Возврат Таблица
КонецФункции
Функция №3 для работы с таблицами значений. Необходима для отслеживания изменений до и после загрузки стороннего приложения
//Вывести массив строк из обеих таблиц непохожие друг-на-друга. Таблицы должны быть идентичные по итменам колонок
//Параметры
//Таблица1 - ТаблицаЗначений - Таблица значений в произвольном порядке, но с идентичными именами колонок
//Таблица2 - ТаблицаЗначений - Таблица значений в произвольном порядке, но с идентичными именами колонок
//Возвращаемое значение
//МассивСтрок - массив строк объединённой таблицы, имеющие различия
Функция МассивСтрок_ПолучитьМассивОтличающихсяСтрок(Таблица1, Таблица2) Экспорт
СистемнаяКолонка="_ГруппаКолонка";
мКолонки=Таблица1.Колонки; //Получить массив имён колонок
СтрКолонки="";
Для Каждого ИмяК Из мКолонки Цикл
СтрКолонки=СтрКолонки+ИмяК.Имя+",";
КонецЦикла;
СтрКолонки=Лев(СтрКолонки, СтрДлина(СтрКолонки)-1);
Таблица3=ТабЗнач_ОбъединитьТаблицы(Таблица1, Таблица2);
Таблица3.Колонки.Добавить(СистемнаяКолонка);
Таблица3.ЗаполнитьЗначения(1,СистемнаяКолонка);
Таблица3.Свернуть(СтрКолонки,СистемнаяКолонка);
мСтр=Таблица3.НайтиСтроки(Новый Структура(СистемнаяКолонка, 1));
Возврат мСтр
КонецФункции
Результирующая функция. Теперь как это совместить для определения ИД процесса
//Подключает компоненту методом - Новый COMОбъект(ИмяКомпоненты)
//Параметры
//ИмяКомпоненты - Строка - Имя компоненты. Например: "Excel.Application"
//ИмяПроцесса - Строка - Имя, например: "EXCEL.EXE", так как оно называется в окне Диспетчера задач, по колонке [Имя образа]
//Возвращаемое значение
//Структура - с именами ключей:
// -Приложение - COM-Объект
// -ИД- Число/Неопределено
// -РодительскийИД- Число/Неопределено
Функция ПодключитьКомпоненту(ИмяКомпоненты, ИмяПроцесса) Экспорт
Стрк=Новый Структура;
Стрк.Вставить("Приложение", Неопределено);
Стрк.Вставить("ИД", Неопределено);
Стрк.Вставить("РодительскийИД", Неопределено);
ТЗ1=ТабЗнач_ПолучитьВсеПроцессы(ИмяПроцесса);
Попытка
COM=Новый COMОбъект(ИмяКомпоненты);
Стрк.Приложение=COM;
ТЗ2=ТабЗнач_ПолучитьВсеПроцессы(ИмяПроцесса);
мСтр=МассивСтрок_ПолучитьМассивОтличающихсяСтрок(ТЗ1, ТЗ2);
Если мСтр.Количество()=1 Тогда
Стрк.ИД=мСтр[0].ИД;
Стрк.РодительскийИД=мСтр[0].РодительскийИД;
КонецЕсли
Исключение
Сообщить("Не удалось загрузить компоненту: "+ИмяКомпоненты);
Сообщить(ОписаниеОшибки());
КонецПопытки;
Возврат Стрк
КонецФункции
Теперь у нас есть всё необходимое. Для получения приложения с его ИД, пишем команду:
Стрк=ПодключитьКомпоненту("Excel.Application", "EXCEL.EXE");
Excel=Стрк.Приложение;
НомерПроцесса=Стрк.ИД;
Послесловие
ДЛЯ ЛЕНИВЫХ
Эта функция "ВСЁ В ОДНОМ" без прочих подготовок.
//Подключает компоненту методом - Новый COMОбъект(ИмяКомпоненты)
//Параметры
//ИмяКомпоненты - Строка - Имя компоненты. Например: "Excel.Application"
//ИмяПроцесса - Строка - Имя, например: "EXCEL.EXE", так как оно называется в окне Диспетчера задач, по колонке [Имя образа]
//_ПолучитьТаблицуПроцессов - Булево - Не использовать. Это для внутреннего использования
//Возвращаемое значение
//Структура - с именами ключей:
// -Приложение - COM-Объект/Неопределено
// -ИД - Число/Неопределено
// -РодительскийИД - Число/Неопределено
Функция ПодключитьКомпоненту(ИмяКомпоненты, ИмяПроцесса, _ПолучитьТаблицуПроцессов=Ложь) Экспорт
Если _ПолучитьТаблицуПроцессов Тогда
ПоФильтруПриложения2=НРег(ИмяПроцесса);
ТабЗн=Новый ТаблицаЗначений;
ТабЗн.Колонки.Добавить("Приложение");
ТабЗн.Колонки.Добавить("ИД");
ТабЗн.Колонки.Добавить("РодительскийИД");
Локатор=Новый COMОбъект("wbemscripting.swbemlocator");
Сервис=Локатор.ConnectServer(".", "\root\cimv2");
ComputerSystems = Сервис.ExecQuery("Select * from Win32_Process");
Для Каждого ComputerSystem Из ComputerSystems Цикл
ИмяПриложения=ComputerSystem.Name;
Если ИмяПроцесса="" ИЛИ НРег(ИмяПриложения)=ПоФильтруПриложения2 Тогда
СтрТаб=ТабЗн.Добавить();
СтрТаб.Приложение=ИмяПриложения;
СтрТаб.ИД=ComputerSystem.ProcessID;
СтрТаб.РодительскийИД=ComputerSystem.ParentProcessID;
КонецЕсли;
КонецЦикла;
Возврат ТабЗн
КонецЕсли;
Стрк=Новый Структура;
Стрк.Вставить("Приложение", Неопределено);
Стрк.Вставить("ИД", Неопределено);
Стрк.Вставить("РодительскийИД", Неопределено);
ТЗ1=ПодключитьКомпоненту(ИмяКомпоненты, ИмяПроцесса, Истина);
Попытка
COM=Новый COMОбъект(ИмяКомпоненты);
Исключение
Сообщить("Не удалось загрузить компоненту: "+ИмяКомпоненты);
Сообщить(ОписаниеОшибки());
Возврат Стрк
КонецПопытки;
Стрк.Приложение=COM;
ТЗ2=ПодключитьКомпоненту(ИмяКомпоненты, ИмяПроцесса, Истина);
//=Получить отличающиеся строки
СистемнаяКолонка="_ГруппаКолонка";
мКолонки=ТЗ1.Колонки; //Получить массив имён колонок
СтрКолонки="";
Для Каждого ИмяК Из мКолонки Цикл
СтрКолонки=СтрКолонки+ИмяК.Имя+",";
КонецЦикла;
СтрКолонки=Лев(СтрКолонки, СтрДлина(СтрКолонки)-1);
//=Объединить таблицы
Таблица3=ТЗ1.Скопировать();
Для Каждого СтрТаб Из ТЗ2 Цикл
ЗаполнитьЗначенияСвойств(Таблица3.Добавить(), СтрТаб);
КонецЦикла;
Таблица3.Колонки.Добавить(СистемнаяКолонка);
Таблица3.ЗаполнитьЗначения(1,СистемнаяКолонка);
Таблица3.Свернуть(СтрКолонки,СистемнаяКолонка);
мСтр=Таблица3.НайтиСтроки(Новый Структура(СистемнаяКолонка, 1));
Если мСтр.Количество()=1 Тогда
Стрк.ИД=мСтр[0].ИД;
Стрк.РодительскийИД=мСтр[0].РодительскийИД;
КонецЕсли;
Возврат Стрк
КонецФункции
Вопрос для всех.
Интересно узнать как всё это провернуть более простыми решениями для определения ИД запущенного процесса?