Using Inno Setup to patch an Install Shield Application - windows

Hi I have a problem and I need some direction.
I have an old application that have an install shield installer, for which I don't have the installer scripts. Now I want to do a simple patch for that application using Inno Setup.
I was reading the documentation and if I knew the appId I could just append to the same installation the new files. However I don't now what Id that application have. I tried a simple script using the same name but it didn't work either.
Is it anyway of finding the appId to append to that installation?
Can someone point me in the right direction, or is not possible to do it?

The short answer is no, you cannot create an update package that is 100% seamless to the previous Install Shield package. The reason being, whether you know the AppId or not, InnoSetup appends a _is to the end of any AppId given for adding to the registry. Quite a funky action if you ask me but it's the way of the world and let's not forget you're dealing with a free application. They had their reasoning and it is sound, just doesn't make sense for your needs at this point.
You can always do what I did when faced with the same situation:
Find the AppId of the original installation.
a. Under the Control Panel open Add/Remove Programs.
b. Find your application in the list and make a note of the name.
c. Open RegEdit.
*DISCLAIMER: THIS COULD ADVERSELY AFFECT YOUR SYSTEM SO BE CAREFUL
d. Open the following registry key: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
e. Click on the first GUID you come to and check the value of DisplayName in the right pane against the name you took note of earlier. If this value matches you've found the AppId - it is the GUID you have selected.
f. Select the next GUID and go back to step 1e until you have a match.
Use this AppId as the AppId you use in InnoSetup but add the word "Update" to your title.
Build and run your installation.
Now you will have two entries in Add/Remove Programs for your application but one is clearly marked update. You've also done the additional leg work to ensure that the AppId is as much a match as possible making it easier for other programs to determine that they're related.
Best of luck in your endeavors!

Related

Proper Way of Handling GUID used by Windows NotificationIcons

The Microsoft Documentation reads:
Notification icons specified with a GUID are protected against spoofing by validating that only a single application registers them. This registration is performed the first time you call Shell_NotifyIcon(NIM_ADD, ...) and the full path name of the calling application is stored. If you later move your binary file to a different location, the system will not allow the icon to be added again. Please see Shell_NotifyIcon for more information.
Since the documentation on Shell_NotificyIcon is rather sparse on how to unregister the GUID again, the following question arises: How do I properly remove the NotificationIcon again when I uninstall the corresponding app again?
There is the brute force approach which is described here, which deletes all system icons and the process explorer.exe must be restarted again. However I'm wondering if there exists more punctual approach.
Another option would be to just create a new GUID, every time a user installs the application or moves it to a new location. Is this considered best practice?
10 year old answer from a Microsoft employee speaks of a possible workaround when changing the path and at the same time claims there is no way to unregister:
There is no way provided to unregister that. If your binaries are Authenticode signed then the registration can move with the application. See the Troubleshooting section in the NOTIFYICONDATA documentation.
Note The only exception to a moved file occurs when both the original and moved binary files are Authenticode-signed by the same company. In that case, settings are preserved through the move.
Both binaries would need to be present simultaneously when the icon is created for the path to be updated.
I personally never use a GUID, I just use the classic ID mode from Win95.

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.

Duplicate entries in Add/RemovePrograms control panel when using MsiSetExternalUI

I created a setup for my product targeting Windows XP and later, to be installed using windows installer (WI). The resulting .msi file has a product code, let's say PC1 (actually a guid), and an upgrade code UC1 (also a guid). After some time, I created a new setup for a newer version of my product. The new .msi file has a new product code PC2 and the same upgrade code UC1 (also called a major upgrade). My company wants to install the .msi file with our own installer. For that, we basically use MsiInstallProduct to install the .msi file, while the entire UI is in our own install program (and we use MsiSetExternalUI to ask WI to send us notifications). The problem that I am having is the following:
if the two builds of the product are installed on the same machine using "msiexec /i myapp.msi" then there will only be one entry in the "Add/Remove Programs" of "Programs and Features" control panel applet. or in other words, during the installation of the new build, the old one is uninstalled.
if the two builds are installed on the same machine programatically using MsiInstallProduct, there will be two different entries in control panel.
Once again, only if I try to install it programatically (using either MsiOpenPackage+MsiDoAction or MsiInstallProduct), the upgrade does not happen and I end up with two entries in the control panel. I also found that if I do not set an external UI callback using MsiSetExternalUI, before calling MsiInstallProduct or MsiDoAction, then the upgrading part of a new installation also works as expected, no duplicate entries in the CP.
The callback that I use for MsiSetExternalUI is basically the same as the one in this MSDN article:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa368786(v=vs.85).aspx
What can I do (or what I need to handle in my callback) to avoid having duplicate/multiple entries in control panel?
Thanks and best regards,
Levente
Re our comments above, I did a google search for CLIENTUILEVEL and the first several hits indicate to me that CLIENTUILEVEL having a null value is normal and that REMOVE=ALL is working. The comments indicate to go a little furthor down the log and find out why the uninstall (Remove existing products) is failing. If you could email me a complete log file ( chrpai#iswix.com ) I could look through it for you.
RemoveExistingProduct standard action
Link to article describing how to interpret Windows Installer log files (see comments)
RemoveExistingProducts running but not uninstalling Options
I ran into the same behavior with my ManagedMsiExec sample project: http://blogs.msdn.com/b/delay/archive/2012/01/09/make-things-as-simple-as-possible-but-not-simpler-managedmsiexec-sample-app-shows-how-to-use-the-windows-installer-api-from-managed-code.aspx
Changing the logging behavior of my app didn't help in my case. But after (independently) noticing the same "CLIENTUILEVEL= REMOVE=ALL" strangeness in the logs, I found a workaround which was to explicitly call MsiSetProperty and set CLIENTUILEVEL to 0 before calling MsiDoAction.
This appears to me to be a bug with Windows Installer itself (incorrectly setting CLIENTUILEVEL during RemoveExistingProducts), but perhaps there's something else going on I don't understand. At any rate, I've had success with this change and maybe others can, too. :)

visual studio 2010 setup project - removing registry

I have 2 msi files that I run silently one after the other from win forms application (master installer for that matter). Both of them configured to write to registry to same location,
for example:
HKLM\Software\MyProduct\MSI1
HKLM\Software\MyProduct\MSI2
Now, I run uninstall in reverse order and when uninstall done, MSI1 removed from registry, but MSI2 is stuck there... Is there anything can be done about that without custom action or coding?
This happens because your registry entries use the same component as another product installed on the machine. For example, you copied the setup project of an existing product and used the copy to create an MSI for a different product.
To avoid it, you need to make sure that each MSI uses unique component names and GUIDs. It's not easy in Visual Studio setup projects. You can try editing the project file. If it doesn't work, it's better to start from scratch with a new setup project.
Ok, I found problem in VS2010 (Big Thanks to Cosmin Pirvu) and just will go on and put here the 2 solution options I see so far. But first, the problem:
As I mentioned I have 2 entries:
HKLM\Software\MyProduct\MSI1
HKLM\Software\MyProduct\MSI2
But in code, they look the same because MSI1 and MSI2 being "place holders":
HKLM\Software\MyProduct[ProductName]
So, the name is identical and properties identical this is why we get same component id for both!
Two things (as far as i see) you can do:
Instead of [ProductName] enter actual product name (hard coded)
(What I did is) In registry entry property, in condition field, enter meaningless string (make it really meaningless, so it wont meat reasonable condition, i used guid with leading __).
Thanks for all answers

Run another installer in an Inno Setup installation

My company is developing an application that has a dependency on another of our applications. That second application already has an Inno Setup installer.
So I think I'd like to bundle the second application's installer within the Inno Setup installer for the first application. But I'm not sure how to go about that properly. Does anyone know the "right way" to do this?
I found this: Inno Setup Knowledge Base—HOWTO: Install .MSI files. I assume the technique could be used for a nested Inno Setup installer. But I have a couple of questions about the fine details:
How could I make it so if the first application is uninstalled, the second is also uninstalled?
Is that a sensible thing to do (automatically uninstall the second application), or should I leave it to the user to do that manually?
If the user tries to uninstall the second application while the first is uninstalled, should I somehow detect that and give a warning? How could I do that?
For the level of uninstaller functionality you are talking about, I suggest you get familiar with pascal scripting in Inno Setup (if you are not already). It offers incredible customisation, but has the caveat of making your projects a lot more complex.
To answer your third question first:
Yes, you should do this. In order to do it properly, you need to add this functionality to the uninstaller of the second application (i.e. the one your app is dependent on). See Uninstall event functions in the Inno Setup help. You need to check in that uninstaller if your app is installed (by checking if HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SecondAppName exists, for example) and in that case show an additional warning.
As for your second question:
If it is remotely possible that your customer wants to continue using the second app, even if he decides that he wants to uninstall the first one, you should offer him the choice. I would do this with a seperate wizard page in the uninstaller for your app, after your app is uninstalled.
And finally, your first question:
You need to determine the name (full path) of the other app's uninstaller exe. You can retrieve it from the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SecondAppName\UninstallString. For executing it from a script in the [CODE] section, see Exec in the Inno Setup help.

Resources