卸载失败,因为程序正在运行。如何在尝试删除之前让 Inno Setup 检查正在运行的进程?

Posted

技术标签:

【中文标题】卸载失败,因为程序正在运行。如何在尝试删除之前让 Inno Setup 检查正在运行的进程?【英文标题】:Uninstall fails because program is running. How do I make Inno Setup check for running process prior to attempting delete? 【发布时间】:2010-12-07 07:14:07 【问题描述】:

Inno Setup 在卸载过程中无法删除组件,因为我的程序仍在运行并且无法删除可执行文件。在允许卸载继续之前,我如何让它检查它是否正在运行?

【问题讨论】:

【参考方案1】:

我们使用了上述以外的其他方式。因为这是一个卸载,我们可以杀死应用程序并卸载它。 最简单的方法,当你不能使用AppMutex时:(与Really killing a process in Windows相关)

[UninstallRun]
Filename: "cmd"; Parameters: "/C ""taskkill /im <precessname>.exe /f /t"

希望有人能帮忙。这个我找了很久。

【讨论】:

taskkill 是否会杀死同一进程的多个正在运行的实例? 用notepad.exe试了一下,效果很好。它会在没有反馈的情况下终止应用程序。 谢谢!是的,除非您以低于提升进程的权限运行设置,否则它会杀死所有实例。 [无论如何+1 :)] 似乎要终止进程,但卸载程序仍将文件视为已锁定并不会删除它们。 最佳解决方案 imo.【参考方案2】:

检查这些

Inno Setup: Detect instances running in any user session with AppMutex

Inno Setup: Is application running?

Inno Setup: Detect if an application is running

有几种方法。如果你的程序定义了一个互斥体使用

[Setup]
AppMutex=MyMutexName

Code 部分中的指定互斥锁

function CheckForMutexes (Mutexes: String): Boolean;

你也可以使用

function FindWindowByClassName (const ClassName: String): Longint; 

通过类名获取窗口句柄并向其发送消息。

或者通过名字来获取它

function FindWindowByWindowName (const WindowName: String): Longint;

或者您为这个特定用例使用几个 DLL 文件之一

PSVince FindProcDLL

或者阅读后自己做

How To Terminate an Application "Cleanly" in Win32

How To Enumerate Applications Using Win32 APIs(这个链接到德文版因为某种原因我找不到英文版的KB175030

或尝试 KB175030-DE 的谷歌翻译版本

KB175030 DE -> EN

【讨论】:

很棒的答案。非常彻底;谢谢!全局互斥锁选项花了 5 分钟才搞定!没有比这更好的了。 您对可以在另一台计算机的内存上打开的基于网络的文件有答案吗? 我可以在 Wayback Machine 上找到的最新英文版 KB 175030 是 2007 年 2 月:web.archive.org/web/20070216103757/http://support.microsoft.com/…。 在这个答案中检查正在运行的应用程序的更多选项:***.com/a/30852146/550712。【参考方案3】:

试试这个解决方案!我在关闭应用程序时遇到了其他解决方案的问题,但 Inno Setup 仍然认为已安装的文件已被锁定。

记得定义你的常量:

#define MyAppName "AppName"
#define MyAppExeName "AppName.exe"

[Code]
function InitializeUninstall(): Boolean;
  var ErrorCode: Integer;
begin
  ShellExec('open','taskkill.exe','/f /im #MyAppExeName','',SW_HIDE,ewNoWait,ErrorCode);
  ShellExec('open','tskill.exe',' #MyAppName','',SW_HIDE,ewNoWait,ErrorCode);
  result := True;
end;

original source of this solution 的主要支持。

【讨论】:

这很好,我改变的一件事是使用不同的过程而不是“function InitializeUninstall(): Boolean;”由于即使用户取消卸载过程,此功能也会终止应用程序,而“procedure InitializeUninstallProgressForm;”只有当他确认卸载时才会运行。【参考方案4】:

当应用程序运行时,使用AppMutex directive 阻止卸载程序继续进行。

[Setup]
AppMutex=MyProgMutex

应用程序必须创建指令指定的互斥锁。有关示例,请参阅链接的 AppMutex 指令文档。


如果您想让卸载程序杀死应用程序,当它仍在运行时,请改用以下代码:

function InitializeUninstall(): Boolean;
var
  ErrorCode: Integer;
begin
  if CheckForMutexes('MyProgMutex') and
     (MsgBox('Application is running, do you want to close it?',
             mbConfirmation, MB_OKCANCEL) = IDOK) then
  begin
    Exec('taskkill.exe', '/f /im MyProg.exe', '', SW_HIDE, 
         ewWaitUntilTerminated, ErrorCode);
  end;

  Result := True;
end;

与上面的AppMutex 指令一样,应用程序必须创建CheckForMutexes 调用中指定的互斥锁。


请注意,对于安装程序,您不必对此进行编码。安装程序内置了重启管理器。 见Kill process before (re)install using "taskkill /f /im" in Inno Setup。

【讨论】:

以上是关于卸载失败,因为程序正在运行。如何在尝试删除之前让 Inno Setup 检查正在运行的进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何卸载已加载的程序集

Android Studio:应用程序安装失败

如何卸载.vsix Visual Studio Extensions?

AppDomain.DoCallback()在啥情况下会失败?

文件夹已在另一程序中打开,无法卸载怎么办

安装UBUNTU时无法卸载/CDROM 挂载点