In WiX how do I test for the existence of a registry key (not value) for Oracle ODP.Net

Dan picture Dan · Aug 25, 2009 · Viewed 19.9k times · Source

More specifically I want to test whether Oracle ODP.Net is installed on a machine. I want to do this by testing for the HKLM\SOFTWARE\ORACLE\ODP.NET registry key.

The actual values used by ODP.Net are stored in HKLM\SOFTWARE\ORACLE\ODP.NET\2.111.6.20 however I assume that this lower level key's name will change as updates are released by Oracle.

I have tried the following which fails, possibly because the (Default) value doesn't really exist or possibly because it is null (I'm not sure exactly how it's represented in the registry).

<Property Id="ORACLE_ODPNET">
  <RegistrySearch Id="ODPNET_RegKey" Type="raw" Root="HKLM" Key="SOFTWARE\ORACLE\ODP.NET" Name="(Default)"/>
</Property>
<Condition Message="This setup requires ODP.Net to be installed.">
  Installed OR ORACLE_ODPNET
</Condition>

So any of the following would be helpful to me:

  • A way to search for a registry key with no values under it.
  • A way to search for a registry value using a path containing wildcards
  • A better way to test for ODP.Net being installed

Answer

Dan picture Dan · Aug 27, 2009

OK, so thanks to Sascha's information it seems that the answer is "you can't" using the built-in WiX registry functions.

Now I also wanted this test to happen along with the other launch condition tests which makes it a bit harder. Getting this to work has taken me quite a while although it's fairly simple now I know how, so hopefully this will save someone else the same pain.

First create a property inside your WiX Product:

<Property Id="ODPNETINSTALLED">0</Property>

Next create a custom action to check for the key and set ODPNETINSTALLED to "1" if it exists. I'm not going to go into compiling and adding the custom action to the installer here but it's fairly simple if you use Votive in Visual Studio. The code for my custom action is:

using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Win32;

namespace WiXCustomAction
{
  public class CustomActions
  {
    [CustomAction]
    public static ActionResult CheckOdpNetInstalled(Session xiSession)
    {
      xiSession.Log("Begin CheckOdpNetInstalled");

      RegistryKey lKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ORACLE\ODP.Net");

      xiSession["ODPNETINSTALLED"] = lKey == null ? "0" : "1";

      return ActionResult.Success;
    }
  }
}

Now you need to register and schedule the action, because I wanted the warning to appear along with my other launch conditions I had to add it to the InstallUISequence element:

<Binary Id="WiXCustomAction.dll" SourceFile="$(var.WiXCustomAction.TargetDir)$(var.WiXCustomAction.TargetName).CA.dll" />
<CustomAction Id="CheckOdpNet" BinaryKey="WiXCustomAction.dll" DllEntry="CheckOdpNetInstalled" Execute="immediate" />
<InstallUISequence>
  <Custom Action="CheckOdpNet" Before="LaunchConditions">NOT Installed</Custom>
</InstallUISequence>

Finally add a launch condition to check the property:

<Condition Message="!(loc.OracleOdpCondition)">
  Installed OR ODPNETINSTALLED="1"
</Condition>

Note that I believe that scheduling in InstallUISequence means the custom action won't be fired during non-UI installs. However, my installer must have UI install so it's not an issue for me.