Как проверить с помощью Inno Setup, запущен ли процесс на Windows 2008 R2 64bit?
Я прочитал следующий пост. Мой код выглядит точно так же, но не работает:
Inno Setup Проверка работающего процесса
Я скопировал пример с http://www.vincenzo.net/isxkb/index.php?title=PSVince
Но пример также не работает, даже если я изменю код следующим образом:
[Code]
function IsModuleLoaded(modulename: AnsiString): Boolean;
external '[email protected]:psvince.dll stdcall';
Код всегда возвращает false
(программа не запущена, даже работает). Протестировано на Windows 2008 R2 и Windows 7.
На самом деле я хочу проверить, tomcat5.exe
или нет. Так что я думаю, что не могу работать с AppMutex
.
Я также видел https://code.google.com/p/psvince/source/detail?r=5
Но я не могу найти какие-либо факты о совместимости этой DLL.
Полный код:
[Files]
Source: psvince.dll; Flags: dontcopy
[Code]
function IsModuleLoaded(modulename: AnsiString ): Boolean;
external '[email protected]:psvince.dll stdcall';
function InitializeSetup(): Boolean;
begin
if(IsModuleLoaded( 'notepad.exe' )) then
begin
MsgBox('Running', mbInformation, MB_OK);
Result := false;
end
else
begin
MsgBox('Not running', mbInformation, MB_OK);
Result := true;
end
end;
Ответы
Ответ 1
К сожалению, psvince.dll не может запросить 64-битные запущенные процессы на основе моего наблюдения, и поскольку я не являюсь его разработчиком, я не знаю, как исправить его для работы с Windows x64.
Мое обходное решение - использовать домашнюю утилиту командной строки, processviewer.exe,
http://github.com/lextm/processviewer
Это было протестировано в Windows 7 x64 в Touch Mouse Mate
http://www.lextm.com/2012/03/new-inno-setup-installer-script-samples-version-compare-running-processes/
Ответ 2
Вы можете использовать WMI и Win32_Process
.
Попробуйте добавить эту функцию в ваш скрипт Inno Setup.
function IsAppRunning(const FileName : string): Boolean;
var
FSWbemLocator: Variant;
FWMIService : Variant;
FWbemObjectSet: Variant;
begin
Result := false;
FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
FWbemObjectSet :=
FWMIService.ExecQuery(
Format('SELECT Name FROM Win32_Process Where Name="%s"', [FileName]));
Result := (FWbemObjectSet.Count > 0);
FWbemObjectSet := Unassigned;
FWMIService := Unassigned;
FSWbemLocator := Unassigned;
end;
Ответ 3
У меня недостаточно комментариев, чтобы добавить комментарий к превосходному ответу RRUZ, поэтому я просто добавлю это здесь.
Удостоверьтесь, что вы уловили исключения, иначе установщик не будет работать для пользователей, которые не могут получить доступ к службе.
try
FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
Result := (FWbemObjectSet.Count > 0);
except
end;
Ответ 4
Там есть еще более простое решение; использование кода, предложенного RRUZ, зависит от того, вы знаете путь установки, который, если вы запускаете, когда инициализирует установщик, вы этого не знаете.
Лучшее решение - использовать FindWindowByClassName. У этого есть небольшое предварительное условие, что у вас есть основная форма, которая всегда открывается, но вы всегда можете запускать несколько проверок, если у вас есть множество форм, которые могут быть открыты. Также само собой разумеется, что вам нужно сделать имя класса уникальным, насколько это возможно!
Пример функции:
function IsAppRunning(): Boolean;
begin
Result := (FindWindowByClassName( '{#AppWndClassName}') <> 0) or (FindWindowByClassName( '{#AltAppWndClassName}') <> 0);
end;
Ссылки на прекомпиляцию # определены ранее в установке script...
#define AppWndClassName "TMySplashScreen"
#define AltAppWndClassName "TMyMainForm"
Затем в разделе кода вы вызываете его следующим образом:
function InitializeUninstall(): Boolean;
begin
// check if application is running
if IsAppRunning() then
begin
MsgBox( 'An Instance of MyFantasticApp is already running. - Please close it and run the uninstall again.', mbError, MB_OK );
Result := false;
end
else
Result := true;
End;
Если вам нужно что-то более сложное, чем это, вам нужно взглянуть на мьютексы, но красота с приведенным выше кодом заключается в том, что он прост, быстр и до тех пор, пока у вас есть достаточно уникальные имена классов, как и все остальное.
(Хотя, по общему признанию, если вы работаете в многопользовательской системе, то это, вероятно, не найдет окно, если оно будет в другом сеансе пользователя. Но, как я уже сказал, для большинства простых ситуаций это было бы хорошо.)
Ответ 5
Простым решением может быть попытка удалить exe файл. Я предполагаю, что вы все равно замените или удалите его. Если файл существует и его удаление не удается, он, вероятно, работает.