Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.07.11;
Скачать: [xml.tar.bz2];

Вниз

Как узнать запущен ли экзекшник по его имени?   Найти похожие ветки 

 
FireHawk   (2005-05-14 21:16) [0]

Собственно, в сабже всё сказано. Знаем путь к программе и её имя. Не знаем имя окна, класса, ничего. Как резидентной программе узнать, запущен ли экзешник?


 
Dimaxx ©   (2005-05-15 00:10) [1]

GetModuleHandle. Если вернула INVALID_HANDLE_VALUE, то не запушена. Иначе получим хэндл.


 
Almaz ©   (2005-05-15 03:07) [2]


> Dimaxx ©   (15.05.05 00:10) [1]
> GetModuleHandle. Если вернула INVALID_HANDLE_VALUE, то не
> запушена. Иначе получим хэндл.

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


> FireHawk   (14.05.05 21:16)  
> Собственно, в сабже всё сказано. Знаем путь к программе
> и её имя. Не знаем имя окна, класса, ничего. Как резидентной
> программе узнать, запущен ли экзешник?

Вам следует воспользоваться, например, 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 AnsiCompareText(lppe.szExeFile, ExeFileName) = 0 then
   begin
     Result := True;
     Break;
   end;
 until not Process32Next(hSnapshot, lppe);
 CloseHandle(hSnapshot);
end;

...

if IsExeRunnign("Delphi32.exe") then
 ShowMessage("Delphi is running");


Удачи.


 
peppo ©   (2005-05-15 10:09) [3]

Гораздо быстрее - просто открыть файл

if FileOpen( Application.ExeName, fmOpenReadWrite)<0 then //запущен


 
peppo ©   (2005-05-15 10:10) [4]

Application.ExeName  в смысле путь к файлу


 
VMcL ©   (2005-05-15 10:21) [5]

>>Almaz ©   (15.05.05 03:07) [2]

Я понимаю, что в вопросе указана WinXP, но:

1. >if AnsiCompareText(lppe.szExeFile, ExeFileName) = 0 then

if AnsiCompareText(ExtractFileName(lppe.szExeFile), ExeFileName) = 0 then
Поскольку в Win9x возвращается полный путь к файлу.

2. PsAPI для Win NT.

>>peppo ©   (15.05.05 10:09) [3]
>>peppo ©   (15.05.05 10:10) [4]

Огромная просьба: не давать глюкосоветы в тематических конференциях.


 
peppo ©   (2005-05-15 11:06) [6]

> Огромная просьба: не давать глюкосоветы в тематических
> конференциях.

Понимаю, не буду.
Но работает же :)


 
VMcL ©   (2005-05-15 11:14) [7]

>>peppo ©   (15.05.05 11:06) [6]

Код-то работает. Только к сабджевому вопросу не имеет никакого отношения.


 
peppo ©   (2005-05-15 11:56) [8]

> VMcL ©   (15.05.05 11:14) [7]

А этого не понимаю. Почему никакого?
Требовалось узнать запущен ли некий exe, имеется полный путь к нему.
Если попытаться открыть этот файл, то, если он используется однозначно будет получен отказ => запущен (ведь exe становится сам-себе страничным файлом при запуске).
Его, конечно, кто-то может просто открыть, а не запустить, поэтому совет и "глючный"(может ещё почему-то), но по сабжу...
Я не припираюсь, просто хочу понять что криво.


 
Ученик   (2005-05-15 11:59) [9]

>VMcL ©   (15.05.05 10:21) [5]
>2.

Вы считаете, что так совсем неправильно или необходимо изменить
параметр fmOpenReadWrite ?


 
Ученик   (2005-05-15 12:09) [10]

>peppo ©   (15.05.05 10:09) [3]
Файл может Read Only и запущен


 
VMcL ©   (2005-05-15 12:27) [11]

>>peppo ©   (15.05.05 11:56) [8]

>Его, конечно, кто-то может просто открыть, а не запустить, поэтому совет и "глючный"

Сами же и ответили на свой вопрос.


 
SammIk ©   (2005-05-15 13:01) [12]

2 [3]
Я чуть от смеха не помер=)))
Это ты проверяешь из своей программы, запущенали она сама?
бу гага


 
peppo ©   (2005-05-15 15:13) [13]

> SammIk ©   (15.05.05 13:01) [12]

И что?
Это тест, адекватный рассматриваемой теме, а не часть сурьёзной программы.


 
peppo ©   (2005-05-15 15:17) [14]

> Это ты проверяешь из своей программы, запущенали она
> сама?

Молодец, правильно понял.


 
Medved ©   (2005-05-15 17:21) [15]

Программа большая, зато работает!

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) и \?? (просто убрать).


 
Medved ©   (2005-05-15 17:28) [16]

Комментарии в самом начале RefreshClick выглядят так:

   PIDarray:array [ 0 .. $FFF ] of DWORD; // PID list
   // $FFF - на всякий случай. Кто знает, сколько процессов
   // может быть запущено в системе. Я запускал 822
   // (последнее, что показал taskmgr.exe).

(копировал из Delphi IDE, оказалась неправильная кодировка).


 
FireHawk   (2005-05-15 22:24) [17]

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_ сообщение, посылаемое при запуске любой программы?


 
FireHawk   (2005-05-15 22:32) [18]

2 Medved
Действительно большая программа. Вроде работает. С токенами возиться не охота - в WinNT/2000 могут быть проблемы при работе с ограниченными учетными записями. Но пока это самый лучший вариант. Опять же, смотрите мой предыдущий пост - зацикливание проверки не подходит, нужно как-то отлавливать момент запуска.


 
Ученик   (2005-05-15 23:04) [19]

>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.


 
Ученик   (2005-05-15 23:07) [20]

>Ученик   (15.05.05 23:04) [19]
SetWindowsHoookEx => SetWindowsHookEx :-)


 
Almaz ©   (2005-05-16 05:18) [21]


> В строке
> if Process32First(hSnapshot, lppe) then
> выражение всегда false, поэтому после этого момента происходит
> выход из функции.

А что при этом возвращает GetLastError, если не секрет ?


> К тому-же имя исполняемого файла часто отличается от имени
> процесса, например при запуске Opera8.exe вы получаете процесс
> Opera.exe.

А что есть имя процесса если не имя исполняемого файла ? Просто Opera8.exe скорее всего запускает Opera.exe.


> Имелось в виду - открыт в текстовом редакторе для правки?

Имелось ввиду открыт на монопольный доступ. Текстовый редактор , как правило, так не делает.


> Поэтому вопрос: а можно ли отлавливать какое нибудь WM_
> сообщение, посылаемое при запуске любой программы?

Подобного сообщения не существует. Если искомые программы создают хотя бы одно окно, то используйте хуки - см. пост  Ученик [19]. Если же программы могут не иметь окон, то тут вам скорее всего придется писать драйвер или заниматься перехватом API вызовов.

Удачи.


 
SammIk ©   (2005-05-16 05:32) [22]

2 peppo
Все равно вы не правы.
Проверять из программы запущена ли она, все равно, что вы будите
сейчас проверять живы ли вы.
Абсурд, не так ли?


 
VMcL ©   (2005-05-16 07:44) [23]

>>SammIk ©   (16.05.05 05:32) [22]

Путь некорректный, но прочитать [4] после [3] стОит, чтобы не садиться в лужу.

>>Almaz ©   (16.05.05 05:18) [21]

>Имелось ввиду открыт на монопольный доступ. Текстовый редактор , как правило, так не делает.

MS Word делает. Хотя Word - это не текстовый редактор, а графико-текстовый процессор.


 
Almaz ©   (2005-05-16 10:19) [24]


> Хотя Word - это не текстовый редактор, а графико-текстовый
> процессор.

Именно. Судя по тому, что у автора опыт не удался - это был блокнот или что-то ему подобное.

Удачи.


 
GrayFace ©   (2005-05-16 16:10) [25]

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 работать не будет.


 
SammIk ©   (2005-05-16 16:26) [26]

Не обратил внимания.


 
alpet ©   (2005-05-16 17:12) [27]

Almaz ©   (15.05.05 03:07) [2]
В ответе не выставлена строчка (из-за чего и не работает Process32First):
 
lppe.dwSize := SizeOf (lppe);

В добавок в Toolhelp функциях есть еще енумераторы модулей...

Автору сабжа наверное проще будет написать маленькую программу, замещающую exe-файл конкретного процесса, которая будет отправлять сообщения в основную программу и запускать сей процесс на выполнение.


 
Dimaxx ©   (2005-05-16 21:18) [28]

Я видел пример (не помню уж что там делалось), который таким образом определял наличие в памяти kernel32.dll и получал его хэндл, чтобы обратиться к занимаемой им памяти. Попробую найти и показать его, но не обещаю. И там такой прием работал. Причем не я сам эту библиотеку загружал.

Так что сказанное Almaz"ом не совсем верно.


 
Almaz ©   (2005-05-16 21:34) [29]


> 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.
Обратите внимание на выделенные строчки.

Удачи.


 
Almaz ©   (2005-05-16 21:41) [30]


> 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;


Удачи.


 
FireHawk   (2005-05-16 23:21) [31]

М-да... Не ожидал я, что написание простенькой в общем-то программы упрется в такую проблему. Функция Almaz`a работает на ура, за что ему и alpet`у огромное спасибо. А насчет отслеживания запуска программы - пожалуй, придётся повозиться с написанием сервиса под WinNT, благо опыт имеется, а под 98/Me влеплю проверку по таймеру каждые 5 секунд. Я, в конце концов, драйвер файловой системы писать не вызывался. Жаль, предложение ученика не подходит - многие приложения вообще без визуальных компонентов и окон не создают. Но все равно, огромное ЕМУ И ВСЕМ ВАМ СПАСИБО!



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.07.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.041 c
14-1116797256
Piter
2005-05-23 01:27
2005.07.11
Вспоминая старое...


14-1118487315
Kerk
2005-06-11 14:55
2005.07.11
Линуксоидам или я уж не знаю кому...


14-1118759928
Lucifer
2005-06-14 18:38
2005.07.11
Помогите выбрать сканер!


6-1112684047
frEE)stylEr
2005-04-05 10:54
2005.07.11
подключение удалённого доступа


1-1118261613
SniZ
2005-06-09 00:13
2005.07.11
Сжатие строки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский