MSI Registry prepend value not updated - wix

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).

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.

WIX Error 1327. Invalid Drive

I have windows service installation process, which worked before untill today.
When I run msiexec /i "C:\installation.msi" /log "C:\logs.log" TARGETDIR=C:\destinationPath
I got error: Error 1327. Invalid Drive: D:\
In logs I can see TARGETDIR repeated 3 times:
Property(N): TARGETDIR = D:\
Property(S): TARGETDIR = C:\
Property(C): TARGETDIR = C:\
In Wix I have
<Property Id="TARGETDIR"/>
And installation
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory...
What can be wrong that firt value of property TARGETDIR is D ? I don't have this drive, can it be cache, or some windows key ? Any suggestion ?
It would help to see more of the verbose log, but if the only log entries related to cached products are as you posted then you are not doing a fresh install. A fresh setup will say something about running from the actual MSI file, and will not refer to cached context. That implies that your ProductCode (or sometimes PackageCode) is still installed on the system, and you are NOT installing your MSI product - you are causing a maintenance mode operation on that already installed product, and that's what is looking for a D:\ drive.
The fact that you removed all those registry entries and it worked confirms this, but it would have been preferable to locate that installed product and uninstall it. There are all kinds of registry entries related to PackageCode, UpgradeCode, Component IDs that may still cause issues. If you were to ask Windows which products are using a particular Component ID you may find it believes there are two. If you uninstall your product does it remove all the files and run any custom actions successfully? If the ref counting of component Ids is wrong that's the kind of thing that can happen.
when I dumped all logs using /lvoicewarmupx
I saw
MSI (s) (D0:0C) [18:55:43:619]: Using cached product context: machine assigned for product: EDA754DD57D2E6245809CEAB950DA2D7
MSI (s) (D0:0C) [18:55:43:619]: Note: 1: 1327 2: D:\
Then I removed from registry all entries for key EDA754DD57D2E6245809CEAB950DA2D7
And Problem is solved.
We have experienced a similar problem "Inavlid Drive A:" on installs where users are either:
Trying to run the MSI from a zip
Trying to run the MSI from a network location

How can I stop an .exe on repair, update and delete in wix?

In my wix I use the following declaration:
<ComponentGroup Id="BinComponents" Directory="BIN">
<Component Id="BinComponent" Guid="23D229D0-06EE-49f4-80B4-6D7136500721">
<File Id="MyProjectOutput" Name="MyProject.exe" Source="MyProject\bin\MyProject.exe"/>
<ServiceControl Id="RemoveService"
Stop="both"
Remove="both"
Name="MyProject.exe"
Wait="yes" /> <!-- Stop running MyProject instances -->
</Component>
</ComponentGroup>
My Repro:
At first, I run my installation as usual. After the installation, I start my web application. An .exe appears in the task manager as usual:
I want to end this .exe on a repair, update or uninstall. So I start my .msi again and choose repair:
Now my problem: After pressing 'Repair', I expect the following dialog because of the declared ServiceControl:
But it doesn´t. Instead, the following dialog appears:
When I log the setup, the log shows the following lines:
MSI (s) (A8:DC) [10:16:28:227]: Executing op: ActionStart(Name=StopServices,Description=Stopping services,Template=Service: [1])
Action 10:16:28: StopServices. Stopping services
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ServiceControl(,Name=MyProject.exe,Action=2,Wait=1,)
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ActionStart(Name=DeleteServices,Description=Deleting services,Template=Service: [1])
Action 10:16:28: DeleteServices. Deleting services
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (A8:DC) [10:16:28:229]: Executing op: ServiceControl(,Name=MyProject.exe,Action=8,Wait=1,)
MSI (s) (A8:DC) [10:16:28:229]: Executing op: ActionStart(Name=InstallFiles,Description=Copying new files,Template=File:
[1], Directory: [9], Size: [6])
[...]
MSI (s) (7C:28) [09:06:21:950]: RESTART MANAGER: Did detect that a critical application holds file[s] in use, so a reboot will be necessary.
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 1610
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 2205 2: 3: Error
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1610
Next to a Repair I also have tried an Update with the same results.
Perhaps any declaration missing?
Note: When I close the MyApp.exe in the task manager, the message does not appear, so the MyApp.exe is definitely responsible for the problem.
You should post the entire log somewhere. The root cause is that a repair shouldn't routinely require files to be replaced. So if you literally installed your product, ran the exe, and then a repair needs to replace files, then the issue is not that files-in-use dialog - it's that the installed product is broken, so required files or registry entries have been removed. The application event log should have MsiInstaller entries that describe a missing component. So look at that root cause first.
After fixing that it should be very rare for a repair to need to replace files, so it may not be worth worrying about. But you could look at integrating your app with Restart Manager or using the WiX util CloseApplication.
The warning dialog that you are seeing is from "InstallValidate" standard action.
I have run into a similar issue in the past . I fixed it by making use of a single service control element instead of multiple service control elements, for the same service id.
In my case, i had multiple service control elements for the same service id.
This is as per the link at
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Upgrade-uninstall-restart-issue-td7586315.html
This did the trick for me. Numerous users have reported the same behavior, though its not officially documented.
Having a single service control element makes Restart Manager take note of the entry in the Service Control table and will prevent Restart Manager from listing the service in the RMFilesInUse dialog box or will prevent Restart Manager
from throwing up warning messages informing the user that a restart might be required.
Here is one more link
Can't start windows service with WiX
My experiments have shown me that there is definitley a link between the number of service control elements and Restart Manager
http://microsoft.public.windows.msi.narkive.com/OOuQQAsw/controlling-restart-manager-behaviour
The other option was to totally disable Restart Manager using the property RESTARTMANAGERCONTROL, In case, you disable the RestartManager, you might be prompted for reboots(you might want to test it once) and the legacy "Files in Use" mechanism kicks off. Disabling Restart Manager is a conscious decision by the concerned msi developer and at times becomes necessary.
I am not sure about how your Service Control table looks like. Just wanted to share my experience with you.
Hopefully it helps.
Regards,
Kiran Hegde

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.

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.