KeyPath for component: is a Directory: . The directory/component pair must be listed in the CreateFolders table

Published 11 August 8 8:19 PM | William

We've been finalizing one of our first new products in my company's product line and we're at the point where we are trying to just polish up any loose ends.  I had built some installers for QA to use but for some hard to understand reason, they didn't realize the installers were not suitable for customers.  I'd been out the last week so when I got a bug report and saw that the majority of the outstanding bugs were related to the installers, I realized there was some misunderstanding.  When I pointed it out to them I got a typical "Yah, I knew that" response that I always get when they miss something really obvious (several coworkers read my blog so  my snark is for their amusement).  After explaining the app.config files don't become part of the binaries and that there's more to a WCF binding than an endpoint, I realized I had a problem.  You see, at this point no one disputed that the current installers couldn't be used for the customer.  But no one in QA wanted to jump up and explain to the boss how this little oversight occurred. It quickly became evident that unless I dropped the issue, I was going to suffer through endless explanations of everything from "How it works in C++" to Installer theory whatever it took to get me to say "Ok, I'll fix it."  So off I went figuring what the heck, it'll only take 20 minutes or so.  But as I was walking to my office, a little devil appeared on my shoulder and started making recommendations to me about how to handle it. I told him to go away but he was a persistent bugger. And after a few minutes, I gave in. I decided to handle it in a really mature manner "I know, I'll write one huge installer for all 4 application components, including the database install, in WIX.  I'll intentionally screw up a few of the icons or something and when it's discovered I'll just play dumb and say "Oh yah, I guess I missed that. You know, since I built the whole script and I'm really busy, I'm going to need *you* to go fix those icon issues."  I realized I'd have to work really hard to keep a straight face as I said that, but it'd be worth it just to be able to listen to their response once they realized they'd have to edit it in WIX. Few things in the world make our QA folks more angry and upset than WIX.  The mere mention of the name from across the room can make them apoplectic.  Too bad I didn't remember the old adage about digging two graves before seeking revenge. 

I was sailing through it and in no time at all, I had a really awesome package.  It was really long and I did it in a hurry so I didn't comment much and I knew it was going to be a *** if I missed anything early on, the package was just getting really big.  I had broken the 4 figure mark in lines of code and had plenty more to go.  Stopping every time I added a new component/fragment/action etc to verify it was correct thus far, I was getting pretty smug.  Not only was the install looking really good, but in under 30 an hour, I had created over 1,500 lines and used every cool feature I knew of in WIX (and cool features are endless).  But even better I thought, "Wait until QA sees this.  They're going to be mad enough when they realize they agreed to a few simple things like icon changes and they find out its WIX, but when they see how long this thing is, hahahahahahahahahahaha"

Only one more thing to do here, the database. Ok, no problem, just write the component to handle clean installs and one for each of the upgrade paths (which was only one at the time).  All was going well and I was already mentally on my way home when I hit compile.  So after all the code that worked without a glitch, I'm down to the easy part and boom.

KeyPath for component: XXXXXXXX   is a Directory: XXXXXXXX. The directory/component pair must be listed in the CreateFolders table.

Below isn't the actual code but it's pretty much the same as  the part that was throwing the problem.  After all I've gotten done, some tiny little component like this is going to bust my chops!  WTF?

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension">
  <Product Id="5225f8c3-2eda-462a-80c1-398c463b39ce" Name="XXXXX" Language="1033" Version="1.0.0.0"
           Manufacturer="XXXXX" UpgradeCode="3b3a2ab7-b013-4d0a-b3c6-410ccbb71083">
    <Package InstallerVersion="200" Compressed="yes" />
    <Media Id="1" Cabinet="XXXXX.cab" EmbedCab="yes" />
    <Property Id="DiskPrompt" Value="HC Mass Notification Install Installation [1]" />
    <util:User Id="SQLUser" Name="[SQLUSER]" Password="[SQLPASSWORD]" />
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="SQLDir" Name="DB" >
        <Component Id="SqlComponent" Guid="AC141F81-A0CF-4737-93C3-82CDA33DDA27">
          <sql:SqlDatabase Id="SqlDatabase" Database="XXXXX" User="UserName" Server="[DBName]" CreateOnInstall="yes" DropOnUninstall="yes" ContinueOnError="yes">
            <sql:SqlScript Id="CreateDB" BinaryKey="create_db" ExecuteOnInstall="yes" />
          </sql:SqlDatabase>
        </Component>
      </Directory>
    </Directory>
    <Binary Id="create_db" SourceFile="CreateMassNotifications.sql" />
    <Feature Id="SqlFeature" Title="SqlFeature" Level="1">
      <ComponentRef Id="SqlComponent" />
    </Feature>
    <Property Id="UserName">username</Property>
    <Property Id="UserPassword">password</Property>
    <Property Id="DBName">server</Property>
  </Product>
</Wix>

 

So I start double checking my GUIDs and tags and all the usual stuff in the checklist whenever I can't build.  I'd embarrass myself thoroughly if I told you everything I did to try to get this to work.  I thought I had a similar problem a while back and that I just had to add an empty file to my directory tag.  So I attempted to do that and I still had the problem.  I started adding Components, ComponentGroups and well, every other stupid thing I could think of. Frustrated I thought "Ok , I've done this 100 times, I'll just start over from scratch."  Then I looked at the API documentation just to double check and nothing looked wrong.  Each new thing I tried just broke something else and I was way frustrated at this point.  But b/c adding a file didn't work, I totally ignored anything related to the directory.  After 20 minutes I decided to give up and started googling.   Quickly, I came across this guy who was having the same problem. Unfortunately it was long on people saying they had the same problem and short on solutions.  I noticed the piece by the guy recommending adding a file and I tried that again - to no avail (the real problem I was doing it incorrectly but that wasn't a great solution anyway. Adding an erroneous file just so the app compiles isn't very elegant although if it would have worked, I'd have called it a night and come back tomorrow).  I was into the 5th page of search results and still nothing.  Then I left for a few minutes and came back to it, and I tried searching again. 

Well, after going through the search results and hopping around, I found what looked like an answer.  But, but I tried adding a file several times, that can't be it.  And off I went making a mess of things again.  After another 40 minutes I was desperate (the little devil that originally appeared on my shoulder was nowhere to be found at this time) and thought, ok maybe it's worth another try.

So using an approach on that link I had overlooked, I decided to add the following line to my component:

<CreateFolder/>

I hit compile and it worked.  So I added it to each of the DB components I was building and viola, no errors.  Ran the setup, it worked and here I am.  So basically, for each component, I just needed to make the following modification:

<Component Id="SqlComponent" Guid="AC141F81-A0CF-4737-93C3-82CDA33DDA27">
         <sql:SqlDatabase Id="SqlDatabase" Database="HCMassNotifications" User="SQLUser" Server="[SQLSERVER]" CreateOnInstall="yes" DropOnUninstall="yes" ContinueOnError="yes">
           <sql:SqlScript Id="CreateDB" BinaryKey="create_db" ExecuteOnInstall="yes" />
         </sql:SqlDatabase>
         <CreateFolder/>
       </Component>

 

And according to the explanation, which makes absolute sense, "Your component is in a directory which does not have any files in it, so the validation is worried that the directory may not be created."  Afterward, I was in such a good mood I actually went back and added the correctly sized icons ;-) just to make sure there wasn't anything intentionally wrong with the installer.  That's what I get for trying to be a smart a55, everyone can laugh at me about how ignoring a single tag to each component blew up my wonderful install.

Filed under:

Comments

# Puneet said on September 2, 2008 2:22 AM:

Very useful. Thanks a lot!

Search

This Blog

Tags

Community

Archives

News

My other sites

Cool Stuff

Book Stuff

Security

ORM

Data Access

Funny Stuff

Compact Framework Stuff

Web Casts

My KnowledgeBase Articles

My MVP Profile

Design Patterns

Performance

Debugging

Remoting

My Fellow Authors

My Books

LINQ

Misc

Speech

Syndication

Email Notifications