![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как узнать запущен ли экзекшник по его имени? [D7, WinXP]
FireHawk © (2005-05-14 21:16:00)Собственно, в сабже всё сказано. Знаем путь к программе и её имя. Не знаем имя окна, класса, ничего. Как резидентной программе узнать, запущен ли экзешник?
FireHawk (2005-05-16 23:21:00) [1]М-да... Не ожидал я, что написание простенькой в общем-то программы упрется в такую проблему. Функция Almaz`a работает на ура, за что ему и alpet`у огромное спасибо. А насчет отслеживания запуска программы - пожалуй, придётся повозиться с написанием сервиса под WinNT, благо опыт имеется, а под 98/Me влеплю проверку по таймеру каждые 5 секунд. Я, в конце концов, драйвер файловой системы писать не вызывался. Жаль, предложение ученика не подходит - многие приложения вообще без визуальных компонентов и окон не создают. Но все равно, огромное ЕМУ И ВСЕМ ВАМ СПАСИБО!
Almaz (2005-05-16 21:41:00) [2]
> alpet © (16.05.05 17:12) [27]
> Almaz © (15.05.05 03:07) [2]
> В ответе не выставлена строчка (из-за чего и не работает
> Process32First):
>
> lppe.dwSize := SizeOf (lppe);
Точно, вы абсолютно правы - спасибо, что заметили - писал по памяти, вот и забыл :(
>FireHawk (15.05.05 22:24) [17]
Как справедливо заметил alpet, функция должна выглядить так:
function IsExeRunnign(ExeFileName: TFileName): Boolean;
var
hSnapshot: THandle;
lppe: TProcessEntry32;
begin
Result := False;
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
lppe.dwSize := sizeof(lppe);
if Process32First(hSnapshot, lppe) then
repeat
if AnsiCompareText(ExtractFileName(lppe.szExeFile), ExeFileName) = 0 then
begin
Result := True;
Break;
end;
until not Process32Next(hSnapshot, lppe);
CloseHandle(hSnapshot);
end;
Удачи.
Almaz (2005-05-16 21:34:00) [3]
> Dimaxx © (16.05.05 21:18) [28]
> Я видел пример (не помню уж что там делалось), который таким
> образом определял наличие в памяти kernel32.dll и получал
> его хэндл, чтобы обратиться к занимаемой им памяти. Попробую
> найти и показать его, но не обещаю. И там такой прием работал.
> Причем не я сам эту библиотеку загружал.
>
> Так что сказанное Almaz'ом не совсем верно.
Обратите внимание - проверял наличие в памяти, причем именно своей памяти (своего АП) и именно DLL, а не EXE. Естественно, что Kernel32.dll равно как и User32.dll и т.п. вы сами не загружали - это делает за вас система.
Чтобы развеять ваши сомнения приведу цитату из MSDN:
The GetModuleHandle function returns a module handle for the specified module if the file has been mapped into the address space of the calling process.
Обратите внимание на выделенные строчки.
Удачи.
Dimaxx (2005-05-16 21:18:00) [4]Я видел пример (не помню уж что там делалось), который таким образом определял наличие в памяти kernel32.dll и получал его хэндл, чтобы обратиться к занимаемой им памяти. Попробую найти и показать его, но не обещаю. И там такой прием работал. Причем не я сам эту библиотеку загружал.
Так что сказанное Almaz'ом не совсем верно.
alpet (2005-05-16 17:12:00) [5]Almaz © (15.05.05 03:07) [2]
В ответе не выставлена строчка (из-за чего и не работает Process32First):
lppe.dwSize := SizeOf (lppe);
В добавок в Toolhelp функциях есть еще енумераторы модулей...
Автору сабжа наверное проще будет написать маленькую программу, замещающую exe-файл конкретного процесса, которая будет отправлять сообщения в основную программу и запускать сей процесс на выполнение.
SammIk (2005-05-16 16:26:00) [6]Не обратил внимания.
GrayFace (2005-05-16 16:10:00) [7]FireHawk (15.05.05 22:24) [17]
Имелось в виду - открыт в текстовом редакторе для правки? Даже в этом случае функция возвращает правильное значение - проверял.
Если exe не запущен, но в этот момент из него что-то читают или в него что-то пушут, то результат неправильный.
Almaz © (16.05.05 5:18) [21]
Если же программы могут не иметь окон, то тут вам скорее всего придется писать драйвер или заниматься перехватом API вызовов.
Про драйвер ничего не могу сказать, но перехват тут не причем. В таком случае можно только внедриться через реестр. В HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs добавить свою DLL и при ее инициализации, например, слать сообщение окну своей программы. В Win9x работать не будет.
Almaz (2005-05-16 10:19:00) [8]
> Хотя Word - это не текстовый редактор, а графико-текстовый
> процессор.
Именно. Судя по тому, что у автора опыт не удался - это был блокнот или что-то ему подобное.
Удачи.
VMcL (2005-05-16 07:44:00) [9]>> SammIk © (16.05.05 05:32) [22]
Путь некорректный, но прочитать [4] после [3] стОит, чтобы не садиться в лужу.
>> Almaz © (16.05.05 05:18) [21]
> Имелось ввиду открыт на монопольный доступ. Текстовый редактор , как правило, так не делает.
MS Word делает. Хотя Word - это не текстовый редактор, а графико-текстовый процессор.
SammIk (2005-05-16 05:32:00) [10]2 peppo
Все равно вы не правы.
Проверять из программы запущена ли она, все равно, что вы будите
сейчас проверять живы ли вы.
Абсурд, не так ли?
Almaz (2005-05-16 05:18:00) [11]
> В строке
> if Process32First(hSnapshot, lppe) then
> выражение всегда false, поэтому после этого момента происходит
> выход из функции.
А что при этом возвращает GetLastError, если не секрет ?
> К тому-же имя исполняемого файла часто отличается от имени
> процесса, например при запуске Opera8.exe вы получаете процесс
> Opera.exe.
А что есть имя процесса если не имя исполняемого файла ? Просто Opera8.exe скорее всего запускает Opera.exe.
> Имелось в виду - открыт в текстовом редакторе для правки?
Имелось ввиду открыт на монопольный доступ. Текстовый редактор , как правило, так не делает.
> Поэтому вопрос: а можно ли отлавливать какое нибудь WM_
> сообщение, посылаемое при запуске любой программы?
Подобного сообщения не существует. Если искомые программы создают хотя бы одно окно, то используйте хуки - см. пост Ученик [19]. Если же программы могут не иметь окон, то тут вам скорее всего придется писать драйвер или заниматься перехватом API вызовов.
Удачи.
Ученик (2005-05-15 23:07:00) [12]>Ученик (15.05.05 23:04) [19]
SetWindowsHoookEx => SetWindowsHookEx :-)
Ученик (2005-05-15 23:04:00) [13]>FireHawk (15.05.05 22:24) [17]
>"Read Only и запущен".
Файл может иметь атрибут Read Only или права Read Only, тогда его нельзя открыть в режиме ReadWrite
>FireHawk (15.05.05 22:32) [18]
А SetWindowsHoookEx с WH_SHELL не подойдет ?
WH_SHELL
Windows calls this hook when actions occur to top-level (that is, unowned) windows.
HSHELL_WINDOWCREATED: Windows calls the WH_SHELL hook when a top-level window is created. The window already exists when this hook is called.
HSHELL_WINDOWDESTROYED: Windows calls the WH_SHELL hook when a top-level window is about to be destroyed.
HSHELL_ACTIVATESHELLWINDOW: This hook code is not used at this time.
FireHawk (2005-05-15 22:32:00) [14]2 Medved
Действительно большая программа. Вроде работает. С токенами возиться не охота - в WinNT/2000 могут быть проблемы при работе с ограниченными учетными записями. Но пока это самый лучший вариант. Опять же, смотрите мой предыдущий пост - зацикливание проверки не подходит, нужно как-то отлавливать момент запуска.
FireHawk (2005-05-15 22:24:00) [15]2 Almaz
/Вам следует воспользоваться, например, Toolhelp API функциями/
/Что-то вроде этого:/
function IsExeRunnign(ExeFileName: TFileName): Boolean;
var
hSnapshot: THandle;
lppe: TProcessEntry32;
begin
Result := False;
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if Process32First(hSnapshot, lppe) then
repeat
...
;
К сожалению, не работает. Почему - не пойму. В строке
if Process32First(hSnapshot, lppe) then
выражение всегда false, поэтому после этого момента происходит выход из функции. В доках я про Process32First ничего не нашел, поэтому как это работает я не представляю. К тому-же имя исполняемого файла часто отличается от имени процесса, например при запуске Opera8.exe вы получаете процесс Opera.exe. Если чего-то не понял, виноват, пожалуйста объясните.
Едем дальше. Многократно битый peppo предложил вполне работающий вариант. Я только не понял, что значит "может просто открыть, а не запустить" [8]или "Read Only и запущен". Имелось в виду - открыт в текстовом редакторе для правки? Даже в этом случае функция возвращает правильное значение - проверял.
Беда в том, что несмотря на работоспособность решения рерро оно мне не подходит. Дело в том, что пишется программа-профайлер, которая при запуске определённых программ изменяет некоторые записи в реестре, системные переменные и др. А зацикливание FileOpen с непрерывным перебором двух десятков файлов, верите-ли, создает небольшие такие проблемы :) Поэтому вопрос: а можно ли отлавливать какое нибудь WM_ сообщение, посылаемое при запуске любой программы?
Medved (2005-05-15 17:28:00) [16]Комментарии в самом начале RefreshClick выглядят так:
PIDarray:array [ 0 .. $FFF ] of DWORD; // PID list
// $FFF - на всякий случай. Кто знает, сколько процессов
// может быть запущено в системе. Я запускал 822
// (последнее, что показал taskmgr.exe).
(копировал из Delphi IDE, оказалась неправильная кодировка).
Medved (2005-05-15 17:21:00) [17]Программа большая, зато работает!
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, PSAPI;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Refresh: TButton;
Exit: TButton;
procedure ExitClick(Sender: TObject);
procedure RefreshClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ExitClick(Sender: TObject);
begin
Close;
end;
procedure TForm1.RefreshClick(Sender: TObject);
var
PIDarray:array [ 0 .. $FFF ] of DWORD; // PID list
// $FFF - ?? ?????? ??????. ??? ?????, ??????? ????????????
// ????? ???? ???????? ? ???????. ? ???????? 822
// (?????????, ??? ??????? taskmgr.exe).
PIDcount:DWORD;
hToken:THandle;
PreviousState,TokenPrivileges:TTokenPrivileges;
privilege_value:int64;
ReturnLength:DWORD;
i:integer;
Count: DWORD;
ProcHand: THandle;
ModName: array[0..MAX_PATH] of char;
ModHand: array [ 0 .. $3FF ] of HMODULE;
begin
// Get PID list
if not EnumProcesses(@PIDarray,SizeOf(PIDarray),PIDCount)
then
begin
ShowMessage('Cannot enum PIDs!');
System.Exit;
end;
PIDcount:=PIDcount div 4;
// set SeDebugPrivilege
if not OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken)
then
begin
ShowMessage('Cannot open process token!');
System.Exit;
end;
if not LookupPrivilegeValue(nil,PAnsiChar('SeDebugPrivilege'),privilege_value)
then
begin
ShowMessage('Cannot lookup privilege value!');
System.Exit;
end;
with TokenPrivileges do
begin
PrivilegeCount:=1;
Privileges[0].Luid:=privilege_value;
Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
end;
ReturnLength:=SizeOf(TokenPrivileges);
AdjustTokenPrivileges(hToken,False,TokenPrivileges,SizeOf(TokenPrivileges),PreviousState,ReturnLength);
if GetLastError<> ERROR_SUCCESS
then
begin
ShowMessage('Cannot adjust token privileges!');
System.Exit;
end;
// get process EXE-names
ListBox1.Items.Clear;
ListBox1.Items.Add('Process count: '+IntToStr(PIDcount));
for i:=0 to PIDcount-1 do
begin
ProcHand := OpenProcess( PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
False,
PIDarray[i]);
EnumProcessModules(ProcHand, @ModHand, SizeOf(ModHand), Count);
if GetModuleFileNameEx(Prochand, ModHand[0], ModName, SizeOf(ModName)) > 0
then
ListBox1.Items.Add(String(ModName));
end;
end;
end.
На форме 2 кнопки и ListBox.
И ещё надо проверить начало пути на наличие \SystemRoot (заменить на путь к системной папке Windows) и \?? (просто убрать).
peppo (2005-05-15 15:17:00) [18]> Это ты проверяешь из своей программы, запущенали она
> сама?
Молодец, правильно понял.
peppo (2005-05-15 15:13:00) [19]> SammIk © (15.05.05 13:01) [12]
И что?
Это тест, адекватный рассматриваемой теме, а не часть сурьёзной программы.
SammIk (2005-05-15 13:01:00) [20]2 [3]
Я чуть от смеха не помер=)))
Это ты проверяешь из своей программы, запущенали она сама?
бу гага