Использование модуля 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), который до сих пор не обсуждался, будет содержать информацию о самом процессе и потоках. Обладая этой информацией, вы сможете делать любопытные вещи, например, манипулировать приоритетами потоков и окнами этого процесса. Мы не собираемся рассматривать эти возможности, но упомянуть о них следует, чтобы спокойно перейти к следующему модулю.