Inno Setup: shared files are not being deleted from my install directory - inno-setup

I have created an installer using Inno 5.5.9 and am installing a number of binary files that need to be marked as shared because a second installer could install a second program to the same directory and these files are common across the two programs.
I am marking the files with the flags 'sharedfile uninsnosharedfileprompt' but they are not removed on uninstall even if they are not in use.
In my testing I install the main program and then uninstall it immediately. The uninstall log says it is 'decrementing shared count' for these files but the shared count is not reaching zero. This is a 32bit program installed onto Windows 10.
#define SourceDirectory "..\bin2017\win32"
#define InstallPath "{app}\bin\Win32\"
[Files]
Source: "{#SourceDirectory}\*.dll"; DestDir: "{#InstallPath}"; Flags: ignoreversion sharedfile uninsnosharedfileprompt
What am I missing to make this work correctly? What could be preventing the uninstaller from decrementing the shared count to zero?
If you need any more info or code please let me know (this is my first question on the excellent site).
Thanks in advance.

The path in the original location has most likely some orphan reference.
I believe your code is correct and the installer behaves correctly. It's just a local problem with reference counting.

Related

Overwrite installed files with files in setup subfolder in Inno Setup

I recently have found some old PC games to play on my Windows 10 64-bit computer. I have looked at various online sources to get the games working. Now I'm interested in creating a custom installer for all the various steps taken to get the games to work properly. I succeeded getting C&C Generals to work with a custom installer via Inno Setup. I however lack the expertise after a bit of research and trial to do the following:
I am able to install the software and use the official patch to update the installed software.
I am unsure how to add a script to copy modified files from the install subfolder to overwrite the installed files in the main folder after the update. The update does not work on the modified files.
Example:
Program installs to C:\Program Files (x86)\Programv1.exe.
Setup source files include a subfolder \modfiles.
Would like to overwrite Programv1.exe post patch update with \modfiles\Programv2.exe
Does this go under the [Code] section?
Can it go under the [Run] section with a postinstall flag? Like a simple copy and overwrite command as the last step?
Thanks!
There many ways to achieve this.
You can execute the patch using the AfterInstall parameter, even before the "mod" is installed. See Inno Setup: Install other installer and run it before continuing my install. Then you can install the mod straight to the installation folder (not to the subfolder):
[Files]
; Install original game
Source: C:\source\TheGame\*; Dest: {app}
; Run patch
Source: C:\patch\PatchTheGame.exe; Dest: {tmp}; AfterInstall: RunPatch
; Install mod
Source: C:\mod\Program.exe; Dest: {app}
Use Run entry to copy the mod after you install the patch:
[Files]
; Install original game
Source: C:\source\TheGame\*; Dest: {app}
; Extract the patch somewhere
Source: C:\patch\PatchTheGame.exe; Dest: {tmp}
; Extract the mod somewhere
Source: C:\mod\Program.exe; Dest: {tmp}
[Run]
Filename: {tmp}\PatchTheGame.exe
Filename: {cmd}; Parameters: /C copy ""{tmp}\Program.exe"" ""{app}\Program.exe""
You can code it in Pascal Script. See Install customized version of configuration file in Inno Setup after (Firebird) subinstaller finishes

Inno Setup Compiler "Cannot find the path specified" error with long paths

I am using a .iss script to build an exe file inside Inno Setup Compiler. I need to package some node_modules into this application so I have a line under [Files] which looks like this:
Source: "{#SourcePath}Encore.Warehouse.UI\bin\Warehouse_Release\warehouse\*"; \
DestDir: "{app}\warehouse"; Flags: ignoreversion recursesubdirs createallsubdirs
When I compile, I receive this error:
Here is the compiler output:
So, it appears to be running fine up until it aborted. My initial thought was that the browser.js doesn't exist but after double checking, this is not the case. Also, I'm using a wildcard in the source path so the compiler knows the file exists, but it seems to be having trouble compressing it.
One other thing that could be causing the issue is the file path length. Node modules usually end up having ridiculous file path lengths due to nested dependencies. In this case, the path length is 260. Assuming this is what's causing the problem, is there any way to get around it?
It's definitely due to a long path. Normally Windows applications cannot process paths longer than MAX_PATH (260 characters).
See Naming Files, Paths, and Namespaces in Microsoft documentation.
A common workaround is prefixing the path with \\?\ (again see the Microsoft article above). The prefix can be used for absolute paths only. But Inno Setup compiler chokes on that with the Source attribute. It looks for : and it accepts only path that either have a drive letter only before the : or that use compiler: or userdocs: prefixes.
You can hack that by using an UNC path with a volume ID (hence no colon).
Use the mountvol command to find the UNC path for your source drive.
And then you will have the same problem with a long path with the DestDir attribute, while installing (not when compiling). There, there's no problem with the colon, so you can simply use the \\?\ prefix.
Source: "\\?\Volume{bb919c3e-bdb1-42b8-9601-6715becd8683}\{#SourcePath}Encore.Warehouse.UI\bin\Warehouse_Release\warehouse\*"; \
DestDir: "\\?\{app}\warehouse"; Flags: ignoreversion recursesubdirs createallsubdirs
Of course, if the problem is caused by a root path being too long already, you can fix the problem simply be moving the source files to a folder with a shorter path. Or you can use subst to create a virtual drive or you can create a symlink/directory junction.
Falling into the same issue, here below is more details on workaround with subst as described in comments and accepted answer.
Here below is content of some precompile.bat file to associate some local path with the A: drive letter
#echo off
REM NB: Removing any previous association to be sure new one will work
subst A: /D 1> NUL 2>&1
subst A: "%~dp0.."
And content of some postcompile.bat to remove association in the end
#echo off
subst A: /D 1> NUL 2>&1
NB1: Careful, once associated, it is difficult to navigate upper paths directly within the .iss script because A:\.. is still A:\ ! (I fall into the issue, so worth to know). Association should then be made with closest top-most folder of all required files directly in precompile.bat.
NB2: I don't know if feasible to remind for any previous association and restore it in the end
These steps can be added to the .iss script as follow:
[PreCompile]
Name: "precompile.bat"; Flags: cmdprompt redirectoutput
[PostCompile]
Name: "postcompile.bat"; Flags: cmdprompt redirectoutput
Note finally that [PreCompile] and [PostCompile] sections will execute from the IDE only. They won't execute from the command line (at least with inno 5.5.9), I also fall into this... so complete compilation from command line should look like:
call "precompile.bat"
call "%ProgramFiles(x86)%\Inno Setup 5\ISCC.exe" "myscript.iss"
call "postcompile.bat"
NB: I think calling Compil32.exe /cc "myscript.iss" (IDE compiler) instead of ISCC.exe (command-line compiler) should run [PreCompile] and [PostCompile] sections but in my case I had to pass extra /D options to the compiler so it was not possible to call Compil32.exe directly.

Upgrading existing application with Inno Setup

I've created a setup file for my application, which works fine for new installations, but I now need to adapt it to handle upgrades.
I understand I should add DisableDirPage=auto under [Setup], so the user won't be prompted for an installation folder during upgrades?
I also do a few things in [Run]. How do I skip these actions when it's an upgrade?
Under [Files] I currently use a single line to install everything to the application folder:-
Source: "{#BuildOutputFolder}\*"; DestDir: "{app}"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
Firstly, I'm guessing this won't work during an upgrade as "onlyifdoesntexist" would prevent the EXE and DLLs from ever being overwritten, even with newer versions?
Secondly, there are certain files (e.g. configs) that get installed, but should never be overwritten during an upgrade. I'm guessing the current line isn't sufficient and I would need to replace it with a number of separate lines to achieve this functionality, e.g. one to install the EXE, one for the DLLs, and one for the configs (with "onlyifdoesntexist")?

InnoSetup - Erroneous "File in use by another process..." message while compiling

Although I really like InnoSetup, I have been suffering with this erroneous message for some time, but my frustration has reached new heights. There are numerous posts complaining about this problem, which is most certainly an InnoSetup bug, but no useful work-arounds that I can find.
I have a very simple (signed) setup that merely copies some files and creates a shortcut. It does not even include an executable. When I try to compile the setup, I am getting this "the process cannot access the file because it is being used by another process" message - repeatedly (normally I always get the setup to compile within 3 tries), but now it seems futile after many. many tries. The file that is "in-use" is not clear from the InnoSetup output or error dialog. There are most definitely no competing processes running. (I have rebooted the machine and still get this message).
Any ideas on how to resolve this are much appreciated.
Here is the complete setup code - it is signed, but that is not a problem with other setups I have created with the same signature.
#define MyAppName "Easy-IAP for IronKey"
#define MyAppVersion "4.0"
#define MyAppPublisher "Command Post Solutions"
#define MyAppURL "http://www.commandpostsolutions.com/"
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{51668D56-27F6-4C83-87F2-677328EFE808}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName="\EZ-IAP"
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputBaseFilename=IronKeySetup
SetupIconFile=C:\Users\ron\Dropbox\EZIAP\eziap.ico
Compression=lzma
SolidCompression=yes
SignedUninstaller=yes
SignTool=Standard /d $qEasy-IAP Installer$q $f
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "C:\Users\ron\Dropbox\Easy-IAP for IronKey\AccessDatabaseEngine.exe"; DestDir: "{app}"; Flags: onlyifdoesntexist
Source: "C:\Users\ron\Dropbox\Easy-IAP for IronKey\dotNetFx40_Full_x86_x64.exe"; DestDir: "{app}"; Flags: onlyifdoesntexist
Source: "C:\Users\ron\Dropbox\Easy-IAP for IronKey\Easy-IAP for IronKey\bin\Release\Easy-IAP for IronKey.exe"; DestDir: "{app}";
; NOTE: Don't use "Flags: ignoreversion" on any shared system les
[ICONS]
Name: "{drive:{app}}\Easy-IAP"; Filename: "{app}\Easy-IAP for IronKey.exe";
I had the same problem.
It was due to McAfee antivirus running the realtime scanning on the exe file being compiled...
As it doesn't seem possible to exclude a directory from realtime scanning, I shut it down in McAfee SecurityCenter, and now it's good.
Hope this help
The problem is often an explorer window being open viewing the folder where the output files will reside.
Explorer continually opens the executable as it is built trying to fetch its icon and other metadata. Close any open explorer windows which are viewing the output folder and try again.
For this reason you are best running your inno setup file from the command line or part of a visual studio or other automated build process.
This is not a bug, this is only bad design of application (or bad documentation) :)
Use the OutputDir directive in your [Setup] section to avoid this wrong behaviour.
OutputDir=c:\output
OutputDir specifies the "output" directory for the script, which is where the Setup Compiler will place the resulting SETUP.* files. By default, it creates a directory named Output under the directory containing the script for this.
You ask why?
If you do not use OutputDir in your script file (and many people do not use it) Inno Setup tries to create resulting setup in the "userdocs:" folder which causes a lot of troubles on all Windows systems.
Always use this parameter, even if you want to have resulting setup in current folder, in that case use:
OutputDir=output
I have OutputDir = x:]setup but the error still occurs. If I reboot my machine and then build as the 1st task then the build works.
Win 7 Pro/64, InnoSetup 5.5.5(a): I had axactly the same InnoSetup compilling problems. After changing folders properties used in projects and output by revoking sharing them all works fine. Conclusion - it is better not to use InnoSetup within shared folders.
I had this when OutputDir="." (meaning, put the output in the same directory as the source files). It would fail every second build.
I fixed it by adding modifying my powershell build script to delete that entire output directory, then build my app (which auto-created that directory), then run iscc to create the setup.exe
The error could be caused because you are trying to copy a folder that is linked with a Windows Service.
To solve this problem, use a [Code] section instead of putting the folder in [Files]. That allows you to check if the folder exist, close the associated windows service and finally copy the folder.
I had the same problem with that the solution is already stated above
and the other reason with this error comes up when the output file of the .exe you compiling has already have the same name in the directory where you put the output directory from inno setup.
In order words when compiling you need some special character like '-' or '_' in creating the file name and to avoid this error message.
I tried various folders on my work machine and nothing resolved the issue. I finally had success by using:
OutputDir=C:\Users\userid\Downloads
(Replace "userid" with your particular account)
I tried all advices from above. I could not make it.
Then I switched back from version 6.2 to 6.0.2 and it fixed the problem.

Uninstalling files not originally installed by INNO setup

I use Inno Setup for my product's installer/uninstaller. My software has auto-update capabilities during which time it may not only change existing binaries but may also add new ones. These are additional product files that are placed into the product's installation directory - not data files.
The Inno Setup uninstaller only knows to uninstall files by name that it originally put there at install time. Since an automatic update doesn't change either the unins000.exe or unins000.dat files that make up the uninstaller, what would be the appropriate way to delete these new product files at uninstall time?
The easiest way I see is to have a batch file in your program dir that deletes all files that were added after the installation and is executed on uninstall:
[UninstallRun]
Filename: cleanup.cmd; WorkingDir: {app}; Flags: shellexec runminimized
UninstallRun commands are executed as the first step of the uninstallation, so this should work fine. If you are bothered by the idea of running a batch script, you can easily create your own cleanup.exe that deletes the files.
When you perform the auto update, you must also update the cleanup file, so that it includes all files that were added with the current update.

Resources