InnoSetup: Pascal script for cancelling setup when file/folder exists - installation

In my InnoSetup I use several file actions in the InstallRun section. If those are executed correctly without problems then a certain temp folder should have been deleted.
If something has gone wrong then the temp folder is still there. In that case I want the setup to be canceled with a messagebox displaying an error message of my choice.
As I have no experience (yet) with Pascal script I kindly ask you to provide me with an example script yo do this.
Thanks in advance!
Addition:
I'll now explain the reason I need this. The scenario is updating an existing version, which is a Windows Service application. Before updating those files I have to uninstall the services first. For this I use my own commandline that's in the installation package. The other new files will be temporary unpacked to a temp folder (subfolder of app folder). After the Windows services are uninstalled the new files are moved from the temp folder to the app folder. If something goes wrong here I want to cancel the setup and show an error message to the user. I can best tell if something has gone wrong by checking if the temp folder is still there.

Assuming that you mean the [Run] section, it is not possible to cancel the installation that late in the process.
Instead, you should look at using PrepareToInstall. In this, all you need to do is to stop and deregister the old service, either directly via API or by invoking a command on the old service EXE as you choose. (Don't forget to handle the case when the service doesn't exist yet, for new installs.)
After this [Files] will replace the files as normal and you can then [Run] or use code (via AfterInstall or CurStepChanged(ssPostInstall), depending on the time you want it to happen) to re-register and start the service.
No need to muck around with temporary folders -- which is good, because that would have caused problems for uninstall as well.

Related

Why am I able to rename a Windows Service executable while it is running?

I have a Windows Service written in a managed language (.NET Framework v4.0) that is currently running.
For some reason, I am able to rename the service main executable while the service is running.
I would suspect the file to be locked by Windows while the service is running, but this does not appear the case.
More interestingly, it's still present in the task manager after renaming.
I'm not complaining that this is possible, but I'm wondering why. Anyone have an explanation for this?
Taken from this answer on superuser,
and How can we overwrite EXE files while users are running them?,
executables that are not exclusively locked, can be renamed. The windows service manager obtains a file handle on the service executable, which it keeps open as long as the service runs, and is totally unaffected by a rename. It does not lock the directory entry itself. So the executable can be read by other processes, and the directory entry of the file can be renamed.
Implications:
After the rename, a different version of the file can be placed.
If you, or an automated update process, fail to place the new version, any service that points to that executable will fail to start next time (on restart/reboot)
If the new version has issues, like bugs or missing dependencies, the service may fail to start next time (on restart/reboot)
When you place the new version, but fail to restart the service immediately, then it will become active at any time in the future which is not something admins (and users) like in a production environment.
Recommendations:
Do not rely on this mechanism. Have your update process stop the service. Fail the update when your update process has insufficient permissions to do so. Then replace the executable and all dependencies, and restart the service.

Windows installer is too clever, tries to repair when tester deletes config file

Our application is deployed to the target machine with an msi file. All works nicely. Our tester has gone through his plan, and one of the tests requires deleting the application's configuration file. The application is designed to alert the user with a dialog on startup saying "missing config". However, what happens is that - somehow! - the software starts the installer again and retrieves the missing file from the msi! Which is nice, but not what we want. How do we disable that behaviour?
without going into much depth of the windows installer mechanics (if you interested in that there a plenty of articles about this), the shortcut of the software is probably advertised, which means the windows installer checks if everything is in its place before the software is started.
if you can edit the msi, make the shortcut non advertised.
if you can't, install it with DISABLEADVTSHORTCUTS
e.g. msiexec /i myMsi.msi DISABLEADVTSHORTCUTS=1
please note that this is only a quick (and dirty) workaround,
to fix this proper you need to understand the whole windows installer advertising (also called repair or self resiliency) mechanism.
but explaining all the causes and the mechanism of the repair is far beyond this answer and there are quite some articles and posts about that on the internet (and especially on MSDN and stackoverflow)
There is a more correct answer to this, and it is NOT DISABLEADVTSHORTCUTS. You set the component id to null in the MSI file to prevent repair of that individual file. See ComponentId comments here:
http://msdn.microsoft.com/en-us/library/aa368007(v=vs.85).aspx
Edit the MSI file with Orca to delete the Componenty ID, and write an uninstall custom action to delete the file at uninstall if it's there.
In addition, that's a redundant test. Windows will restore that file for you if it's missing, so the idea that you need a test to notify that it's missing is pointless. The true test should be that Windows will restore the file if it's lost, and your app needs to do potentially nothing about the missing file.
You don't mention what tool you are using to make your MSI but I'm going to go out on a limb and guess Visual Studio Deployment Projects (.VDRPOJ).
One of the (many) horrible things about this tool was that it fails to expose the foundational concept of components. Instead it makes every file a key file of it's own component and hides the existence of the component from you. I say 'was' because Microsoft killed this project type in VS. There are around 50k people complaining on UserVoice to bring this tool back and I'm guessing that 49,990 of them don't know what a key path is.
Windows Installer has a concept called the component rules and each component has a keypath. The keypath teaches MSI how to handle repair scenarios. But your tool has to allow you to be able to control this to make it work.
Windows Installer is functioning exactly the way it's supposed to function. You just aren't up to speed on what that is.
However, if you want to ignore Windows Installer best practices and continue using the tool you use today, the trick is to install the app.config file as a different file. Then have the application copy the file to the real file name on run. Windows Installer won't service what it didn't install.
Several answers have been provided that can work:
You can install the file with a blank guid. Then you need to remove it on uninstall using the RemoveFile feature. You will also run into issues if you want to replace it during an upgrade. Could be tricky at times.
You can disable the advertised shortcut(s), but this affects too much in my opinion.
Finally you can use my suggestion to install a separate non-advertised shortcut to use to launch the application. Such a shortcut bypasses the self-repair check. It may still be invoked by other means such as missing file associations, COM registration or similar, but those are exception states.
However, my preference is that an application can start without a config file present, if at all possible. I always suggest a good startup routine with "internal defaults" available. The startup routine should also degrade gracefully if faced with any file system access denied conditions.
Most importantly you should place this config file in the userprofile so you can generate the file on first launch for the user in question. It can even be copied from a read-only copy in the main installation directory.
When you generate a file from internal defaults and put it in a userprofile location, the file will have no interference with Windows Installer at all. The issues that results is how to clean up user data on uninstall. I discussed this with Stefan Kruger (MSI MVP) at one point, and I agree with his notion that user data is indeed user data and should not be automatically dealt with by your installer at all. Leave it installed, and clean it up via system administrator tools if necessary - for example logon scripts.

Inno Setup: restart in the middle of setup process

I've made a installer via Inno Setup and now I'm need to restart computer after some files were run.
So, i have code:
....
[Files]
....
[Run]
Filename: firstfile
RESTART
Filename: secondfile
....
Is this possible? I have found one example script github, but i cant understand how to use this DetectAndInstallPrerequisites functions.
If someone can advise or provide some simple example, I would be very gratefull
Have a look at the CodePrepareToInstall.iss example script included with Inno. It shows how to arrange for a reboot and have the installation automatically resume afterwards. (You may need to make further changes or save further values if your installation is more complex or prompts for further user input.)
The missing link in that example is that you need to fill in the DetectAndInstallPrerequisites function by using ExtractTemporaryFile to retrieve the appropriate files (as it runs before the main [Files] section is processed) and Exec(ExpandConstant('{tmp}\yourfile.exe'), ...) to actually run the file. If this is a subinstaller you can then check its exit code to determine if a reboot is actually required or not rather than unconditionally requesting a reboot.
Note that this code will be executed again following the reboot, so you also need some way to detect that the subinstall has succeeded and skip trying to run it again. Typically this is done by trying to detect the version of the installed subcomponent.

How to delete application file from AppData\Roaming folder

I am using windows installer to create setup project.
How I can remove/delete application files from AppData\Roaming folder when application uninstalled.
I tried added a special folder and set DefaultLocaltion to [AppDataFolder] but it didn't working.
Do I need to do anything else?
I'd need to understand what you are trying to do to give you specific advice. In general what you are trying to do would be OK removing files from CommonAppDataFolder but not AppDataFolder as trying to clanup user data from multiple user profiles is not a best practice. Additionally trying to cleanup Roaming Profile User data is outright impossible because the other users aren't logged on.
You'll want to read:
Managing Roaming User Data Deployment Guide
Assuming you are trying to do what I think you are, you'll need a cleanup script / exe that you leave behind on uninstall and a custom action to write to the registry during uninstall ( MSI can't do this natively ) to call that script/EXE. You'll want to leverage the Active Setup trick as described here:
Using Active Setup to Repair User Settings
The way it'll work is your uninstall leaves the EXE and registry entry behind so that when a user logs on it's roaming data gets pulled down from the server to local and Active Setup realizes it hasn't run the script yet. The script runs (once) and the data is deleted. When the user logs off the data is replicated / deleted on the server. Then they log on again it doesn't run again.
By default Windows Installer does not remove the files created by your application, after the installation. To do that you need to either write your own custom action, that will run upon uninstall, or depending on the tool used for authoring the MSI, you can use built-in options for cleaning the application locations, as some tools have this support.

Strategies For Replacing Program Executable in Windows

I have a Windows program that needs to update itself from a server automatically.
It is already able to transfer files from the server and update + validate things like DLL plugin files before loading them.
However, this program also needs to update itself. There are probably a few different ways this could be done, and the most obvious one I've seen from various online game clients is creating an "auto patcher" that downloads and then runs the client executable. That introduces the problem of having to update the autopatcher, so if there is a more elegant solution I'd like to hear about it.
I have to imagine there is a way to download what will be the new executable file as a temporary file, let's say "client.exe.tmp" and then launch a separate process that waits for the original client.exe to exit and then renames/copies the new file over the top of it.
Has anyone done this sort of thing before successfully and what method did you use to get it to work?
Running exe downloads the new one, puts it somewhere
Running exe renames itself to anything (like .exe.tmp)
Running exe puts the downloaded exe where the running one is (named just like the original)
Running exe starts the downloaded exe
Downloaded exe checks for .exe.tmp file, if found deletes it and kills the old running process
Done
I like the patcher/maintenance/feature add/remove tool approach. Even if for some reason you need to update something as trivial, I see no "chicken or egg paradox" here, it is more of a "one hand washes the other" thing.
Application checks server for updates, if any, check if patcher is up to date, if needed, application updates patcher
Patcher is executed as a separate process, downloads the update, and notifies application to prompts to install it
You agree, application quits notifying the patcher, patcher unpacks data, replaces exe, does additional stuff that may be needed by the new version and launches it and terminates
Consider ClickOnce deployment which will help you to insall/replace/update latest version from shared location and executed.

Resources