Inno Setup终止正在运行的进程

时间:2011-04-04 22:33:05

标签: install inno-setup kill

我已经实现了一种方法来查找进程(“iexplore.exe”)是否正在运行,我现在需要找到一种方法来关闭它(终止进程)来自Inno Setup。

strProg := 'iexplore.exe';
winHwnd := FindWindowByWindowName(strProg);
MsgBox('winHwnd: ' + inttostr(winHwnd),  mbInformation, MB_OK );
if winHwnd <> 0 then
  retVal:=postmessage(winHwnd,WM_CLOSE,0,0);

上例中的消息框将始终返回0,因此无法获取句柄。 (示例中的WM_CLOSE常量已正确初始化) 我需要另一种方法来做到这一点,并且希望不涉及编写执行此操作的C ++ DLL(我不熟练使用C ++,我可能能够在C#中编写DLL,但是我不知道是否Inno Setup将与那个人互动。

这个C#DLL将获取进程列表,通过进程名称进行迭代,找到匹配项(==“iexplorer”)然后使用该名称终止进程...但是我仍然希望找到一个更简单的解决方案所以我不得不用Pascal脚本来互操作。

提前致谢!

4 个答案:

答案 0 :(得分:4)

使用Win32_Process的版本,您使用ie&#39; notepad.exe调用该程序&#39;:

const wbemFlagForwardOnly = $00000020;

procedure CloseApp(AppName: String);
var
  WbemLocator : Variant;
  WMIService   : Variant;
  WbemObjectSet: Variant;
  WbemObject   : Variant;
begin;
  WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  WMIService := WbemLocator.ConnectServer('localhost', 'root\CIMV2');
  WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Win32_Process Where Name="' + AppName + '"');
  if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
  begin
    WbemObject := WbemObjectSet.ItemIndex(0);
    if not VarIsNull(WbemObject) then
    begin
      WbemObject.Terminate();
      WbemObject := Unassigned;
    end;
  end;
end;

答案 1 :(得分:2)

您的代码会做出一些错误的假设,您应该全部解决这些问题:

  • 关闭任何程序而不先询问用户是个坏主意。考虑到Internet Explorer的情况,用户可能会打开一些网页,其中部分填写表格 - 如果您无条件地关闭它们,您可能会因为失去工作而积极地惹恼用户。
    您应该做什么:检查是否有任何程序打开会干扰您正常的安装进度,如果发现有任何程序提醒用户需要关闭它。问他们是否取消或重复检查,除非所有干扰程序都关闭,否则不要继续。

  • 如果您确实需要向窗口发送WM_CLOSE消息,则支持功能FindWindowByWindowName()将无效。为什么Internet Explorer窗口的窗口名称是“iexplore.exe”?它将是开放网页的标题,因此您不会事先知道它是什么 您应该做什么:使用更合适的FindWindowByClassName()功能。使用Spy ++或UI Spy等工具,您可以找到程序窗口的类名。对于我系统上的Internet Explorer,它是“IEFrame”,但你真的可以依赖它吗?再次,更好地让用户控制事物,并重复运行过程检查,直到所有干扰程序都已关闭。

  • 使用匹配的窗口或类名关闭单个窗口可能不够。单个Windows进程可能打开多个窗口,并且可能有多个同一个可执行文件的实例正在运行,每个实例都打开一个或多个窗口。
    你应该做什么:在循环中执行你的检查(和关闭)代码,直到一切都准备好继续。

  • 但即便如此,你应该为出错的事做好准备 - Windows是一个多任务系统,可能会产生新的进程或随时打开窗口。如果启用了自动播放,那么当您认为已关闭它们时,插入CD或USB记忆棒可能会打开Internet Explorer窗口。

答案 2 :(得分:1)

我遇到了这个问题,并编写了一个简短的C ++程序来杀死可能处于挂起状态的某些进程,从而无法响应告诉他们死亡的消息。我只使用属于我的产品的应用程序,而不是系统应用程序。

如果您想要使调用参数正确的痛苦,您可以在Pascal脚本中执行相同的操作。以下是我所做的概述:

获取CSIDL_PROGRAM_FILES的位置。 Inno setup可以使用{pf}或{pf32}常量来完成此操作。或者调用Windows api SHGetSpecialFolderLocation函数。

例如,

设置一个字符串,该字符串等于要杀死的进程的路径 String target = pf +“Mycompany / MyAppFolder / myHelperApp.exe”

调用Windows api函数CreateToolhelp32Snapshot,它返回正在运行的进程列表。

使用Windows api的OpenProcess和GetModuleFleNameEx查看目标的返回列表。

当你发现目标调用目标进程句柄上的Windows api TerminateProcess时。

答案 3 :(得分:1)

const 
  WM_QUIT = 18;

function InitializeUninstall(): Boolean;
var
  winHwnd: longint;
  retVal : boolean;
  strProg: string;
begin
  Result := true;
  strProg := 'Readme.txt - Notepad';
  winHwnd := FindWindowByWindowName(strProg);
  MsgBox('winHwnd: ' + inttostr(winHwnd),  mbInformation, MB_OK );
  if winHwnd<>0 then begin                    { no module found or ignored pressed}
    MsgBox('ravi:' #13#13 'Bye bye!', mbInformation, MB_OK); 
    abort();                                      { continue setup  }
  end;
end;

工作正常..

使用该代码,我能够跟踪正在运行的退出应用程序......