Получение характеристик и управление текущим процессом 1С на основе WMI

09.07.12

Разработка - Универсальные функции

Функционал для работы из 1С с текущим процессом класса Win32_Process. Пример получает текущее значение ОЗУ занятое процессом 1С. По описанной методике можно получать значения пиковых нагрузок на ОЗУ, время запуска текущей сессии 1С с точностью до миллисекунд. Определять загрузку активного ядра процессом и даже поменять приоритет самого процесса.

Все началось с этого топика. Ну, а точнее с поднятой темы. Идея использовать для получения размера временной структуры в ОЗУ средства WMI оказалось живучей и в конце концов привела меня к набору инструментов, позволяющих исследовать и управлять процессом 1С при помощи инструментария в общем-то диспетчера задач Windows.

Определение размера объекта, созданного в 1С при помощи замеров свободной ОЗУ оказалось не слишком информативно, так как память одновременно с 1С могут занимать и высвобождать другие процессы, поэтому пришлось идентифицировать и изучать запущенный процесс 1С. Наилучшим средством оказался класс Win32_Process, который по сути и представляет собой основу диспетчера задач Windows и при помощи нехитрых изменений базовый код функции определения объема занятой процессом ОЗУ может применяться также и для определения пиковых нагрузок, времени работы процесса, процента загрузки процессора и еще многого другого. Также можно выполнять некоторые действия с процессом типа изменения приоритета процесса.

Подробнее о доступных свойствах и методах, конечно в MSDN по классу здесь.

Ну а теперь собственно функция. Сначала для 7.7

Функция ПамятьПодПроцессом()

  //Возвращает объем ОЗУ, занимаемой текущим процессом 1С 7.7 в байтах

  //Через rundll32 получаем ID текущего процесса 1С 
  WSHShell = СоздатьОбъект("WScript.Shell");
  l = СоздатьОбъект("wbemscripting.swbemlocator");
  oExec = WshShell.Exec("rundll32 kernel32,SleepEx");
  s = l.connectserver();
  ProcessID = s.get("win32_process.Handle="+oExec.ProcessID).ParentProcessID;
  УбитьРандл = oExec.ProcessID;
  oExec = "";
  // Убиваем запущеный rundll32
  Скрипт = "
  |Function KillProc(ProcessID)
  |strComputer = ""."" 
  |Set objWMIService = GetObject(""winmgmts:\\"" & strComputer & ""\root\CIMV2"") 
  |Set colProcesses = objWMIService.ExecQuery(""select * from win32_process where ProcessId ="" &ProcessID)
  |For Each objProcess in colProcesses
  |objProcess.Terminate()
  |Next
  |End Function
  |";
  ИспСкрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
  ИспСкрипт.Language="vbscript";
  ИспСкрипт.AddCode(Скрипт);
  ИспСкрипт.Modules("Global").CodeObject.KillProc(УбитьРандл);
  //Находим память под текущим процессом 1С - ProcessID
  Скрипт = "
  |Function UsedMemory(ProcessID)
  |strComputer = ""."" 
  |Set objWMIService = GetObject(""winmgmts:\\"" & strComputer & ""\root\CIMV2"") 
  |Set colProcesses = objWMIService.ExecQuery(""select * from win32_process where ProcessId ="" &ProcessID)
  |For Each objProcess in colProcesses
  |UsedMemory = objProcess.PageFileUsage
  |Next
  |End Function
  |";
  ИспСкрипт= СоздатьОбъект("MSScriptControl.ScriptControl");
  ИспСкрипт.Language="vbscript";
  ИспСкрипт.AddCode(Скрипт);
  Возврат Число(ИспСкрипт.Modules("Global").CodeObject.UsedMemory(ProcessID));
КонецФункции

 Так как работа с COM объектами и скриптами в 8-ке устроена несколько иначе, то для этой платформы та же функция будет выглядеть так:

Функция ПамятьПодПроцессом()

//Возвращает объем ОЗУ, занимаемой текущим процессом 1С 8 в байтах
 WSHShell = Новый COMОбъект("WScript.Shell");
 l= Новый COMОбъект("wbemscripting.swbemlocator");
 oExec=WshShell.Exec("rundll32 kernel32,SleepEx");
 s=l.connectserver();
 ProcessID=s.get("win32_process.Handle="+СтрЗаменить(Строка(oExec.ProcessID),Символ(160),"")).ParentProcessID;
 УбитьРандл = oExec.ProcessID;
 //Убиваем запущеный rundll32
 Скрипт = "
    |Function KillProc(ProcessID)
    |strComputer = "".""
    |Set objWMIService = GetObject(""winmgmts:\\"" & strComputer & ""\root\CIMV2"")
    |Set colProcesses = objWMIService.ExecQuery(""select * from win32_process where ProcessId ="" &ProcessID)
    |For Each objProcess in colProcesses
    |objProcess.Terminate()
    |Next
    |End Function
    |";
 ИспСкрипт = Новый COMОбъект("MSScriptControl.ScriptControl");
 ИспСкрипт.Language = "vbscript";
 ИспСкрипт.AddCode(Скрипт);
 ИспСкрипт.CodeObject.KillProc(УбитьРандл);
 //Возвращает память под текущим процессом 1С
 Скрипт = "
    |Function UsedMemory(ProcessID)
    |strComputer = "".""
    |Set objWMIService = GetObject(""winmgmts:\\"" & strComputer & ""\root\CIMV2"")
    |Set colProcesses = objWMIService.ExecQuery(""select * from win32_process where ProcessId ="" &ProcessID)
    |For Each objProcess in colProcesses
    |UsedMemory = objProcess.PageFileUsage
    |Next
    |End Function
    |";
 ИспСкрипт = Новый COMОбъект("MSScriptControl.ScriptControl");
 ИспСкрипт.Language = "vbscript";
 ИспСкрипт.AddCode(Скрипт);
 Возврат ИспСкрипт.Run("UsedMemory",ProcessID);
КонецФункции

UsedMemory = objProcess.PageFileUsage и есть процесс возврата нужной информации свойством PageFileUsage класса Win32_Process. Если, допустим, нас интересует когда был запущен текущий процесс с 1С нужно использовать свойство CreationDate. Ну, а изменить приоритет выполнения процесса можно с помощью метода SetPriority().

 Обе функции протестированы на работоспособность в XP SP3 и Win7 32. Не предполагаю проблем и с другими ОС, но ничего другого под рукой не было, так что ограничился этими вариантами.

Пытался использовать данный инструментарий для исследования принципов заполнения и высвобождения памяти клюшкой. Из общеметодологических выводов отмечу лишь такие, показавшиеся мне интересными моменты:

1. В большинстве случаев создание крупной структуры данных, вызывает увеличение объема занятой процессом ОЗУ (но НЕ ВСЕГДА!).

2. Конструкция типа Объект = ""; не высвобождает ОЗУ, занятую процессом и соответственно объектом

3. Чаще всего (но опять же не всегда) моментальное освобождение памяти происходит через инструкцию Объект = СоздатьОбъект() когда мы создаем новый объект по имени предыдущего.

Ну вот собственно и все. Для чего использовать данный инструмент, кроме исследования памяти занимаемой процессом решите сами. Я же если еще вернусь к более детальному исследованию особенностей поведения и использования ресурсов Windows процессом 1С, постараюсь свести свои результаты в более-менее солидное исследование и опубликую анализ полученных данных.

См. также

Библиотека процедур и функций для технологической платформы "1С: Предприятие 7.7"

Универсальные функции Платформа 1С v7.7 Россия Абонемент ($m)

В библиотеку собраны различные функции по работе с документами, журналами, типами данных, строками, датой и временем, таблицами значений, Excel, файлами, XML, JSON, Http-сервисами, SMTP серверами и т.п.

1 стартмани

22.12.2023    660    9    user706545_kseg1971    0    

4

1С 7.7 и новый 1С:Контрагент

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Россия Бесплатно (free)

Получение реквизитов контрагентов из 1С:Контрагент для старых конфигураций под 1с 7.7.

25.04.2022    1821    zhenyat    7    

6

Печать таблицы значений в 1С 7.7 при отладке

Универсальные функции Платформа 1С v7.7 Россия Бесплатно (free)

Функция выводит таблицу значений в табличный документ. (v7.7) Особенно полезно при отладке. Не нужно вносить изменения в код, вызываем функцию как вычисляемое выражение при останове. Если таблица обрабатывается в несколько этапов, можно вывести её после каждого и визуально проследить эволюцию.

30.06.2021    4404    Zoltan_Black    11    

2

Установка принтера по умолчанию для 1С 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Установка принтера по умолчанию в 1С 7.7. Обработка может быть полезна в том случае, когда нужно установить принтер по умолчанию, а доступа к рабочему столу нет (например, терминальный режим без рабочего стола или remoteApp)

1 стартмани

13.02.2019    13286    4    alsen    3    

4

Формирование строки json в 1С: 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 1С:Комплексная 7.7 Абонемент ($m)

Предлагается набор функций 1с 7.7 для формирования строки json стандартными средствами.

1 стартмани

10.12.2018    10107    malovandrey    5    

18

Как создать индикатор в 1С:Предприятии 7.7

Универсальные функции Работа с интерфейсом Платформа 1С v7.7 Конфигурации 1cv7 Россия Абонемент ($m)

В статье дано описание создания индикатора на форме в среде разработки 1С:Предприятие 7.7 исключительно типовыми средствами.

1 стартмани

27.09.2016    18676    2    HAMMER_59    6    

2
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. treedo 124 14.07.12 10:31 Сейчас в теме
Статья хорошая, но редко когда применяется...
3. dusha0020 1104 15.07.12 10:48 Сейчас в теме
(1) treedo, Применяется редко, но самый лучший багаж - это знания. Прочитал, понял и запомнил что можно так. Теперь это с тобой и когда-нибудь может пригодиться, а тяжелее не стало:)
2. CaSH_2004 372 14.07.12 13:20 Сейчас в теме
Отличная тема для изучения
4. malina-da 15.07.12 17:15 Сейчас в теме
В целях самообразования хорошая статья, спасибо автору, надеюсь пригодится в дальнейшем.
5. Stamper 43 16.07.12 13:22 Сейчас в теме
(0)
2. Конструкция типа Объект = ""; не высвобождает ОЗУ, занятую процессом и соответственно объектом
3. Чаще всего (но опять же не всегда) моментальное свобождение памяти происходит через инструкцию Объект = СоздатьОбъект() когда мы создаем новый объект по имени предыдущего.

не понял, т.е. чтобы освободить память от "Объект" из п.2 нужно в эту переменную поместить другой объект? но ведь тогда он снова займёт какую-то память, может даже и большую.
прошу объяснить! спасибо
6. dusha0020 1104 16.07.12 13:48 Сейчас в теме
(5) Stamper, Объяснить трудно. Приведу пример из практики:
Замеряем объем ОЗУ под процессом. Допустим получили Х1. Дальше:
ТЗ = СоздатьОбъект("ТаблицаЗначений");
Затем добавляем поля и строки заполняя их чем либо. Наша ТЗ получила большущий объем информации и мы снова земеряем память. Получаем Х2>>Х1.
Если теперь написать так:
ТЗ = "";
и замерить ОЗУ то получим снова Х2:), а если так:
ТЗ = СоздатьОбъект("ТаблицаЗначений");
то в большинстве случаев X2 будет чуть больше или равно X1.

Процессы выделения и очистки памяти строго в клюшке (про 8-ку не знаю не исследовал) не привязаны к каким либо командам собственно языка 1С. Они вызываются транслятором или даже виндой по их собственному разумению. Поэтому в формулировках выводов у меня и написано "как правило" и "почти наверняка":)
7. Stamper 43 16.07.12 21:26 Сейчас в теме
(6) ой, это для 7.7? никак не привыкну смотреть на версию
Оставьте свое сообщение