Deciphering the MSI Directory table, part 6 (standard directories)
Before picking up this series of blog entries on the Directory table again, I went back and re-read all the previous entries to make sure I remembered the details told up to this point. It was then that I realized the last entry on this series as posted over 11 months ago. What disturbed me even more than the fact that I didn't realize I had dropped this series for so long (I thought I had posted in the last three months) was this quote:
The first paragraph of part 1 surprised me because it reminded me how long I've been operating under frustration.
For some people this blog series will be deciphering the MSI Directory table. For me this blog series will provide guide posts for a path I should never follow again. But enough of that. Let's get to the point and talk about standard directories in the Directory table.
As always I'm going to start with some example data. If this stuff doesn't look familiar (that's okay, it's been almost a year) I suggest going back and (re)reading part 5. Here's a Directory table modified from our part 5.
Directory Directory_Parent DefaultDirs
s72 S72 l255
Directory Directory
TARGETDIR SourceDir
ProgramFilesFolder TARGETDIR PFiles
FirstFolder ProgramFilesFolder One
Based on what we've learned thus far, you should expect that Directory table to create the following layouts:
Target layout
ProgramFilesFolder = TARGETDIR\PFiles\
FirstFolder = TARGETDIR\PFiles\One\
Source layout
ProgramFilesFolder = SourceDir\PFiles\
FirstFolder = SourceDir\PFiles\One\
You'd be half correct. The source layout would look exactly like that. However, the target layout would be quite different. The magic is in the ProgramFilesFolder identifier. That's because ProgramFilesFolder is what I call a standard directory. The MSI SDK has the full list of standard directories.
So how does it work?
Well, when the Windows Installer scans the Directory table, it converts the standard directory identifiers into the appropriate paths on the machine. For example, ProgramFilesFolder turns into the value returned by ::SHGetFolderPath() for CSIDL_PROGRAM_FILES which is usually something like "C:\Program Files\". The LocalAppDataFolder identifier is the value returned for CSIDL_LOCAL_APPDATA which is usually something like "C:\Documents and Settings\username\Local Settings\Application Data\".
That means that our target layout actually looks something like this:
Target layout
ProgramFilesFolder = ProgramFiles\
FirstFolder = ProgramFiles\One\
Note: "ProgramFiles" is intended to represent wherever "C:\Program Files\" actually exists on the user's machine. You should never expect ProgramFiles to be on the C: drive or even in "Program Files". I say this because the "Program Files" string is localized, that'll getcha' for sure.
This means that the FirstFolder directory will always be under ProgramFilesFolder. Next time we'll see how to allow the user to configure where your application gets installed. In the meantime, I would encourage you to take a look at that list of standard directories the Windows Installer provides you.
Comments
Anonymous
October 12, 2006
Nice to see the series continued. Hopefully the next installment will address a question I raised in the comments? ;) http://blogs.msdn.com/robmen/archive/2005/06/28/433241.aspx#435203Anonymous
October 12, 2006
I'm second guessing myself and wondering if I included the URL in my last comment. Since my comment hasn't appeared yet, I will post again with the URL just incase. ;) http://blogs.msdn.com/robmen/archive/2005/06/28/433241.aspx#435203Anonymous
October 13, 2006
New to your blog, Rob - just wanted to start out by saying a big THANK YOU for clarifying this for me. Any resources you'd recommend for more of this type of information about Windows Installer? I've been working in WfWI (Altiris - teh yuck), and I would much rather be using WiX; however, I don't feel like I know enough basic stuff about WI to be effective with either (or effectively explain WiX to our dev team). I think it's important that I understand the underlying tech on a fundamental level before I start ravenously advocating a switch. Added to aggregator, FGJ! ^_^