Wix Installer Registry Search Fails - wix

I am attemping to do a registry search with in a wix installer so that I know where to install my plug in. I am trying to look up where Tekla Structures 2018i is installed at. However, every time I try running the installer my condition fails. Any help would be greatly appreciated.
Product tag:
<Property Id="TSMAINDIR">
<RegistrySearch Id="TS2018iSetupMain"
Root="HKLM"
Key="Software\Tekla\Structures\2018i\setup"
Name="MainDir"
Type="raw"
Win64="yes"/>
</Property>
<Condition Message="This application requires Tekla Structures 2018i. Please install Tekla Structures 2018i then run this installer again.">
<![CDATA[Installed or TSMAINDIR]]>
</Condition>
RegEdit:
UPDATE:
I have created a log file. The file is rather lengthly so I will not post it. However, When I do a search for TSMAINDIR I find the following:
AppSearch: Property: TSMAINDIR, Signature: TS2018iSetupMain
MSI (c) (00:34) [14:25:26:994]: Note: 1: 2262 2: Signature 3: -2147287038
MSI (c) (00:34) [14:25:26:994]: PROPERTY CHANGE: Adding TSMAINDIR property. Its value is 'C:\Program Files\Tekla Structures\'.
MSI (s) (E4:2C) [14:25:27:694]: Ignoring disallowed property TSMAINDIR

Looks OK to me. You have the right bitness flag so you search the x64 section of the registry. Have you looked in the log file? How to create a log file.
I don't really think it should matter since you are not in deferred mode, but try setting the property to be secure:
<Property Id="TSMAINDIR" Secure="yes">
<...etc...>

Related

WiX Condition works in MSI but not in Bundle

When I'm building my MSI file, and I use a basic condition, the expected happens. For example, let's say that I have this in Setup File:
<Property Id="myProperty" Value="0"/>
<Condition Message="Value of myProperty is [myProperty], and it should be 1.">
<![CDATA[Installed OR myProperty = "1"]]>
</Condition>
If I build this and run the MSI file, it works -- that is, it displays the error message and quits.
Working condition when running MSI
However, if I put the MSI into a Bundle, it doesn't work. That is, when I put just this into my Bootstrapper ("Properties" below is the name of my Setup project -- bad name, I realize):
<Chain>
<MsiPackage SourceFile="$(var.Properties.TargetPath)"/>
</Chain>
And then I run the setup file, I get an error. When the installation starts, it checks the condition, gives me the expected message box (same as above), and then I get this error message:
Setup Failed
Looking at the Log, I get three error messages:
Error 0x80070643: Failed to install MSI package.
Error 0x80070643: Failed to execute MSI package.
Error 0x80070643: Failed to configure per-machine MSI package.
With the exit code:
Exit code: 0x643, restarting: No
I'm such a noob at WiX that I'm not even sure how to go about researching what the problem is -- I can't even ask an intelligent question. Hence, I'm reaching out to you kind folks!
(I'm using WiX 3.10 and Visual Studio 2015)
EDIT:
Thanks for getting back to me! I tried your suggestions:
In the installer file, I made the property public and I made it secure. I left the condition the same, and, since I don't think that I should get the value here as opposed to in the bootstrapper, I left the value of the property out. Here is the code that I made for the property/condition:
<Property Id="MY_PROPERTY" Secure="yes"/>
<Condition Message="MY_PROPERTY is [MY_PROPERTY]. Should be 1">
<![CDATA[Installed OR MY_PROPERTY = "1"]]>
</Condition>
Then, in the boostrapper file, I added a child element of and gave it a value:
<MsiPackage SourceFile="$(var.LCondErrorInstaller.TargetPath)">
<MsiProperty Name="MY_PROPERTY" Value="0"/>
</MsiPackage>
When I ran it, I got almost the same behaviour as I did before, except for one difference -- when I get the error message. This time, I get the pop-up screen with the Message condition and the same error message as I did before (see "Setup Failed" above), except this time I get it happens little later in the installation, making me think that the condition is, in fact, getting triggered in the bootstrapper.
As far as the log files, they look the same (I'm not sure how to get log files of the MSI when running the Burn file, what I do now is just run the Burn file with the flag "/l", like so: > file.exe /l logFile.log).
For clarity, here are the parts of the log file that appear to be important:
Error 0x80070643: Failed to install MSI package.
Error 0x80070643: Failed to execute MSI package.
Error 0x80070643: Failed to configure per-machine MSI package.
...
Exit code: 0x643, restarting: No
I should have been more specific when I initially asked the question about what kind of behaviour I'm looking for...
I will have more than just that one MSI file in the Burn file. What I want to do is this: when the Burn file installs, if there is a condition in one of the MSI files that is not met, I want that MSI file to simply not be installed, and the rest of the MSIs to be installed. I don't care about the UI.
If there's another way to do this, I'm all ears.
If you have launch conditions in the MSI you can replicate or move those launch conditions into the bootstrapper bundle itself to stop this type of behaviour.
Launch condition failure returns Fatal Error 1603 (0x643 in hex) which is what I would expect to see when the MSI launched by the bootstrapper fails due to launch condition not met.
You should see something like this in the msi's logs
Action ended 17:33:38: LaunchConditions. Return value 3.
MSI (c) (08:4C) [17:33:38:610]: Doing action: FatalError
Action 17:33:38: FatalError.
Action start 17:33:38: FatalError.
...
MSI (c) (08:4C) [17:33:41:188]: MainEngineThread is returning 1603
To elaborate, you would have to change your msi package definition to the following to get it to run properly through the bootstrapper
<Chain>
<MsiPackage SourceFile="$(var.Properties.TargetPath)">
<MsiProperty Name="MYPROPERTY" Value="1"/>
</MsiPackage>
</Chain>
Additionally if you want to pass in a property from your bootstrapper to your MSI the property must be a public property which is a property whose name is ALL CAPS.
If you want to use this property somewhere in the Install phase of your msi you must also mark this property as secure.

MSI Registry prepend value not updated

We are using wix 3.9.1208.0 to generate MSI. Below code prepend the value to Upperfilters registry key.
<RegistryKey Id="UpperFilters" Root="HKLM" Key="xxxxxxxxx" Action="create">
<RegistryValue Name="UpperFilters" Type="multiString" Action="prepend" Value="xxxxx"/>
</RegistryKey>
After install observed, value not prepend to 'UpperFilters' registry key and not found any errors in MSI log. This issue happened only once.
MSI Log:
MSI (s) (0C:28) [10:38:08:835]: Executing op: ComponentRegister(ComponentId=xxxx,KeyPath=02:xxxxx,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
MSI (s) (0C:28) [10:38:24:455]: Executing op: RegOpenKey(Root=-2147483646,Key=xxxxx,,BinaryType=0,,)
MSI (s) (0C:28) [10:38:24:456]: Executing op: RegAddValue(Name=UpperFilters,Value=xxxxx[~],)
Is MSI returns any failures when unable to update registry?
Will all registry failures are recorded in MSI log?
What's the issue in my scenario?
Thanks in Advance.
It might help to show more from the log. It's hard to tell what's going on from those log fragments. ComponentRegister isn't typically next to RegOpenKey - it's just a register of the keypath in the registry and not related to the actual issue.
There are few things that could be wrong:
Why is the Component id xxxx? Have you hidden the actual guid when you posted the log information or is that what you actually used? It's not a legal id.
It's a 64-bit system and you tried to update the 32-bit registry. Without knowing the system bitness and your MSI's architecture we can't tell if you updated the required key.
Prepending doesn't really do anything if there is nothing in the existing data, so without seeing the data before and the data afterwards it's not clear if it worked correctly (because there was nothing to prepend to) or failed (because it did not actually prepend your data to the existing data).

Wix v3.7 - Error Writing Registry Values

I'm creating an installer using wix and I'm having problems writing to the registry. Here is my RegistryValue element:
<Component Id="CMP_odbcreg" Guid="{115B002E-F4C9-48CD-8E1C-E8803B16AE69}">
<RegistryValue Id="rg_psql"
Root="HKLM"
Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"
Name="PostgreSQL"
Value="Installed"
Type="string"
KeyPath="yes"
Action="write"/>
</Component>
Nothing is being written to the registry. This component is in my main install feature, so it should always write to the registry. I looked at my log file and found this:
MSI (s) (60:1C) [00:00:07:080]: Doing action: WriteRegistryValues
MSI (s) (60:1C) [00:00:07:080]: Note: 1: 2205 2: 3: ActionText
Action 0:00:07: WriteRegistryValues. Writing system registry values
Action start 0:00:07: WriteRegistryValues.
WriteRegistryValues: Key: Writing system registry values, Name: , Value:
Action ended 0:00:07: WriteRegistryValues. Return value 1.
I don't know if I'm interpreting that right, but it seems like nothing is being written to the registry at all. I have several other components generated using heat that contain RegistryValue elements which should have been executed in addition to CMP_odbcreg. I checked my Windows Registry and confirmed that no values are being written.
I have a wix manual which contains an example of writing to the registry. I tried copying and pasting it into my installer and adding it to the main install feature. That didn't work either
Please Help!
So it turns out I was looking at the wrong registry. Windows 7 machines have a 32 bit AND a 64 bit registry, so I should have been looking at the regedit.exe found in Windows\SysWOW64.
Since nowadays 64 bit systems are widely spread I recommend a small lecture on Registry Redirection, I am sure you will find the info useful for the future. This applies to any application accessing the registry, not just to an installer.
In your case, if you need to disable the redirection for the installer, you can have a look at this SO thread.

Why doesn't this silent launch work in WIX?

I have the following command running at the end of my package install for an application.
<Property Id="WixShellExecTarget" Value="[INSTALLDIR]RCR.VDS.exe" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA"
DllEntry="WixShellExec" Impersonate="no" />
I can't use [#myApplication] because I run heat on my output folder on my build server so I don't know the auto generated id of my application. Any ideas on how to silently run my application after the install?
The log file shows this for the command line section
******* CommandLine: **********
MSI (c) (30:74) [09:47:14:156]: Note: 1: 2203 2: VDSInstall.msi 3: -2147287038
MSI (c) (30:74) [09:47:14:156]: MainEngineThread is returning 2
Please see: How To: Run the Installed Application After Setup
If you want the custom action called during a silent install add:
<InstallExecuteSequence>
<Custom Action="LaunchApplication" After="InstallFinalize">SOMECONDITION</Custom>
</InstallExecuteSequence>
Note SOMECONDITION should be an expression that checks the EXE is installed and the user wants the program to be launched.
The are a copy things you can consider:
The identifier from heat.exe will be stable. So you can use the ugly identifer in your [#UglyFileId1234abcef45612345asdf] custom action.
a. You could also apply a XSLT to transform the heat output for the executable file's Id to something nicer than the ugly identifier. Depends how readable you want the launch custom action to be.
If you want the executable launched silently then you'll probably want the Quite Execution custom action instead of the Shell execute custom action that "LaunchApplication" uses.

Writing install location to registry from installer

I am using WiX 3.6 to create an installer.
One of the needs is to write the location of the install location to the registry in either HKCU or HKLM depending on the ALLUSERS property.
Now based on the research I have done I think the following should work
<RegistryKey Root="HKMU"
Key="Software\OpenCover"
Action="createAndRemoveOnUninstall">
<RegistryValue Name="Location"
Type="string"
Value="[APPLICATIONFOLDER]"
Action="write"
KeyPath="yes" />
</RegistryKey>
The problem is it only works for when ALLUSERS="" i.e. HKMU is interpreted as HKCU.
If I try a perMachine installation where ALLUSERS=1 then the entry is not written to HKLM as expected, though when I look at the installer log file I see the call to WriteRegistryValues.
MSI (s) (D4:14) [22:46:24:901]: Executing op: ActionStart(Name=WriteRegistryValues,Description=Writing system registry values,Template=Key: [1], Name: [2], Value: [3])
Action 22:46:24: WriteRegistryValues. Writing system registry values
MSI (s) (D4:14) [22:46:24:902]: Executing op: ProgressTotal(Total=2,Type=1,ByteEquivalent=13200)
MSI (s) (D4:14) [22:46:24:903]: Executing op: RegOpenKey(Root=-1,Key=Software\OpenCover,,BinaryType=0,,)
MSI (s) (D4:14) [22:46:24:903]: Executing op: RegAddValue(Name=ConsoleLocation,Value=C:\Program Files (x86)\OpenCover\,)
WriteRegistryValues: Key: \Software\OpenCover, Name: ConsoleLocation, Value: C:\Program Files (x86)\OpenCover\
MSI (s) (D4:14) [22:46:24:906]: Executing op: RegCreateKey()
WriteRegistryValues: Key: \Software\OpenCover, Name: , Value:
Can someone explain how to achieve the task I need to complete
The problem is actually to do with a 32 bit installer on a 64 bit platform.
When ALLUSERS="1" is used in this scenario then the registry entries, marked up with HKMU, are actually being written, but under in this case, HKLM\Software\Wow6432Node\OpenCover. I suspect entries marked as HKLM are also redirected in the same manner.
Unfortunately the documentation on WriteRegistryValues Action does not explain the 32/64 bit of "magic" redirection and the information, details regarding the actual registry entry, doesn't appear in the logs.
To get an insight as to what is happening then the following article demystifies the observed behaviour Registry Keys Affected by WOW64. From this article we can see that the installer "thinks" it is writing to a folder HKLM\Software but this is actually being "redirected" to HKLM\Wow6432Node\Software for a 32 bit process on a 64 bit platform and hence explains why it is not reflected into the log files. The article also explains why when ALLUSERS="" and HKMU is then HKCU why the entries appear where one would expect them to be, because these entries are "shared" between 32 and 64 bit applications.
My guess is that your installer isn't elevating (UAC enabled?) and that the write to HKLM is being redirected to HKCU.
BTW, you could also consider using the Windows Installer API from within your application to query the UpgradeCode, ProductCode, ProductInformation(INSTALLLOCATION) without the need to write a registry key to store this metadata.