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

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.

Related

After aborting the installer if i try to install again, installer is still pointing to old path

I am trying to install a installer developed using InstallShield 2008. While installing after selecting the destination path i am aborting the installation.
When i try to install again by default it is taking the destination path as previously given path which was provided before aborting the installation.
And also it is not allowing me to install in different path.
For Example:
*Step1 : Installation starts
Step2: Destination path as C:\Installer
Step3: Click next and abort installation
Step4: Start the installation again
Step5: Provide Different destination path as C:\Installer1*
Here installation is failed. Because destination is still pointing to Step2
My question is from where Installer is taking the old path.?
Persisted Path: The technicalities appear to be relatively straightforward: the old path is read back either from the registry or from disk each time the setup is launched, and a custom action in the setup's GUI sequence must have persisted the path "somewhere" during the first run (this is erroneous design, see technical comment below). Reading back the value can be done by using AppSearch (built-in MSI feature) or by means of a custom action.
Registry / Disk: As to finding where the value is read from. The easiest would be to just search the registry first for the literal path. Just open regedit.exe and search for the path there. You can also look for the custom action that does the persisting (or the AppSearch or custom action that does the retrieval) and see if it is a script with code you can see - then you should be able to see where it has persisted the path. Use Orca or a similar tool to view the Custom Action table. The custom action can also be compiled and undecipherable. Do you have the setup source? The path can also be persisted to disk, but the registry is most commonly used. Remember to search both HKCU and HKLM.
Involved Debugging: I can't see why you would, but it is also possible to use ProcMon.exe to monitor what registry locations your MSI reads and / or writes to. This is involved debugging and should never be needed for something this simple. Just mentioning it as a technical option. Generally the last resort we have to figure out the strangest problems.
Technical Comment: MSI setups are not supposed to write anything to the registry or disk from the setup's user interface sequence (setup dialogs). All changes should be made from the installation sequence (InstallExecuteSequence) which also generally runs with elevated rights - the user interface normally runs with user rights. This InstallExecuteSequence sequence is kicked off from the last dialog in the GUI sequence, and runs the file copy and system change operations. Control then returns to the GUI sequence to show the setup complete dialogs. It is also possible to run the setup silently, in which case the InstallUISequence never runs and all custom actions inserted there fail to run. Accordingly custom actions should be present in the InstallExecuteSequence as well as the InstallUISequence if they are to run in silent mode. This potential design flaw is a very common silent deployment error which occurs when setups are not designed properly for silent running. Remember that all corporate deployment runs silently. Setup GUI is highly overrated (in my opinion - a "fact" that could change in the future).
It is still possible for an MSI setup to write to the registry or disk from the InstallUISequence by using a custom action to do so. Such a custom action would normally not have access to write to HKLM or to protected parts of the disk - unless the whole setup runs elevated because it was launched from an elevated command prompt (for example), or launched by an admin who elevates it via the UAC prompt.
In other words: this setup is badly designed, but I guess that is clear already.

Change registry value permission command line or NSIS

I'm trying to grant ordinary users write access to a registry value I created.
They cannot have write access to the parent key.
Through regedit, it's simple:
1. Select value
2. Edit Permissions (change accordingly)
3. OK
However I'm struggling to do the same via command line or NSIS.
The command regini has a very nice method for changing key permissions. If this worked for changing value permissions, I could easily script it into my installer.
The NSIS plugin AccessControl has a very nice method for changing key permissions but no evidence of changing value permissions.
In this case, the key is HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run which I will not modify the permissions of.
How can I change only the permissions of the value I've created? How can I do this just as regedit allows, but silently through command line or NSIS?
The value would be something like:
[HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"My Value"="C:\Please\Let\Me\Change\Permissions\Sadface.exe"
Note, this is for scripted software installer which build script will run on Mac, Linux and Windows (NSIS allows this). Recommendations for bundling special dlls or Windows executable is OK so as long as they're easily bundled and chained against at install time. Solutions including tools such as Windows SDKs cannot be accepted unless the footprint is small and so as long as the DLLs can easily be bundled and included into a LGPL 2.1 project. e.g. installing users will have to run this, so solutions need to be reasonably portable/distributable.
As #Noodles mentions in the comment above, it's not possible to change value permissions, so no solution exists. Registry editor is actually providing the key permissions, which is observable by looking at the Window title, and which is undesired for this particular solution.

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.

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

How does the savedState Dictionary work in the Installer?

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?

Resources