Windows Installer Resiliency Check testing
It's been a few years since I worked actively with this but I noticed something strange that I had trouble with reconciling. I've made some example msi files and written up a demonstration text:
Basically I am very curious why there is such a difference between RepairTest_File.msi and RepairTest_One.msi.
RepairTest_File.msi does not behave logically to me. If this was by design you really should see the same happening in the RepairTest_One.msi example.
Can someone explain this? Just how it's supposed to work?
Note: This require a fairly high level of Windows Installer knowledge.
1 Comment
[ + ] Show comment
-
so how were you actually testing the repair function?? - Badger 8 years ago
-
By pressing the (advertised) start menu shortcut. Your question implies that you are missing some key information, let me know if you need further clarification. - dreyer 8 years ago
Answers (6)
Please log in to answer
Posted by:
apptopack
8 years ago
Couldn't get much time to test. Have just analyzed your source and see that RepairTest_file and RepairTest_one msi's are having ICE 38 error for c_filezilla.xml component. It's always recommended to eradicate errors during validation.
I will analyze the installation once when I get time and explain you in detail about your case.
Comments:
-
Yeah, I've noted the ICE 38 error, I've read the reference on the validation error but it really makes little sense.
"Component Component1 installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file."
First, why? Second, no it mustn't :) My RepairTest_One.msi example shows otherwise.
Looking forward to reading your input mate :) - dreyer 8 years ago
Posted by:
Pressanykey
8 years ago
Hi,
as my previous commentator has noted, ICE's can be really helpful. In this case, you really should use registry keys as Key Paths for components containing user specific data, even if this requires creating "dummy" registry keys.
When I have a bit of time I will look into the examples you have given us...
just my tuppence
Phil
as my previous commentator has noted, ICE's can be really helpful. In this case, you really should use registry keys as Key Paths for components containing user specific data, even if this requires creating "dummy" registry keys.
When I have a bit of time I will look into the examples you have given us...
just my tuppence
Phil
Comments:
-
I guess in the end we might be forced to accept this as just the way it is but it is terribly poor design, at least that is my perspective but it is possible there is something I'm missing.
Also it's not accurate considering that this is not a requirement as long as the user data is stored in the same feature as the entry point.
I welcome your input! - dreyer 8 years ago-
Hi Dreyer, your agrumentation is vlaid, AS LONG AS THE USER DATA IS STORED IN THE SAME FEATURE AS THE ENTRY POINT. (sorry for shouting) ;-) . But this is usually only the case if you have created the msi yourself, you have of course, full control. However... with vendor MSI's this is a different matter completely. I've gotten into the habit of using reg keys for components that contain user specific data and to be really 100% sure you can also use active setup... again, horses for courses right?
Phil - Pressanykey 8 years ago
Posted by:
EdT
8 years ago
Both the MSIs are not written in a way that I would expect to work.
Incidentally, Pressanykey's comment about the userdata being stored in the same feature as the entry point is incorrect, and suggests a lack of understanding of how the repair process works.
If you have user and machine components, they should not be in the same feature. When creating a user feature for installation of user files and registry keys, it should be made the PARENT feature of all other existing features in the installation. This is easily done using ORCA or any other MSI editor. Use a registry key path in HKCU that does not already exist in user profiles It's OK to put everything in one component (with a registry key path) as the user profile install is not usually that big anyway. DO NOT put any machine parts in this component or feature (including HKLM keys) as locked down users will lack permissions for the install and it will fail on repair. ALLUSERS should be set to 1 to ensure reliable operation and correct context of DLL registration.
The key factor to understand here is that the repair process goes UP the feature tree. So ANY advertised entry point that is triggered in a child feature will result in that child feature being checked for missing key paths, and if none are found, the repair check moves up the feature tree, feature by feature, until the parent feature is checked. As in our example the parent feature is the "user feature", the missing HKCU key path will be noted, and the entire user feature repaired. So in practice, there is no need whatsoever for there to be an advertised entry point in the parent (user) feature.
In the example given by the O/P, the child feature should contain everything except the content needed in the user profile, which is the xml file if I understand the app correctly. The parent (user) feature would then contain a component installing a registry key to HKCU with the registry key as key path, and the file would be added to this component for simplicity. Just make sure that the user path for the XML file resolves correctly during repair.
Comments:
-
Hi Edt,
I can't remember saying that it's not important about mixing user and machine data, and as far as I can remember (and looking at my comments) at no point endorsed it... One of the major ICE's (IMHO) that need and should always be addressed is that concerning user and machine resources in the same component. I only suggested that always add a HKCU registry key to a component as this ensures / enhances resiliency. I personally do not think there is anything wrong with mixing user / machine components in the same feature.
Phil - Pressanykey 8 years ago-
Hi Phil,
My reference to your posting is only in one sentence and the rest of the posting is about the O/P's question in general. There is indeed nothing to stop you mixing user and machine resources in the same component, but where you have a user -feature- which is intended to self heal in a user context, you cannot put machine content in it as the user will seldom have the permissions to install it and the self heal will fail. - EdT 8 years ago-
Hi Edt, I think we have crossed wires here, I DO NOT endorse mixing user and machine resources in COMPONENTS and would avoid it at all costs whilst repackaging, but see no harm in mixing components that contain (only) user resources with components that contain (only) machine resources in a single FEATURE. This is mainly due to my normal job of re-packaging, were I tend to put everything on one feature, and have the corresponding actions for the deployment tool to be executed. As for authoring a MSI installation, that's a different matter and would depend on the requirements of the customer and application (here you cannot always adhere to the "perfect" solution and / or best practices...
just my tuppence - Pressanykey 8 years ago
-
Hi EdT,
I must say I disagree with your "feature design". I would not say that it "suggests a lack of understanding of how the repair process works", but it does not consider all implications of such a design.
Consider a shared environment, terminal servers or meeting room computers, multiple users with different permissions / licenses etc.
As long as there are "system wide entry points", like COM (when the Class table is used). You are exposing that MSI (entry point) to every user on that machine.
With that in mind, I would argue that the correct design would be the other way around. User components in a sub-feature and Machine components in a parent.
How that design would work:
- When a machine components entry point is triggered by a user that shouldn't have access to that application, it will still be able to use that COM component (given that there are no keypaths missing on the system, which in normal cases there aren't) without doing any repair. And no files from that application will be written to that users profile. (That user shouldn't have access, why install user files/settings assosciated with it?)
- For users that do have access and should trigger a repair for user files/settings, you should expose an entry point to the sub-feature to those users only, i.e: shortcuts.
* I would agree that this has little technical implications for a standard client desktop/laptop, that are more or less single user.
** It's worth noting that you could design packages so that any and all "system wide entry points" reside in a sibling-feature. Potentially making the package less robust (would not repair that feature through other entry points), but more importantly; you would have to repackage just about everything if you want this design to be consistent across your environment.
*** The problem becomes severer if you are operating in an environment where sources are locked down with equivalent access permissions... any triggered repair of files will require access to the source MSI, which will not only break the repair for that particullar MSI, but render any application that attempt to load the COM useless. - aslakt 8 years ago-
Hi Aslakt,
You are of course correct that the solution has to be appropriate to the environment, and my solution was indeed specifically for the situation where applications are deployed with ALLUSERS=1 which has been pretty much the corporate standard at the dozens of corporates I have worked for. Citrix and terminal server environment present different challenges as self healing just does not work due to the lack of permissions that users enjoy. In that environment active setup has (in my experience) been the reliable alternative. As to repairs needing access to the source MSI - that is easily solved by placing any such required files on the local machine and adjusting the MSI accordingly - basically using the duplicate files table. Where you are working with Windows 7, the entire MSI is cached locally as this was an MS fix for the issue of signed apps failing to uninstall when they were cached locally without the internal cabs - this broke the signing. Bizarrely, MS did not add the necessary information into the registry to use this local cache as a repair source for the MSI but again that's easy to do and I wrote it up in an article on Symantec Connect. - EdT 8 years ago-
Agreed.
But I still believe that in terms of correctness, best practise, logic and all that good stuff, the user specifics should be the child feature. Even if the scenarios are few and far between, the design is still an improvement to the other way around. - aslakt 8 years ago
-
This is what I consider the ideal feature structure:
-> Public
----> UserData
-------> Private
Break down of contents of the various features:
-> Public: Common COM objects or other common files (or common advertised entry points), example: MSCOMCTL.OCX
-> UserData: HKCU settings or %AppData% files for the relevant application.
-> Private: Application spesific files, i.e. MyApp.exe under %ProgramFiles%\MyApp or default MyApp HKLM settings.
This would be in an ideal world where Windows Installer did not require you to use a HKCU registry key in the UserData feature to trigger an repair.
In the real world I would most likely just merge the contents of UserData and Private feature into one single feature. By keeping the user data in the same feature as the entry ponint (shortcut) you can use the userdata file as the component KeyPath instead. - dreyer 8 years ago
Posted by:
EdT
8 years ago
Is this a belief you can back up with any MS or third party documentation? I have yet to find anything that specifically addresses these points, and best practices, in my experience, tend to be business-specific. Microsoft themselves have moved the goalposts as the version of Windows Installer has incremented from 1.x to the present day.
I have a simpler belief - if it works in the environment you are packaging for, then it is correct.
Comments:
-
I'm not entirely sure how to reply to that, but I'll give it a shot:
1: I fail to see what you gain from having user settings in a parent feature, apart from the cosmetics of having them separated.
2: Single feature design provides the same functionality, and you're even safe as far as ICE 38 goes (yes it will still complain if you run the check, but it will install user files without using registry keypaths).
3: User settings in a sub-feature provides all the above while isolating the user settings from machine settings, even when entry points are triggered "unintentionally".
3.1: I should mention that the feature design described in my first comment includes a shortcut to a "machine component" in the user-feature. If you want to separate completely, this shortcut should be in a sub-sub-feature, but you would then need to take care of ICE 38.
- The diplomatic conclusion then would be to go for #3.1. Which has a bit of both worlds.
- I must admit I struggle to see the problem of going for option 3, apart from the obvious mix of "component types". What are the technical issues with it, considering you've sorted out everything mentioned by feature design?
(@dreyer kinda beat me to it :) ) - aslakt 8 years ago-
What both you and @dreyer may have missed in my earlier posting is that the repair process moves UP the feature tree. My placing the machine parts in a child feature together with their shortcuts, the MSI gets installed fine by a system account. Any advertised entry point in the child feature will then trigger an integrity check on the child feature (which should pass unless there is a fault in the MSI) and will then MOVE UP to the parent feature and check key paths there also. That should kick off a self healing operation if a user component's key path is missing, as it will be following a system install. Since the self healing operation takes place with user privileges, that precludes the inclusion of any machine components which a standard user would not have permissions to install. But is it perfect for file and registry installs to the user's profile. As for the Microsoft ICE errors, it is not always possible to fix every one as it was impossible for MS to predict every permutation of MSI structures that would work perfectly and include them in their tests. We all understand how important MSI testing remains, including install, uninstall and reinstall, to ensure integrity of the operating system and the app itself.
The one downside of having user components in a child feature is that self healing is not triggered unless there is an advertised entry point in a feature that is a child of the child, or in the user feature itself. Conversely, I have yet to encounter a practical reason to avoid having the user feature as the parent of all subfeatures. I would add that the user-parent-feature approach is something I use only where user self healing is required and as an alternative to active setup. It's also easy to implement using ORCA which in complex MSI files avoids some of the nasties that commercial editors can insert. - EdT 8 years ago-
"Since the self healing operation takes place with user privileges, that precludes the inclusion of any machine components which a standard user would not have permissions to install."
I think this is wrong. If you install an application per-machine in System Context, delete the MyApp.exe from the Program Files folder using an admin account and then logon with a standard user account and press the advertised shortcut for MyApp you will see Windows Installer repairing and installing MyApp.exe again. This is where trusted installer comes into play. - dreyer 8 years ago
Posted by:
Pressanykey
8 years ago
Hi All,
this is turning out to be a really interesting discussion...
I agree with Edt, the advantages of having the UserData Feature being the root, as this ensures that when any self repair operations are executed, any user specific resources are ensured to be checked for the presence of KeyPaths and if missing repaired (and lets face it, this is usually where the danger lies, as the user can delete his / her own resources as and when they please).
Also, as previously mentioned, if it works for the environment you are deploying to, it's good enough. Regarding Terminal Service environments, that's always usually a stickler, and you have to make compromises here. Speaking of compromises, best-practices here or there, as soon as you have to author a MSI for a specific customer for a specific software application, whilst trying to adhere to your own principles, as soon as the (paying) customer wants / requires something that is not strictly best practice / makes sense, this has to be implemented, as, in the end, he is paying the bills...
just my threpence...
this is turning out to be a really interesting discussion...
I agree with Edt, the advantages of having the UserData Feature being the root, as this ensures that when any self repair operations are executed, any user specific resources are ensured to be checked for the presence of KeyPaths and if missing repaired (and lets face it, this is usually where the danger lies, as the user can delete his / her own resources as and when they please).
Also, as previously mentioned, if it works for the environment you are deploying to, it's good enough. Regarding Terminal Service environments, that's always usually a stickler, and you have to make compromises here. Speaking of compromises, best-practices here or there, as soon as you have to author a MSI for a specific customer for a specific software application, whilst trying to adhere to your own principles, as soon as the (paying) customer wants / requires something that is not strictly best practice / makes sense, this has to be implemented, as, in the end, he is paying the bills...
just my threpence...
Comments:
-
The same applies when user data is stored in the same feature as the entry point, however. Of course you can't stick user data in a feature below your entry point, but nobody here is recommending that anyway :)
Keeping user data in the root feature defers no advantages that I am aware of. While it has significant disadvantages in some scenarios.
Take this example:
Appl-A has the following feature structure:
-> User Data
--> Common Files
--> Application Files
The 'Common Files' feature contains the following file with advertising info (Class, ProgID): scrrun.dll
Two users are using a computer intermittently with this application installed: User1 and User2.
User1 makes use of Appl-A while User2 has no intrest in it.
User1 logs onto the machine, presses the start menu shortcut (entry point) and launches the application. The user data repairs and all is well in the world. User1 ends his day and logs off the computer.
Day two comes around and User2 logs on, he has no interest in this application but he is an avid VBScripter. He runs a VBScript that calls on Scripting.FileSystemObject (scrrun.dll contains this object). But what is this? A repair is triggered? All of a sudden User2 now has received all the user data for Appl-A. You can deduce that the design of such a feature structure is flawed even though in practical terms it is not a very big deal.
The situation where this is a really big deal was especially valid for SCCM 2007 where you'd install directly from a distribution point (UNC Path). In many corporations Appl-A UNC path would be locked down with a security group. User1 would be a member of this security group, while User2 would not. This poorly authored Windows Installer package would then prompt a repair every time User2 called the Scripting.FileSystemObject object. It would prompt for the source of the installer but would be unable to locate it as User2 would not have read rights on the InstallSource folder.
Likewise on Terminal Services this will flood the Event Log with unnecessary warning errors and start to fill up userprofiles with unnecessary data.
Now further on...
Appl-B has the following feature structure:
-> Common Files
--> User Data
---> Application Files
The 'Common Files' feature contains the following file with advertising info (Class, ProgID): scrrun.dll
In the exact same scenario as above when User2 logs onto the machine and calls on the Scripting.FileSystemObject the Windows Installer entry point will hook onto the top level feature. A resiliency check will be made against the top feature "Common Files" and Windows Installer will report back that all is well; no repair will be triggered for user data for User2 for Appl-B.
You can clearly see why such a feature structure is superior. - dreyer 8 years ago-
+1 - aslakt 8 years ago
-
I believe your example is flawed as scrrun.dll should already be present as part of the operating system fileset and it is bad practice to install another instance especially if there is a version difference. This is what conflict management is all about, and I would argue that scrrun.dll would have been removed (or disabled) by any competent packager as part of the packaging or test process.
I do follow your argument but are you able to offer another example that does not include bad practice, as many of my clients would have specified. - EdT 8 years ago-
Same would apply for any COM installed with advertising info.
The example is good because it would be easy for anyone to reproduce it for testing.
Are you being difficult just for the sake of being difficult here? - aslakt 8 years ago -
Obviously you'd never put scrrun.dll in your package, I used it as an easy to follow example. That doesn’t mean your captures won’t include other common files that are shared between applications (that are not a part of the default operating system files) that might behave in this manner.
I don’t have a readily available example at the top of my head, but you understand the argument which is all that matters. We aren’t really in disagreement in regards to the user data anyway I just demonstrated to you why it’s not _always_ the best idea to put user data at the very top. We both agree with the concept of having user data in the above (or in the same) feature as the main application files (.exe and the entry points). - dreyer 8 years ago
Posted by:
EdT
8 years ago
I would always try to separate out files that are of a shared nature, even if not part of the native O/S - specific examples including the VC++ runtimes. Typically these get updated at some point as the inevitable security issues creep out and it's safer to have these runtimes deployed separately to any dependent apps as then the whole issue of revision control is taken away from the main app. Again, it's horses for courses as some companies prefer to have runtimes included as part of the base app layer for the O/S whereas others would only deploy when needed. Equally, I would consider any process that triggers the repair of another application to indicate a flawed package, and conflict management goes some way to avoid this, but as we all know, you cannot realistically conflict manage apps like MSOffice (as it breaks updates) and inevitably there are conflicts in real life that cannot be fixed. So at the end of the day, I hope we can all agree that there are different ways to achieve a given result, and it is finding the way that works for your environment is ultimately the primary goal.
Comments:
-
I do the same thing, no objections here. Merry Christmas! - dreyer 8 years ago