WIx - "Registry key not found" when trying to see if a value of SQL SMO exists

2.4k views Asked by At

It's been a while since I've done any WiX, but just found out that a bit of an existing bootstrapper exe I wrote ages ago, isn't actually doing what I thought it was - doh !! I've seen other people with similar issues, but I still can't figure out why it's not working.

I'm basically trying to determine if a particular version of SQL SMO is installed and am looking in the registry at this location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion

where there is a REG_SZ key called "Version" and it's set to something like 13.0.1601.5

Below is a mock-up of my code:

    <?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
     xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

    <Bundle Name="RegReadTesterSetup" Version="1.0.0.0" Manufacturer="BigChris Inc" UpgradeCode="fcaa47db-3b55-474f-995d-2b0a0905fced">
        <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />

    <util:RegistrySearch Id="IsSMOInstalled"
                 Root="HKLM"
                 Key="SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion\Version"
                 Value="13.0.1601.5"
                     Win64="yes"
                 Result="exists"
                     Format="raw"
                 Variable="SMOInstalled"/>

        <Chain>
      <MsiPackage SourceFile="C:\Users\chris.moxon\AppData\Local\Temporary Projects\SimpleTextFileSetup\bin\Debug\SimpleTextFileSetup.msi"
              Id="MYTEXT"
              DisplayName="Big Chris Test File"
              Visible="yes"
              InstallCondition="SMOInstalled = 0"
              SuppressSignatureVerification="yes"/>
        </Chain>
    </Bundle>
</Wix>

Note : The indented settings (Win64 & Format) are just some of my clutching at straws attempts to get it to work; but with or without these settings; run on a 64bit or 32bit machine, I always get (on machine's where this key does exist !):

Registry key not found. Key = 'SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion\Version'

Setting numeric variable 'SMOInstalled' to value 0

in my log file; so the end result is that the SMOInstalled variable always gets to set to 0 and thus SMO ( or my text file ) is always installed.

I appreciate (or hope) that I must be doing something silly - but alas I have no idea what !!

Thanks in advance,

Big Chris.

1

There are 1 answers

1
Brian Sutherland On BEST ANSWER

This should work:

<util:RegistrySearch Id="IsSMOInstalled"
             Root="HKLM"
             Key="SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion"
             Value="Version"
             Win64="yes"
             Result="exists"
             Variable="SMOInstalled"/>

You shouldn't need Format="raw" when doing a Result="exists" registry search.

The issue you are having is that you are mixing up what a key and value represent in the registry. The "Key" is the path you see at the bottom of regedit when you pick a registry location. The value is actually the name a registry value at the registry key location. In this case the Registry Value that you want is "Version" from the key "HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion" and you are seeing if that value exists or not (which will set SMOInstalled to 0 (not exists) or 1 (exists)).

If you want to get the actual version information (the "data" on the registry value) you need to use Result="value" and then SMOInstalled will be set to the data of the Registry Value or not defined if it does not exist.

To understand Win64="yes" you need to understand the difference between the 64bit registry and 32bit registry. On a 32 bit machine there is only one registry and I'm not sure how Win64='yes' registry searches behave. On a 64 bit machine there are two registry locations. One for 32-bit processes (x86) and one for 64-bit processes (x64). If explicitly specified you can view the other bitness' registry location from a certain bitness process but you need to be sure this is what you want to do. A 32 bit process on a 64bit machine that tries to look at the registry gets its registry keys redirected to SOFTWARE\Wow6432Node\abc\xyz... even though you only specified SOFTWARE\abc\xyz... .

If your program works with either the 32bit or 64bit SMO installed you'll likely have to check both registry locations. This would mean having two registry searches on for the 32 bit registry location and one for the 64 bit location. You can something like this

<util:RegistrySearch Id="IsSMOInstalledx86"
             Root="HKLM"
             Key="SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion"
             Value="Version"
             Result="exists"                     
             Variable="SMOInstalled"/>

<util:RegistrySearch Id="IsSMOInstalledx64"
             After="IsSMOInstalledx86"
             Condition="SMOInstalled = 0 AND VersionNT64"
             Root="HKLM"
             Key="SOFTWARE\Microsoft\Microsoft SQL Server\SharedManagementObjects\CurrentVersion"
             Value="Version"
             Win64="yes"
             Result="exists"
             Variable="SMOInstalled"/>

(Just as an extra gotcha, you can't use "NOT SMOInstalled" in your registry condition because just using PROPERTYNAME or NOT PROPERTYNAME in a condition actually evaluates whether the property is defined or not and doesn't actually evaluate the value of that property at all. See here for more info, specifically under the "Properties in Expressions" header.)