2011-04-04 235 views
3

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

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脚本进行交互。

在此先感谢!

+0

刚刚发现这一点:HTTP://support.microsoft.com/default.aspx SCID = KB; EN-US; q178893 – 2011-06-01 18:55:58

回答

2

你的代码做了几个假设是错误的,你应该解决这些所有:

  • 这是一个坏主意,关闭所有程序,而不要求用户第一。考虑一下Internet Explorer的情况,用户可能会打开一些网页,部分填写表格 - 如果您无条件关闭它们,您可能会因为失去工作而主动剥离用户。
    您应该做些什么改为:检查是否有任何程序已打开,干扰您的安装的正常进度,并且如果发现有人提醒用户他们需要关闭它。循环询问他们是否取消或重复检查,除非所有干扰程序关闭,否则不要继续。

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

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

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

+0

点1)好点,我所知道的?这和我的第一个解决方案s使用inno setup插件,提示用户在继续之前关闭程序 - 管理层拒绝此解决方案,因为他们希望尽量减少对用户的干扰。我们的用户几乎无法找到Windows开始按钮的位置,更不用说读取提示并做出正确的选择。你在我们的案例中提到的循环会导致愤怒的电话,电脑被冻结,虽然它对我们来说是最合乎逻辑的解决方案,他们是精通技术的... – BrunoBozic 2011-04-07 07:38:21

+0

点2)是的,所有这些方法都不可靠,这就是为什么我是考虑杀死一个进程,而不是一个窗口,但我不知道如何通过Inno实现这一点(杀死进程),现在我会尝试使用FindWindowByClassName,现在我意识到WindowName的错误 – BrunoBozic 2011-04-07 07:39:54

+0

点3)再次我的首选解决方案是杀名为iexplore.exe的进程 – BrunoBozic 2011-04-07 07:40:31

1

我有这个问题,并写了一个短的C++程序来中止特定进程可能处于挂起状态,从而无法给告诉他们死亡的消息作出回应。我只对作为我产品的一部分的应用程序而不是系统应用程序执行此操作。

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

获取CSIDL_PROGRAM_FILES的位置。 Inno安装程序可以使用{pf}或{pf32}常量来实现。或者调用Windows API a SHGetSpecialFolderLocation函数。

设置一个字符串等于路径要终止的进程,例如 目标字符串= PF +“MyCompany的/ MyAppFolder/myHelperApp.exe”

调用Windows API函数CreateToolHelp32Snapshot函数,它返回一个正在运行的进程列表。

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

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

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; 

它工作正常..

使用的代码,我能够跟踪其运行出境申请...

4

版本与使用Win32_Process,与您通话即程序'的notepad.exe':

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;