0
votes

My installer needs to read a value from the registry and set the install path to parent of that value.

For example, from registry I get:

D:\apps\client

Then the installer should install the app to

D:\apps

I tried [DIR]\..\ (in "Directory" or "CustomAction"), but seeing following error when installing:

Error 1324. The folder path '..' contains an invalid character.

How can I do this with WiX?

2

2 Answers

3
votes

It seems that you can't do it with pure wix. You can use the Custom Action Type 1. Execute it in immediate mode before 'LaunchConditions' action. Initialize somewhere in your wix-code new property like:

<Property Id="DIRFROMREG" Value="0" Secure="yes">  

And here is sample on C#:

 public class CustomActions
{
    [CustomAction]
    public static ActionResult DirectorySearchAction(Session session)
    {
        try
        {
            session.Log("Directory search");
            RegistryKey reg = Registry.LocalMachine.OpenSubKey(@"...your subkey...");
            if (reg != null)
            {
                var dir=reg.GetValue("...your value...");
                /*
                    var parentdir= split here your directory
                */
                session["DIRFROMREG"] =parentdir;
                session.Log(@"directory is ");
            }
            else
            {
                session.Log(@"The registry key is not found");
            }
        }
        catch (Exception e) 
        {
            session.Log(@"Error "+e);
        }
        return ActionResult.Success;
    }
}

And the last thing:

<SetProperty Id="INSTALLLOCATION" Value="[DIRFROMREG]" After="Your custom action">NOT DIRFROMREG=0</SetProperty>

Hope this helps.

0
votes

Nerielle has a good answer. My installs all go to subfolders so when I find an old component I need the parent folder for install, so I came here for an answer.
From Custom action to manipulate property I found how to get the parent folder since I have a known fixed install sub path.

    <!-- Set INSTALLFOLDER from SERVERINSTALLFOLDER without the \Server\ -->
    <CustomAction Id="VBScriptInstallFolderFromFoundServer" Script="vbscript">
      <![CDATA[         
        pathvalue = Session.Property("SERVERINSTALLFOLDER")
        if pathvalue <> "" Then
          Session.Property("INSTALLFOLDER") = Left(pathvalue,Len(pathvalue)-Len("\Server\"))
        End If
      ]]>
    </CustomAction>

Combined with Locate Installation directory of another product

    <Property Id="SERVERINSTALLFOLDER">
      <!-- Id="C_SERVER_SERVERHOST.EXE" Guid="{xxx GUID OF my exe component xxx}" -->
      <ComponentSearch Id="ServerComponentSearch" Type="file" Guid="{xxx GUID OF my exe component xxx}">
        <DirectorySearch Id="ServerComponentDirectorySearch" Depth="0" AssignToProperty="yes" />
      </ComponentSearch>
    </Property>

And with Wix remember property pattern storing the INSTALLFOLDER path in registry.
I can now update old, or install new getting the correct install path of previous install as suggestion.
The vbscript could have been changed to use path handling function to find parent instead of removing fixed sub string to more correcly answer the question but...
My InstallUISequence and InstallExecuteSequence :

      <!-- Save INSTALLFOLDER parameter to CMDLINE_INSTALLFOLDER -->
      <Custom Action='SaveCmdLineValue' Before='AppSearch' />
      <!-- Set INSTALLFOLDER from SERVERINSTALLFOLDER without the \Server\ -->
      <Custom Action="VBScriptInstallFolderFromFoundServer" After="AppSearch">
        SERVERINSTALLFOLDER
      </Custom>
      <!-- Set INSTALLFOLDER from parameter CMDLINE_INSTALLFOLDER -->
      <Custom Action='SetFromCmdLineValue' After='VBScriptInstallFolderFromFoundServer'>
        CMDLINE_INSTALLFOLDER
      </Custom>

And lastly... in Product I to refer to the Fragment I put these in:

    <!-- Install to previous install path From parameter, OR from found installation OR from registry -->
    <CustomActionRef Id='SaveCmdLineValue' />
    <PropertyRef Id='INSTALLFOLDER'/><!-- include Fragment -->
    <PropertyRef Id='SERVERINSTALLFOLDER'/><!-- include Fragment -->
    <CustomActionRef Id='VBScriptInstallFolderFromFoundServer' /><!-- include Fragment -->