Problem with Wix uninstall using CustomAction - installation

I've created a very simple MSI which copies some files to the ProgramFiles directory and while installing calling to custom actions found in a binary written in C#.
While installing, I can easily call any custom action I want. For example I've created an installation step where the user should enter a license, and after confirming the license it is checked against a server using logic written inside C# custom action.
But, when uninstalling, every time I add a custom action (even if it does nothing but returning Success), I get error that the installation failed.
This is how I use the uninstalling step:
<InstallExecuteSequence>
<Custom Action='TestUninstallation' After='MsiUnpublishAssemblies'>REMOVE="ALL"</Custom>
</InstallExecuteSequence>
where TestUninstallation is defined as following:
<CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no" BinaryKey="TestCustomAction" DllEntry="Uninstall" />
The property DllEntry equals Uninstall which is a C# method which only returns Success.
After installation is completed, I'm trying to uninstall and I'm getting the UserExit dialog defined inside the AdminUISequence with the property OnExit.
Any idea what am I missing?

Debugging: Managed code is relatively easy to debug (native code is actually even easier). Here are some pointers:
Debug C# Custom Actions (Advanced Installer)
Different debugging methods / aspects
Suggestions: I think you just have a broken reference to the dll export function - in other words an erroneous dll function name / reference:
<CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no"
BinaryKey="CustomActions" DllEntry="__ERRONEOUS FUNCTION REFERENCE__" />
Just check what the dll actually exports and match like this:
<CustomAction Id="CustomAction1" BinaryKey="CustomActions" DllEntry="CustomAction1"/>
As always the real McCoy is the check of the dll itself to see if you have the right function name (the below screen shot from this prior answer, recommended read).
This is a native code C++ dll:
This is a DTF-packaged managed code dll:
Notice that this is a native dll with the managed code stuff embedded. It yields a very different functions list, but you still have to find the function name in there that you refer to.
This is a straight-up managed code dll (no native wrapping):
And finally: this is the straight-up managed code DLL without being wrapped in a native dll shell.
Un-Uninstallable Setup: When a custom action crashes or fails during uninstallation, you will have problems getting rid of the installation (it just rolls-back and you are stuck with it installed). There are several fixes or workarounds.
The overall fix - in my view - is to not fail custom actions on uninstall, or at least condition them so you can force an uninstall by setting a property via the command line:
Set in MSI property table: SUPPRESSERROR = 0. Then - when needed - on the command line set:
msiexec.exe /x {PRODUCT-GUID} SUPPRESSERROR="1"
Inside the MSI you condition the uninstall custom action with:
REMOVE="ALL" AND SUPPRESSERROR="0"
Now the custom action will not run if SUPPRESSERROR is anything but 0.
There is an older answer with several further options: I screwed up, how can I uninstall my program? (courtesy of Wim Coenen, with me messing up his answer with more suggestions).
Boilerplate: For quick use, let me just dump a boilerplate ad-hoc custom action test project here. This assumes a C# managed code custom action project called "CustomAction1" in the same Visual Studio solution and a reference added to it in your WiX source - like you already have obviously (this is for later when we have all forgotten what the problem was and need to test again):
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WiXCustomActionsTesting" Language="1033" Version="1.0.0.0"
Manufacturer="test" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<UIRef Id="WixUI_Mondo" />
<Property Id="SUPPRESSERROR" Value="0" Secure="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="WiXCustomActionsTesting" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<!--BEGIN CUSTOM ACTION SECTION-->
<Binary Id="CustomActions" SourceFile="$(var.CustomAction1.TargetDir)\$(var.CustomAction1.TargetName).CA.dll" />
<CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no" BinaryKey="CustomActions" DllEntry="CustomAction1" />
<InstallUISequence></InstallUISequence>
<InstallExecuteSequence>
<Custom Action='TestUninstallation' After='InstallInitialize'></Custom>
</InstallExecuteSequence>
<!--END CUSTOM ACTION SECTION-->
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WiXCustomActionsTesting" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="C:\Projects\MySetup\MyApp.exe">
</File>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Create WiX project
Copy paste the code, set a new Upgrade GUID
Create CustomAction project, default name
Add reference to custom action project from wix project
Add reference to WiXUIExtension.dll
Adjust path to file in component
Compile

Related

Unable to remove previous versions of MSI. Multiple entry's show up in control panel

I am not sure if i am missing something or i just plain dumb, the issue i am having related to uninstalling a MSI. Basically i am building a app, and using WIX to create the MSI installer. What is happening is that i am able to install a previous version of the app but not upgrade to a newer version MSI. E.g, when i click/install the newer version MSI then the older MSI, both MSI will be installed and visible in control panel(MyApp 1.5.0, MyApp 1.6.0).
I am pretty sure i have the "MINORUPGRADE/MAJORUPGRADE" along with the RemoveExistingProducts Action configured properly but this issue still happens.
I tried modifying the MINORUPGRADE/MAJORUPGRADE values and the RemoveExistingProducts property but still get the same behavior.
My WIX config looks like this (without the Directory/paths...)
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" Language="1033" Manufacturer="MyApp" Name="MyApp $(env.APP_BASE_VERSION)" UpgradeCode="$(env.UPGRADE_CODE)"
Version="$(env.APP_BASE_VERSION)">
<Package Compressed="yes" InstallerVersion="200" InstallScope="perMachine" InstallPrivileges="elevated" Description="MyApp $(env.APP_VERSION) Installer"
Comments="" Manufacturer="MyApp" />
<Property Id="MsiLogging" Value="v!" />
<MediaTemplate EmbedCab="yes" CompressionLevel="$(env.COMPRESSION_LEVEL)"/>
<Icon Id="icon.ico" SourceFile="$(env.STATIC_RESOURCE_PATH)\icon.ico" />
<Property Id="ARPPRODUCTICON" Value="icon.ico" />
<Upgrade Id="$(env.UPGRADE_CODE)">
<UpgradeVersion
Property="MAJORUPGRADE"
Minimum="0.0.0.0"
IncludeMinimum="yes"
Maximum="$(env.APP_BASE_VERSION)"
IncludeMaximum="no"
IgnoreRemoveFailure="no"
MigrateFeatures="yes" />
<UpgradeVersion
Property="MINORUPGRADE"
Maximum="$(env.APP_BASE_VERSION)"
Minimum="$(env.APP_BASE_VERSION)"
IncludeMinimum="yes"
IncludeMaximum="yes"
/>
</Upgrade>
...
<CustomAction Id="Remove_Roaming_MyApp" Directory="TARGETDIR" ExeCommand="cmd.exe /C "rmdir /s /q "[AppDataFolder]\MyApp""" Execute="deferred" Return="ignore" HideTarget="yes" Impersonate="no" />
<Property Id="WixShellExecTarget" Value="[#MyAppEXE]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<util:CloseApplication Id="CloseApp" Target="MyApp.exe" RebootPrompt="no" CloseMessage="yes"/>
<CustomAction Id="Kill_MyApp_instances"
Directory="TARGETDIR"
ExeCommand="taskkill.exe /IM MyApp.exe /F"
Execute="deferred"
Return="ignore" HideTarget="yes" Impersonate="no" />
<!-- This will create a log in the Temp folder of the user profile by default. NOTE: this is not the full log! The MSI will need to be ran with `/l*v <destination file>` -->
<CustomAction Id="CopyLog_partial"
ExeCommand="cmd /c copy "[MsiLogFileLocation]" "%SystemDrive%\Windows\Temp\MyApp-msi.log""
Directory="TARGETDIR"
Impersonate="no"
Execute="commit"
Return="ignore" />
<CustomAction Id="CopyLog_full"
ExeCommand="cmd /c copy "[MsiLogFileLocation]" "[LocalAppDataFolder]\Temp\MyApp-msi.log""
Directory="TARGETDIR"
Impersonate="no"
Execute="immediate"
Return="ignore" />
<InstallExecuteSequence>
<RemoveExistingProducts Before="InstallValidate" />
<Custom Action="WixCloseApplications" Before="InstallValidate" />
<Custom Action="Kill_MyApp_instances" After='InstallInitialize'></Custom>
<Custom Action="LaunchApplication" After='InstallFinalize'>NOT Installed</Custom>
<Custom Action="CopyLog_partial" After="PublishProduct" />
<Custom Action="CopyLog_full" OnExit="success" />
</InstallExecuteSequence>
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ELECTRON_FRAGMENTS"/>
<ComponentRef Id="Remove_MyApp_Roaming_comp" />
<ComponentRef Id="Remove_uninstallCache_folder" />
<ComponentRef Id="Remove_MyApp_programFiles_comp" />
<ComponentRef Id="Shortcut_startMenu" />
</Feature>
</Product>
</Wix>
The intended behavior is to remove the previous MSI or better yet all versions installed during the installation process of the MSI. I know this can be done with a CustomAction but i was wondering if theres a more elegant way to do this?
Summary: When you get two entries in Add / Remove Programs the major upgrade has failed. I suggest you comment out all major upgrade
constructs and try to get a heartbeat with the simplest constructs
available - explained below.
Major Upgrade: You have used old constructs to implement your major upgrade. There is a newer and simple way, like this:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
This is sort of like a "template" implementing the major upgrade with the least amount of fuzz by just using "normal options" or simplified options if you like. There is no need to add your own RemoveExistingProducts entry when you use this template, in fact that will probably yield a "duplicate entry / symbol" on compile:
Add the MajorUpgrade element above.
Comment out the entire Upgrade element.
Comment out the RemoveExistingProducts element.
Older Constructs: The MajorUpgrade element will be enough to implement a working major upgrade, but you can still use the old WiX constructs (Upgrade and UpgradeVersion elements) to obtain more fine-grained control of the authoring of the Upgrade table. It is this table which defines how existing installations are to be handled. The upgrade table identifies related products by matching upgrade codes and then performs whatever action is defined for that scenario in the Upgrade table itself.
Previous Answers: There are several older answers on this topic, please see the following:
Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs
Adding entries to MSI UpgradeTable to remove related products (this shows how to use both the newer template construct AND the older WiX element for "fine-grained" control of Upgrade table).
A Few More Links:
Upgrading a WiX generated package with major version zero
How to prevent Wix from installing an older version?
Wix UpgradeVersion
Checking for Oldies
UPDATE:
Unable to remove previous versions of MSI. Multiple entry's show up in control panel
WIX does not uninstall older version (potential causes of failed major upgrade)

Wix: Feature Condition on Property set by Custom Action

In my WIX setup package I have a feature that contains merge module and must be installed conditionally. The condition should be evaluated using property set by custom action. Here's how this looks in my WXS:
<Directory Id="INSTALLLOCATION" Name="testSetup">
<Merge Id="mergeA" Language="1033" SourceFile="test.msm" DiskId="1" />
</Directory>
<InstallExecuteSequence>
<Custom Action="find" Before="CostInitialize">Not Installed</Custom>
</InstallExecuteSequence>
<CustomAction Id="find" Return="check" BinaryKey="script" VBScriptCall="findA" />
<Binary Id="script" SourceFile="script.vbs" />
Since level=0 disables the feature I've put NOT to install only if the path exists.
<Feature Id="productFeatA" Title="featA" Level="1">
<Condition Level="0"><![CDATA[NOT pathA]]></Condition>
<MergeRef Id="mergeA" />
</Feature>
And the simple test VBS script:
Function findA
Session.Property("pathA") = "test"
End Function
So using properties that are set via custom action I cannot get feature conditions to work. Any idea what I'm doing wrong here?
Your custom action is currently only scheduled to run in the InstallExecuteSequence. If your install runs through the InstallUISequence then the Feature will still get enabled. The InstallUISequence is unless you explicitly specify to run the install 'quietly'.
Fortunately, the fix is easy. Add the following as a peer of the InstallExecuteSequence:
<InstallUISequence>
<Custom Action="find" Before="CostInitialize">Not Installed</Custom>
</InstallUISequence>

Can't get Wix custom action to work in Votive/VS2010

Help! I need to execute a managed custom action in my Wix 3.5 setup project and no matter what I've tried I can't get it to work.
I'm using the Votive integration in Visual Studio 2010. My Wix Product.wxs file is basically unchanged from the visual studio template except a few text changes:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="666ffc07-90b2-4608-a9f0-a0cc879f2ad0" Name="Product Name" Language="1033" Version="5.5.0002" Manufacturer="TiGra Astronomy" UpgradeCode="d17a5991-b404-4095-9e93-08d2db984cfd">
<Package InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Directory Name">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<!-- <Component Id="ProductComponent" Guid="3ea5ade7-9b7b-40da-9e83-13e066a000ef"> -->
<!-- TODO: Insert files, registry keys, and other resources here. -->
<!-- </Component> -->
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="ASCOM Driver" Level="1">
<!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->
<!-- <ComponentRef Id="ProductComponent" /> -->
<!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
<ComponentGroupRef Id="Product.Generated" />
</Feature>
</Product>
I have set a reference to my managed custom action project, set the HARVEST property to true. The project is called WIX.CustomActions and produces WIX.CustomActions.dll and WIX.CustomActions.CA.dll
I see that Wix is processing the reference during build and the WIX.CustomActions.dll assembly shows up in the Binary table in the final setup project, but the WIX.CustomActions.CA.dll does not.
I have a CustomActions.wxs that should package and invoke the custom action:
<?xml version="1.0" encoding="UTF-8" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Binary Id="DriverRegistrationCA" SourceFile="$(var.WIX.CustomActions.TargetDir)\$(var.WIX.CustomActions.TargetName).CA.dll" />
<CustomAction Id="RegisterDriver" BinaryKey="DriverRegistrationCA" DllEntry="RegisterAscomDriver" Execute="deferred" Return="check" />
<CustomAction Id="UnregisterDriver" BinaryKey="DriverRegistrationCA" DllEntry="UnregisterAscomDriver" Execute="immediate" Return="check" />
<InstallExecuteSequence>
<Custom Action="RegisterDriver" After="InstallFinalize" />
<Custom Action="UnregisterDriver" Before="RemoveFiles" />
</InstallExecuteSequence>
</Fragment>
</Wix>
I've looked at various 'howto' sources on the interweb and they are at best confusing, with contradictory advice. As I understand it, the WIX.CustomActions.CA.dll file is an unmanaged dll that loads the .NET framework and passes control to the 'real' managed custom action. However, the WIX.CustomActions.CA.dll does not get packaged in my MSI file. I've followed examples as best I can but I can't see what's wrong.
Please, has anyone got this working in Votive? Can you give me an actual working example?
You need a reference (e.g., CustomActionRef) from your product to the fragment; otherwise, it's discarded by the smart linker.
Following on from Bob Arnson's suggestion, I added the following two lines near the top of my Product.wxs file:
<CustomActionRef Id="RegisterDriver"/>
<CustomActionRef Id="UnregisterDriver"/>
That seems to have done the trick. Orca now shows that I have a Binary table, containing my CA dll, and a CustomAction entry in InstallExecuteSequence.
None of the examples I found on the web mentioned this requirement. I guess people were just recycling received wisdom with little or no understanding. So here is the answer, thanks to Bob!

Launch after install, with no UI?

How do I launch my application after install with no UI (or in quiet mode)? Thanks!
I had a installer with UI which has an option to run after install. Now I want my application to updates itself by downloading and running the new version of installer in quiet mode, but after updating done, it won't launch again.
From the msdn topic on sequencing custom actions:
As in the case of standard actions,
custom actions that are scheduled in
the InstallUISequence or
AdminUISequence run only if the
internal user interface is set to the
full level.
So I guess your custom action is scheduled in a UI sequence, not in InstallExecuteSequence. Try scheduling your custom action in the InstallExecuteSequence like this:
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFiles'/>
</InstallExecuteSequence>
where "LaunchApplication" should be replaced by the Id of your CustomAction element.
edit: I looked at the instructions that you followed, and I don't see the custom action for launching the application being scheduled in any sequence. It is only triggered from a UI action (clicking the Finish button). This explains why it is never executed during a silent install.
edit: full sample (it's a bit sloppy as it also tries to execute the custom action on uninstall, repair etc. but for some reason I couldn't get the "NOT Installed" condition to work)
<?xml version='1.0' encoding='utf-8'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product
Name='ProductName'
Id='*'
Language='1033'
Version='0.0.1'
Manufacturer='ManufacturerName' >
<Package
Keywords='Installer'
Description='Launch application demo'
Manufacturer='ManufactererName'
InstallerVersion='100'
Languages='1033'
Compressed='yes'
SummaryCodepage='1252'/>
<Media Id='1' Cabinet='test.cab' EmbedCab='yes'/>
<Directory Id='TARGETDIR' Name="SourceDir">
<Directory Id='ProgramFilesFolder'>
<Directory Id='TestFolder' Name='Test' >
<Component Id="ExeComponent" Guid="*">
<File Id="ExeFile" Source="c:\windows\notepad.exe" />
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id='Complete'
Display='expand'
Level='1'
Title='Test'
Description='Test'>
<ComponentRef Id="ExeComponent" />
</Feature>
<InstallExecuteSequence>
<Custom Action='LaunchInstalledExe' After='InstallFinalize'/>
</InstallExecuteSequence>
<CustomAction Id="LaunchInstalledExe"
FileKey="ExeFile"
ExeCommand=""
Execute="immediate"
Impersonate="yes"
Return="asyncNoWait" />
</Product>
</Wix>
In my final solution I used two properties, one for UI (LAUNCH_APP_ON_EXIT), one for command line arguments (UPDATING_AUTOMATICALLY).
I have to do this because if I run the CustomAction after InstallFinalize in full UI mode, the application would start before you click the "Finish" button.
Now I can call setup.exe /qn UPDATING_AUTOMATICALLY=1 in my program to update.
Here is it all:
<Property Id="LAUNCH_APP_ON_EXIT" Value="1" />
<Property Id="UPDATING_AUTOMATICALLY" Value ="0" />
<CustomAction Id="LaunchApplication" FileKey="mainExecutableFile" ExeCommand="" Execute="immediate" Impersonate="yes" Return="asyncNoWait" />
<UI>
<!-- explainations: http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/ -->
<UIRef Id="MyWixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText"/>
<Publish Dialog="MyExitDialog" Control="Finish" Order="1" Event="DoAction" Value="LaunchApplication">LAUNCH_APP_ON_EXIT</Publish>
</UI>
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFinalize'>UPDATING_AUTOMATICALLY = 1</Custom>
</InstallExecuteSequence>
I would assume that you are launching your app from a custom action, which is triggered through a property bound to the checkbox. If that is the case, you can try specifying that property as a command line argument to setup.exe. Say, if your custom action is bound to the MSI property LAUNCH_NEW_VERSION, you can call setup.exe like this:
setup.exe /q LAUNCH_NEW_VERSION=1
The standard setup bootstrapper should pass that property/value to the MSI engine. If it doesn't, you might consider invoking the .msi directly instead of calling the bootstrapper exe to run your installer.
This is the approach I took.
<Property Id="WixShellExecTarget" Value="[#(the id of your exe here)]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
This will execute which ever file id you enter in the Value. The [# ] is needed. I used this and ran it via the UI but you should be able to call this custom action anywhere and it work.

uninstall using Wix on GINA causes login failure

Problem: After uninstalling a replacement GINA I get logged off immediately after logging on if I use the WIX 3.0 installer.
I have a replacement login process (GINA) for windows XP.
It consists of a single file placed in the system directory
C:\windows\system32\NewGina.dll
and a registry entry
(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\GinaDLL=NewGina.dll)
and I have no trouble manually installing it, running it, manually uninstalling it and logging in normally.
I can also create an installer using the Microsoft installer package in VS2008 and install, login, uninstall, login still works properly.
The problem I have is when I use the Wix installer, and I install, login, uninstall, and login, I get logged out immediately after login. After immediate logout, I was able to connect a remote regedit and dump the registry. I tried diffing before and after registries and I tried process monitor hoping to discover what the Wix installer was doing but the actions and changes (about 35,000) were a bit extensive to analyze. The registry line (listed above) was gone and windows should revert to the original msgina.dll
Since the rest of the project uses the Wix Installer, I'm hoping to use it.
Any ideas on how to get this to work and avoid the auto logoff?
Thanks
APB
My Wix script looks like
<Package InstallerVersion="200" Compressed="yes" />
<Condition Message="This application is only supported on Windows XP">
<![CDATA[(VersionNT = 501)]]>
</Condition>
<InstallExecuteSequence>
<ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>
<Media Id="1" Cabinet="NewGina.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="SystemFolder">
<Component Id="NewGina" Guid="cdbdfbe9-8137-4305-98cb-a05618ea0ade" >
<File Source="..\NewGina\Release\NewGina.dll" Checksum="yes" />
</Component>
<Component Id="RegistryEntries" Guid="cdbdfbe9-8137-4305-98cb-a05618ea0adf" >
<RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="GinaDLL" Value="NewGina.dll" />
</RegistryKey>
</Component>
</Directory>
</Directory>
<Feature Id="NewGina" Title="NewGina" Level="1" >
<ComponentRef Id="NewGina" />
<ComponentRef Id="RegistryEntries" />
</Feature>
This line is a little disturbing:
<RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" Action="createAndRemoveOnUninstall">
If my memory serves correctly that says create the Winlogon key during install (probably a noop) then remove the entire Winlogon key during uninstall. In you dump can you see if that registry key exists any longer? If my memory is correct, it might be all gone.
The correct authoring in any case, would be to just remove the RegistryKey/#Action attribute. You just want the RegistryValue installed and uninstalled. No special actions necessary.

Resources