Inno Setup: How to close a program before reinstalling it

As a software developer, I love Inno Setup!  It is a wonderful, powerful, free software-deployment tool.  I’ve tweaked my programs’ Inno Setup scripts to accomplish certain important, but tricky tasks.

Most recently, I looked for a way to check if a program is running (and to close that program) when we’re about to install a new version.  I found an existing script which checks to see if a program is running and exits the installation if it is (after first displaying an error message in a message box.)  It was very helpful in presenting the basic concept.  However, I wanted the script to give the user the opportunity of closing the target program and continuing with the installation, rather than aborting the whole process.  The resulting, expanded script accomplishes this.  It includes documentation and groups basic customization options close together, so you can easily adapt the script for your own installers.

To test the script’s resulting installer, open up a Notepad window and leave it open before running the installer (or uninstaller.)

You’ll need the following resources to compile this script:

  • Inno Setup
  • PSVince (the DLL with the function to determine if a given application is running)
  • the script (a.k.a. “Prompt to Close the Program”, which you can download or copy-and-paste from the text below)

You can also download a compiled, executable version to see it in action before deciding whether to adapt it for your own needs.

— Andrés Cabezas

Script Source Code

;——————————————————————————-

; This sample script was created by Andres Cabezas ( http://wwww.domador.net )

; It is based on another sample script, created by Vincenzo Giordano, found at
; http://www.vincenzo.net/isxkb/index.php?title=Call_psvince.dll_on_install_and_uninstall

; To clarify your freedom to use this code, I’ve appended a license at the end,
; an even-more-permissive version of the already-permissive Expat license.

;——————————————————————————-

; Sample application-name settings

[Setup] AppName=Prompt to Close the Program
AppVersion=1.0
DisableProgramGroupPage=true
DisableStartupPrompt=true
DefaultDirName={pf}\Prompt to Close the Program
DefaultGroupName=”Prompt to Close the Program”

OutputBaseFilename=PromptToCloseTheProgramSetup

;——————————————————————————-

[Files] ; DLL used to check if the target program is running at install time
Source: psvince.dll; flags: dontcopy
; psvince is installed in {app} folder, so it will be loaded at
; uninstall time to check if the target program is running
Source: psvince.dll; DestDir: {app}

; Comment out the following two lines if you don’t want a Start Menu program group
; to be created. (You’ll need to run the uninstaller’s EXE directly from its
; folder (e.g. “C:\Program Files\Prompt to Close the Program”) if you do.)

[Icons] Name: “{group}\Uninstall this application”; Filename: “{uninstallexe}”

;——————————————————————————-

[Code]

////////// Customize the following constants to suit your own program //////////

const

// Name of the application that should be closed and name of its executable

ProgramName = ‘Notepad’;
ProgramExeName = ‘notepad.exe’;

// Messages user will see if the application is running.
// (It may be a good idea to give instructions on HOW to close your application,
// if it’s not obvious to the user (e.g., in the case of background applications)

ProgramRunningOnInstallMessage = ProgramName + ‘ is currently running. ‘ + #13 + #13 +
‘Please close it and then click on ”Retry” to proceed with the installation.’;
InstallationCanceledMessage = ‘The installation was canceled.’;

ProgramRunningOnUninstallMessage = ProgramName + ‘ is currently running. ‘ + #13 + #13 +
‘Please close it and then click on ”Retry” to proceed.’;
UninstallationCanceledMessage = ‘The uninstallation process was canceled.’;

////////////////////// end of basic-customization section //////////////////////

//——————————————————————————

// IsModuleLoadedI – function to call at install time
// Also added setuponly flag
function IsModuleLoadedI(modulename: String ): Boolean;
external ‘IsModuleLoaded@files:psvince.dll stdcall setuponly’;

// IsModuleLoadedU – function to call at uninstall time
// Also added uninstallonly flag
function IsModuleLoadedU(modulename: String ): Boolean;
external ‘IsModuleLoaded@{app}\psvince.dll stdcall uninstallonly’ ;

//——————————————————————————

// Calls IsModuleLoadedI or IsModuleLoadedU as appropriate

function IsModuleLoaded( modulename: String; isUninstallation: Boolean ): Boolean;
begin
if isUninstallation then
Result := IsModuleLoadedU( modulename )
else
Result := IsModuleLoadedI( modulename );
end;

//——————————————————————————

// Prompt the user to close a program that’s still running.
// Finish when the executable is closed or the user cancels the process.

// -> message : A message to show the user to prompt them to close
// -> isUninstallation : Whether this is an uninstallation (to call the right function.)
// <- True if the program was closed (or was not running),
// False if the user clicked on the Cancel button and didn’t close the program

function PromptUntilProgramClosedOrInstallationCanceled(
message: String;
isUninstallation: Boolean ): Boolean;
var
ButtonPressed : Integer;
begin
ButtonPressed := IDRETRY;

// Check if the program is running or if the user has pressed the cancel button
while IsModuleLoaded( ProgramExeName, isUninstallation ) and ( ButtonPressed <> IDCANCEL ) do
begin
ButtonPressed := MsgBox( message , mbError, MB_RETRYCANCEL );
end;

// Has the program been closed?
Result := Not IsModuleLoaded( ProgramExeName, isUninstallation );
end;

//——————————————————————————

function InitializeSetup(): Boolean;
begin
Result := PromptUntilProgramClosedOrInstallationCanceled( ProgramRunningOnInstallMessage, False );

if Not Result then
begin
MsgBox( InstallationCanceledMessage, mbInformation, MB_OK );
end;
end;

//——————————————————————————

function InitializeUninstall(): Boolean;
begin
Result := PromptUntilProgramClosedOrInstallationCanceled( ProgramRunningOnUninstallMessage, True );

// Unload the DLL, otherwise the dll psvince is not deleted
UnloadDLL(ExpandConstant(‘{app}\psvince.dll’));

if not Result then
begin
MsgBox( UninstallationCanceledMessage, mbInformation, MB_OK );
end;
end;

//——————————————————————————

// Copyright (C) 2011 by Andres Cabezas Ulate ( andres.cabezas@domador.net )

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the “Software”), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//——————————————————————————

Copyright © 2020 Domador Software S.R.L.