Perl для системного администрирования

       

Использование модуля Win32 IProc



Использование модуля Win32::IProc

Второй подход - применять модуль Win32: : IProc Амина Мюлэй Рамдэна (Amine Moulay Ramdane). И хотя название подсказывает, казалось бы, очевидный выбор, но Win32: : Iproc, в действительности, гораздо полезнее для нас, чем Win32: :Process. У Win32: : Process есть один значительный недостаток, который тут же выводит модуль из борьбы: он создан для работы с процессами, которые были запущены им самим. В то время как нас больше интересуют процессы, запущенные другими пользователями. Если вам не удается установить модуль Win32: :IProc, загляните в раздел «Информация о модулях из этой главы» .

Сначала необходимо создать объект процесса подобным образом:

use Win32::IProc;

и обратите внимание на регистр.

Обязательно должно быть "IProc"

$pobj = new Win32::IProc or die

"Невозможно создать объект proccess: $!\n";

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

$pobj-> EnumProccesses(\@processlist) or

die "Невозможно получить список процессов:$!\n";

@processlist - это массив ссылок на анонимные хэши. В каждом анонимном хэше есть два ключа: ProcessName и Processld с их значениями. Такой код позволяет аккуратно вывести нужную информацию:

use Win32::IProc;

$pobj=new Win32::IProc or die



$pobj->EnumPrecesses(VSprocessiis и or

die "Невозможно получитэ список процессор:$г\п';

foreach Sprocess (@processlist){

$pid = $process-x{ProcessId};

Snair.e - $cessNama}; write:

}

format STDOUT_TCP =

Process ID Process Name

format STDOUT =

@<««« @««« ««««««««««««

$pid, $name

Получаем результат:

Process ID Process Name

======= ===========

0 System-Idle

2 System

25 smss.exe

39 winlogon.exe

41 services.exe

48 lsass.exe

78 spoolss.exe

82 OKSERVICE.EXE

Отличие от действий pulist.exe заключается в том, что Win32: : IP roc не может сообщить вам пользовательский контекст для процесса. Если эта информация для вас важна, то следует применять pulist.exe.

pulist.exe может вывести только один тип информации, а что может Win32: - сейчас будет ясно. Допустим, вам хочется узнать не только о запущенных процессах, но и о том, какие исполняемые программы и динамически загружаемые библиотеки (.сШ) использует каждый процесс. Получить эту информацию просто:

импортируем постоянную FULLPATH.

чтоб показывать пути к

библиотекам, может быть и NOPATH use

Win32:.IProc "FULLPATH": Spobj = пел Win32::IProc:

$pobj ->EnuTiProcesses(\5processlist) or die

"Невозможно список процессов : $;

foreach Sp^ocess (?processlisr){ print "\n".

$p^ocess->(D''ocessNaTie!

"\n".(' = ' x length($orocess->{ProcessNa~e})!. "-n":

Vswodules,FULLPATH); print join("\n", map {lc $_->

{Modul'eName}} ^modules), "\n":

}

GetProcessModules() получает идентификатор процесса, ссылку на массив и флаг, говорящий о том, возвращать ли полный путь к библиотеке. Элементами массива, на который мы ссылаемся, являются ссылки на анонимные хэши, содержащие информацию о каждой библиотеке, используемой этим процессом. В нашем примере собираются имена всех библиотек. тар() используется для того, чтобы обойти весь массив ссылок, разыменовывать каждый анонимный хэш и получить значение ключа ModuleName.

Вот отрывок полученных данных:

smss.exe

\systemroot\system32\smss.exe c:\winnt\system32\ntdll.dll

winlogon.exe

\??\с:\winnt\system32\winlogon.exe

c:\winnt\system32\ntdll.dll

c:\winnt\system32\msvcrt.dll

c:\winnt\system32\kernel32.dll

c:\winnt\system32\advapi32.dll

c:\winnt\system32\user32.dll

c:\winnt\systein32\gdi32.dll

c:\winnt\system32\rpcrt4.dll

c:\winnt\system32\userenv.dll

c:\winnt\system32\shell32.dll

c:\winnt\system32\shlwapi.dll

с:\winnt\system32\comctl32.dll

c:\winnt\system32\netapi32.dll

С:\winnt\system32\netrap. dll

c:\winnt\system32\samlib.dll

c:\winnt\system32\winmm. dll

с:\winnt\system32\cwcmmsys.dll

c:\winnt\system32\cwcfm3.dll

c:\winnt\system32\msgina.dll

c:\winnt\system32\rpclts1.dll

c:\winnt\system32\rpcltcl. all. . .

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

Дескриптор процесса можно рассматривать как открытое соединение с данным процессом. Чтобы выяснить разницу между дескриптором процесса и его идентификатором, проведем аналогию со стоянкой прицепов. Если каждый прицеп на стоянке считать процессом, то адрес прицепа можно считать идентификатором процесса. Это способ найти нужный прицеп. Дескриптор процесса - это что-то наподобие телефонных линий, труб и проводов, подведенных к прицепу. Когда прицеп подсоединен к этим коммуникациям, вы можете не только найти нужный прицеп, но и передавать в него информацию.

Для получения дескриптора процесса, если у нас есть его идентификатор, используем метод Ореп() из модуля Win32: : IProc. Ореп() принимает идентификатор процесса, флаг доступа, флаг наследования и ссылку на скалярное значение, в котором хранится дескриптор. В следующем примере запроса мы будем использовать флаги доступа, которых достаточно для получения информации о процессе. Подробную информацию об этих флагах можно найти в документации по Win32: :IProc и в разделе «Processes and Threads» документации Win32 SDK по основным службам, которую можно найти на http://msdn.microsoft.com. Дескрипторы процессов, открытые при помощи Ореп(), необходимо закрыть при помощи CloseHandle().

Зная дескриптор процесса, можно использовать метод Kill() для завершения его работы:

завершить процесс и заставить его вернуть именно этот код

$pobj->Kill($handle.$exitcode);

Но дескрипторы процессов следует применять не только для того, чтобы завершать работу процесса. Например, можно использовать такие методы, как GetStatusQ, чтобы больше узнать о процессе. Вот пример кода, который выводит информацию о времени для заданного идентификатора процесса:

use Win32::IProc qw(

PROCESS_QUERY_INFORMATION INHERITED DIGITAL);

$pobj = new Win32::IProc;

$pobj->Open($ARGV[0],PROCESS_QUERY_INFORMATION, INHERITED. \$handle) or warn

"Невозможно получить дескриптор:".$pobj->LastError()."\n";

ft DIGITAL = время в понятном формате $pouj->

GetStatus($handle,\$statusinfo.DIGITAL):

$pobj->CloseHandle($handle):

while ((Sprocname,$vaiue)=eacn %$statusinfo){

print "$procname: $value\n":

}

В результате получается что-то приблизительно следующее:

Kernelrii?L-: 00;00:22:442:270 Fxituate:

ExitTime:

CreationDate: 29/7/1999 CreationTime:

17:09:28:100

UserTime:

00:00:11:566:632

Теперь известно, когда процесс был запущен и сколько системного времени он занимает. Поля ExitDate и ExitTime пусты, поскольку процесс все еще активен. Вы могли бы спросить, как эти поля, в принципе, могут оказаться не пустыми, если для получения дескриптора нужно использовать идентификатор работающего процесса? На этот вопрос есть два ответа. Во-первых, можно получить дескриптор для работающего процесса, а затем заставить этот процесс завершиться до того, как вы закроете дескриптор. GetStatusO в таком случае вернет информацию о завершении работы для умершего процесса. Вторая возможность получить эту информацию- использовать метод Сгеate(), о котором мы пока еще не знаем.

Create О

позволяет запускать процессы из Win32: так же, как и в случае с Win32::Process. Если запустить процесс при помощи модуля, то объект процесса ($pobj), который до сих пор не обсуждался, будет содержать информацию о самом процессе и потоках. Обладая этой информацией, вы сможете делать любопытные вещи, например, манипулировать приоритетами потоков и окнами этого процесса. Мы не собираемся рассматривать эти возможности, но упомянуть о них следует, чтобы спокойно перейти к следующему модулю.

Содержание раздела