4
votes

I need to install my app's files to usual location like C:\Program Files\MyApp
and also need to copy several of them into custom folder in another partition
(let's say D:\CustomFolder, it's allowed to hardcode it).

Install should be silent - no gui or wizard. And alose everything should be in one *.msi file.

I can do that via CustomActions, but elegant-declarative way is preferable.

Has anyone tried this before?
Thanks.

UPDATE: Forgot to mention, that it's allowed for files that should be on separate partition to be in C:\Program Files\MyApp

3

3 Answers

4
votes

Solved. The approach is:

  1. Specify custom folder where file should be put:

    <Property Id="MY_CUSTOM_DESTINATION" Value="D:\MyCustomFolder" />

  2. Put <Copy ..> directive into <File ...> which should be copied

<DirectoryRef Id="MyAppFolderThatIsInProgramFiles">
     <Component Id="MyComponent" Guid="some_guid">
      <File Id="MyFileXml" Source="MyFile.xml" KeyPath="yes" >
          <CopyFile Id="Copy_MyFileXml" DestinationProperty="MY_CUSTOM_DESTINATION"/>
      </File>
     </Component>
</DirectoryRef>

p.s. as a side-effect, file specified in <File Id="MyFileXml" ... /> will be put into both location: C:\Program Files\MyApp and D:\MyCustomFolder, but that's correct for my task.

1
votes

It's against Windows Installer Best Practices to hard code directories. You can never assume there will always be a D: or even a C:. Still, customers have asked (demanded) that I install something to D:\FOO.

So, how to make the customer happy and have the install still "work" on that VM that doesn't have a D:? By redirecting the directory at install time with a custom action that only redirects it if D: is a fixed hard disk.

Also, while the CopyFile element is useful, it's not really needed because you can just author the files into components twice and smart cabing will make sure your MSI doesn't bloat up by having the File records point to the same entry in media \ cab storage.

0
votes

You can simply describe your disk structure under the Directory Tag:

<Property Id="DRIVE_1" Value="c:\" />
<Property Id="DRIVE_2" Value="d:\" />
<Property Id="DRIVE_3" Value="e:\" />

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="DRIVE_1" />
    <Directory Id="DRIVE_2" />
    <Directory Id="DRIVE_3" />
</Directory>

I wouldn't advocate hardcoding, but you get the idea.