Windows application registry settings and guidelin

2019-02-21 01:33发布

问题:

As I have been learning WiX to write an installer, I've learned a lot from documentation and tutorials how to setup a program during install and set or read registry values. However, the registry settings in said documentation and tutorials is done without explanation for what the requirements are for such settings.

As a specific example, I have a WiX installer for a simple application with InstallScope set to perMachine. I wanted to add a "registered user" dialog to my WiX installer. I found an example which allows the user to enter their name, organization, and a registration key. These are set to the WiX pre-defined properties: USERNAME, COMPANYNAME, and PIDKEY, respectively. When these are validated, under the hood, WiX writes these out to the following registry folder:

HKLM > Software > Microsoft > Windows > CurrentVersion > Installer > UserData > S-1-5-18 > Products > {GUID} > InstallProperties

I've been doing a lot of research trying to find the answer to the following questions and have not been able to find the answers.

  1. What are the minimum requirements (or at least minimum Microsoft guidelines) for what registry entries need to be set when installing the simplest Windows application? I know that this depends somewhat whether the install is for all users (machine), or specific users, so there would be two different answers.

  2. Where are the standard locations that simple application information is supposed to be kept in the registry?

  3. In order to meet the guidelines/requirements of #1, what are the registry settings that WiX always creates under the hood without explicit XML entries to make them occur?

  4. Once certain registry items are set, as in the example given above, how does the application locate them properly using the registry API? Specifically, for example, if once installed, I want my app to be able to read the registered user information, does it literally have to know and open the entire key as shown above, or is there a Windows API call that handles part of that?

I did find some promising looking information in the MSDN, in an article entitled, Application Registration, but I'm having trouble correlating the specifics of that article with what WiX does with the registry for an install. Specifically, for example, they suggest using HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER > SOFTWARE > Microsoft > Windows > CurrentVersion > App Paths > ... but on my system (running Windows 10) that key doesn't even exist. So other apps aren't even using it. This leads back to my question #1.

回答1:

Those "WiX pre-defined properties: USERNAME, COMPANYNAME, and PIDKEY" are actually Windows Installer properties with documentation here in MSDN, such as PIDKEY here:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370826(v=vs.85).aspx

I didn't see a question related to them, but being Windows Installer properties they are intended for use during the install. The fact that username is written to the registry is an implementation detail of the documentation:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa372385(v=vs.85).aspx

stating that if it's not automatically set it will use the previously saved value.

WiX generates MSI files for install, so many of its properties and data items translate directly to something in an MSI file or a Windows Installer property. Most of the information to do with standards and best practices for Windows Installer is here:

https://msdn.microsoft.com/en-gb/library/bb204770.aspx

as "Windows Installer Best Practices" and it includes a link to the Windows Installer Logo Requirements:

https://msdn.microsoft.com/en-gb/library/aa372825.aspx

all of which talks about installation and application best practices, so this really is a "link only" answer to that part of the question because there is a lot there.

Regarding #3 you probably mean Windows Installer, not WiX. But either way it's irrelevant because it's implementation detail. There are MSI APIs - see comment below. One example: If Windows writes information about all your installer components to the registry it is unimportant because MsiEnumComponents() will enumerate all the components on the system, MsiEnumClients() will enumerate the products that own them, MsiGetComponentPath () where a component was installed, and so on.

It's not clear from your question what "registered user information" is, unless you mean USERNAME. Do you want to find out who installed the product? If so, USERNAME is not the best choice because it doesn't have to be a user account - it's just a name. In general there are APIs for everything like this that do NOT require reading the registry. MsiGetProductInfoEx () will get you product information for a particular user. MsiEnumProductsEx () will enumerate all products and which user installed them.

PIDKEY is the non-validated product id, as the docs say. It becomes the ProductID property that can be retrieved from an app using MsiGetProductInfo (..ProductCode..., "ProductID", ...) and note also you get "RegCompany" and "RegOwner" which are the others you refer to.



回答2:

I think Phil has answered most of your questions, let me see if I can add something to issue 4. Some tentative answers to issue 1 and 3 towards the end. And issue 2 - perhaps see the list of registry locations just below.

If I understand correctly, you want to access the "standard properties" written to the registry during the installation via the proper APIs so you don't need to read the registry locations you speak of directly. In essence you want to go through the correct APIs.

Thank God someone makes the effort to figure this out, way too many people hack the registry directly. Never go down that road.


With regards to issue 2. The Windows Installer database is stored in several registry locations, here are some of them:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer
  • HKCR\Installer
  • HKCU\Software\Microsoft\Installer
  • Please add items here if you got any, I know there are more locations than this

Everything found under these keys is essentially an implementation detail as Phil has explained. Nothing should be written here, and as you suspect nothing should be read from here "manually" (directly).

Maybe I misunderstood the question? Perhaps what you want is to know where to store your own, custom MSI properties reliably? If you ask me, I would just store them in either:

  • HKLM\Software\YourCompany\YourApp\MajorVersion [List of values here]
  • HKCU\Software\YourCompany\YourApp\MajorVersion [List of values here]

You can make any number of such custom properties, and you simply use a registry element in WiX to write the value of the property to the registry. You refer to the value as [PROPERTYNAME] in the registry tag to write the value of the property to the specified registry key / value.

  • How To: Read a Registry Entry During Installation
  • How To: Write a Registry Entry During Installation

Your application can then read the information back with ease using standard Win32, .NET or even COM APIs.


Now issue 4 - retrieving built-in MSI property values from the registry:

If you want to retrieve standard, built-in MSI properties from the registry (in other words, not your own, custom properties), you should go through the proper API, since the location in the registry will be a "moving target" when you upgrade your application using an MSI major upgrade (the product code is part of the registry path, and using a major upgrade the product code will change) - so do not read directly from sub keys of: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18.

So, in order to access information in MSI database files directly (from actual MSI database files) OR to retrieve information from installed packages on your system (from the registry), you can use the MSI API - in other words the Windows Installer Win32 API which also provides a COM layer on top of it accessible from scripting languages. So in essence you have:

  1. C/C++ style installer functions (Win32 calls usually used from C++)
  2. COM automation
    • Essentially a COM layer on top of the installer functions
    • You can use VBScript, JavaScript, or any Active Scripting languages to access it.
  3. Third alternative: DTF - a .NET wrapper around the Win32 MSI SDK (details below, and on serverfault.com). Allows you to efficiently access the MSI SDK from .NET languages such as C# without any COM Interop clunk.

The MSI SDK: Do you have msi.chm help file readily available? This is the MSI Bible. It is your one-stop location for all things MSI (you probably already have it, I think it is installed with WiX) - and you will find the documentation for accessing the MSI API here. If you don't have the file, but have Visual Studio installed, just search for it and add a shortcut to your desktop or something like that. Or look for it in your WiX installation folder. You can also find the info online on MSDN, but it is much faster using the local file. And you get a sense of "completeness" when you are dealing with a file instead of the "endless web".

As part of the MSI SDK there is a sample COM automation VBScript which shows how to retrieve product information (product properties) for an installed MSI package. It is called wilstprd.vbs - there is a whole family of such sample VBScript for various MSI related tasks. I am almost certain this is not included with WiX (perhaps it should be?), and it is NOT part of the MSI SDK help file msi.chm.

If you have Visual Studio installed, the Windows SDK should also be installed. Just search for wilstprd.vbs and you should find it in several locations (x86, x64 versions - no file content difference). You can start your search in %SystemDrive%\Program Files (x86)\Windows Kits if you have a default installation.

You can run this script like so (using cmd.exe or powershell.exe):

cscript .\wilstprd.vbs "{A645BC30-D32A-408B-B964-C190C9056D7A}"

This will produce a list of property values from the installed MSI:

All the information you need to retrieve MSI properties from the registry database should be in that sample file (wilstprd.vbs), but below is a quick mock-up that I adapted since I had it available (I think it was a sample from Phil I adapted). It is just a minimal sample without any error handling. It just outputs some core MSI properties to a text file for all installed MSI files.

Copy the script and paste into a *.vbs file on your desktop, and try to run it by double clicking. Your desktop must be writable for you, or you can use any other writable location. Output is to msiinfo.csv (obviously open in Excel, Notepad or any other viewer for comma separated values). This is a terrible script in the sense that is has no error handling, and it doesn't escape any embedded commas in the property values, but it is just intended as a short example of the MSI API in action:

Set fso = CreateObject("Scripting.FileSystemObject")
Set output = fso.CreateTextFile("msiinfo.csv", True)
Set installer = CreateObject("WindowsInstaller.Installer")

On Error Resume Next ' Ignore all errors

output.writeline ("Product Code,Product Name,Version") ' Column headers

' Output 3 core built-in MSI properties for each installed MSI package
For Each product In installer.ProductsEx("", "", 7)
   productcode = product.ProductCode
   name = product.InstallProperty("ProductName")
   version=product.InstallProperty("VersionString")
   output.writeline (productcode & ", " & name & ", " & version)
Next

output.Close

MsgBox "Export done, please open msiinfo.csv"

And finally, issue 1 & 3 - what are the minimum properties required for registration? The honest answer is that I don't know. I am not sure.

This is then only a tentative answer, but the MSI SDK sample script wilstprd.vbs retrieves the following MSI properties. I assume this means that these are always written to the MSI database - some of them seem to always return an empty string. They are hence built-in MSI properties.

ProductCode, Language, ProductName, PackageCode, Transforms, AssignmentType, PackageName, InstalledProductName, VersionString, RegCompany, RegOwner, ProductID, ProductIcon, InstallLocation, InstallSource, InstallDate, Publisher, LocalPackage, HelpLink, HelpTelephone, URLInfoAbout, URLUpdateInfo

Some of these properties are crucial and come from the MSI database file itself such as Product Code, ProductName, Language, PackageCode, VersionString. I don't think an MSI can be installed without these values set. All should be set by a WiX compiled package, to the best of my knowledge.

Other properties are set depending on how the installation was performed via msiexec.exe (command line). This includes Transforms (list of transforms applied at the installation command line), AssignmentType (whether MSI is installed per machine or per user), InstallSource (the source location for the installed MSI), InstallDate (short DateTime in string form for when install or modify was performed).

Transforms are little database fragments applied to an MSI at install time. They are used to modify the original MSI without changing the original files. Here is a description of using transforms and applying them and / or property values at the command line.

Finally some properties seem to often be missing and return blank such as RegCompany, RegOwner, HelpLink, HelpTelephone, URLInfoAbout, URLUpdateInfo. These may need to be manually added to the property table I believe (or rather added as properties in your WiX source file).


Completely off topic, but you ask all the right questions, and I think you just need the right information sources (instead of me over-explaining things perhaps).

I apologize if this is poor etiquette - but this should include all kinds of sources that may actually help people if they can't find answers here. I am happy to delete this if inappropriate.

When finding my feet with new technologies I always try to find the SDK information with help files and hopefully basic samples. Then I look for real-world samples and finally I look for information sources and blogs to ask for advice and read (in essence figure out what not to do, more than what to do). Here are some of my favorite information sources for MSI / WiX - links for self-help:

The definitive sources the "bible" help files:

  • The MSI SDK: msi.chm
  • The WiX help file: WiX.chm
  • The DTF help files (included with WiX): DTF.chm, DTFAPI.chm

DTF is a .NET wrapper for the whole MSI API. It is extremely well designed and makes it easy to access MSI files and MSI information using C# and other .NET languages. It is installed as part of WiX.

Online WiX resources:

  • WiX Documentation Home
  • WiX Reference Manual
  • WiX tutorial

Finding general deployment information:

  • http://www.installsite.org
  • http://www.itninja.com/

Asking deployment questions:

  • http://forum.installsite.net
  • http://www.itninja.com/question
  • http://www.stackoverflow.com (obviously)
  • http://community.installshield.com/
  • http://www.advancedinstaller.com/forums/

Blogs:

  • https://www.joyofsetup.com/
  • http://robmensching.com/blog/ (old: https://blogs.msdn.microsoft.com/robmen/)
  • https://blogs.msmvps.com/installsite/
  • http://blog.deploymentengineering.com/
  • https://blogs.msdn.microsoft.com/astebner/

I think that should be a "balanced list" of deployment resources, but many may have been forgotten.