How does the savedState Dictionary work in the Installer? - installation

I'm struggling to find documentation on how the stateSaver/savedState Dictionary works for the Windows Installer, in the Install and UnInstall overrides, can someone help.
In my installers CustomAction I've been writing to registry entries, each time I do I add some of it's detail to the stateSaver.
I had presumed this was taken into account when uninstalling but how?
I think the stateSaver Dictionary is written to file when you install, and on uninstall the content of that file, .InstallState is read and used to install the entries it finds.
My issue is some registry entries remain after uninstall, I don't know why and my lack of understanding of how the Dictionary works is not helping.
Here's an example of what the Install is doing
RegistryKey expressionEvaluatorVersionKey = expressionEvaluatorKey.CreateSubKey(packageVersion);
This is creating a Sub Key for a key added with the Windows Installer.
How should I delete this Sub Key in the uninstall?

I'm not sure installState is your issue. This is just a file containing various key-value pairs, I don't think there's anything intelligent going on in there.
This sounds to me like the (built-in) Uninstaller process could be saying "I need to delete this key but it isn't empty, therefore I'm going to leave it".
Could you possibly put all registry key/entry creation (and by implication all key/entry removal) into the Custom Action dll?
Another problem I have found with installState - and this is why I try to avoid it - is that it is not unknown for people to come along and delete the installState file. Depending on how you've written your Uninstall custom action, this might mean you never get a clean uninstall of your program because you'll get exceptions when you try to read stuff that you expect to be in the dictionary which is missing.
Since you appear to be using a custom action dll already to do this work hopefully my suggestion is not so onerous?

Related

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.

VS2010 Deployment Project: Issues with multi-user-install and registry entry

I have issues setting up my deployment project in Visual Studio 2010. Im using Windows 7 x64. Here's my problem:
The setup is supposed to install my program for all users. During the setup three registry keys are written to the HKEY_LOCAL_MACHINE/Software/Something folder, containing the setup variables for Serial, Name and Organization as values - [COMPANYNAME], [PIDKEY], [USERNAME].
What happens:
User1 (Admin) installs the software, entering his username, serial and company. Everything works. The keys can be found and values read by the program, using Registry.LocalMachine.OpenSubKey(path). The first thing I don't get is that I cannot find the registry entries, using the regedit.exe. Anyway, the code above finds them.
Now, User2 (Non-admin) tries to execute the freshly installed program. The installer is launched again, saying "Wait for ... to configure ...". The user specific folders for User2 are created correctly. The program is started, but the registry keys cannot be found by the program anymore.
Now, finally, User1 tries opening the program again. (The registry entries cannot be found anymore.) Edit: The registry entries are actually there, but its values are empty.
So, my questions:
Why can't I see the registry entries with regedit after the install, although they are obviously there?
(2. Why are the registry entries deleted, when the second user tries launching the program for the first time and how can I avoid that?)
Edit:
2. Why are the registry values set to empty strings, when the second user tries launching the program for the first time and how can I avoid that?
Cheers from Auckland and thanks!
Marc
You might be missing the registry entries if you have a 32 bit package installed on a x64 machine. In this case the registry entries would be redirected under "HKLM\Wow6432Node...". This is the standard behavior for x64 Windows machines. The same happens with the file redirection to Program Files and Program Files(x86).
That is strange. It could happen that the second launch of the installer, a normal automatic repair operation, has removed the registry entries by mistake. To get more details about the actions executed during the second launch I recommend you enable permanent logging on the OS.
http://support.microsoft.com/kb/223300
Wonder why the Find-function didn't find the keys though?
Probably the API used is considering the keys do not exist if all the values are empty. You should check its docs.
Obviously the "second installer" performs the entry again, without having values for that. Do you have an idea how to solve that?
This usually happens if the registry are written with values from public properties. During the automatic repair the properties don't have their initial install values so they are considered to contain an empty string, which is than used to replace the registry values.
The only solution you have is to make a small custom action that runs during repair, as immediate, which searches the registry entries before they get overwritten and places their values in the properties your are using. This way the overwrite operation will use the correct values.

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

Using Inno Setup to patch an Install Shield Application

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!

Uninstall error if original install DVD is not in drive

When trying to remove our application in Add/Remove Programs, the following error pops up, and the application fails to uninstall:
Error
'mFileBagIDE.dll' is not a valid short file name.
The curious thing is that you only get this error if the original installation DVD is not in the drive. If the DVD is in the drive, the uninstall works perfectly.
Here's the real kicker: we did not catch this bug until after our application was already widely deployed, and our clients' situations are such that it is likely many of them no longer have their original DVD. This means that the next version's installer (doing a windows installer major upgrade) will fail because it is unable to first remove the previous version.
So, my question is twofold:
What did we do to create this problem so we can avoid it in future releases?
Is there a way to tell our next windows installer to ignore this error and go ahead and remove the previous version?
Our current installer (the one that is causing problems) was generated using InstallAware. We're likely moving to WiX. But solutions in any platform (InstallAware, WiX, raw MSI tables) are appreciated!
UPDATE: I have the following row in both the InstallExecuteSequence and InstallUISequence tables in my MSI, which may very well be relevant, but I have no idea what the SRCDIREX property is, or where it is being set.
| Action | Condition |
|---------------|--------------|
| ResolveSource | NOT SRCDIREX |
Probably one of the actions (either standard or custom) that references the original MSI was not conditioned to run on installation only (for example, ResolveSource should be conditioned as "Not INSTALLED"). You might be able to workaround this with a patch (an MSP file) that changes the condition on the relevant action.
I would start by determining which action is causing the error. Here's how I would do that:
Install your app from the dvd
copy the msi file to some local folder, let's say "c:\temp"
Remove the dvd
kick off the uninstall like this: "msiexec /x yourapp.msi /L*v c:\temp\uninst.log"
When the error comes up, the uninstall is effectively paused. You can then check the end of the log to see exactly where you are in the sequence. That should help you to debug.
If the answer really is ResolveSource, regular patching may not be an option.
Heath Stewart mentions this in his blog -
http://blogs.msdn.com/heaths/archive/2007/10/25/resolvesource-requires-source.aspx
"In general, do not schedule ResolveSource. If this runs when installing a patch, for example, the user will have to insert the original media whether they would otherwise need to or not."
If that's the position you find yourself in, you could create a transform that updates the condition on your ResolveSource action, and apply that to the cached copy of the msi file manually. It's a bit of a pain, but I'm pretty sure that would work.
have you tried to copy those files to %WinDir%/system32 folder?
EDIT: Make a setup to copy all the setup MSI package to the disk, and install it from the diskdrive.
Remove every files uneeded to uninstaller. Adobe, HP and many other companys are doing that.

Resources