问题
I've seen others' questions on this matter, but I can't make it work for me. I'm trying to get used to Wix so we can migrate our vdproj's (I feel like we've taken 1 step forward and 4 steps back here...the most basic of things have become completely non-trivial with Wix...but I do see value in having a fully fledged declarative markup for building installers).
I have the following wxs in a wixproj in SharpDevelop.
Install works. Uninstall does nothing and leaves the install folder and dll in place. What's the problem?
Files.wxs:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="Client">
<Component Id="InteropDll" Guid="AD09F8B9-80A0-46E6-9E36-9618E2023D66" DiskId="1">
<File Id="Interop.dll" Name="Interop.dll" Source="..\Interop\bin\$(var.Configuration)\Interop.dll" KeyPath="yes" />
<RemoveFile Id="RemoveInterop.dll" Name="Interop.dll" On="uninstall" />
</Component>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
Setup.wxs:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Client Setup"
Language="1033"
Version="1.0.0.0"
UpgradeCode="4A88A3AD-7CB6-46FB-B2FD-F4EADE0218F8"
Manufacturer="Client Setup">
<Package Description="#Description"
Comments="Comments"
InstallerVersion="200"
Compressed="yes"/>
<!--
Source media for the installation.
Specifies a single cab file to be embedded in the installer's .msi.
-->
<Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
<!-- Installation directory and files are defined in Files.wxs -->
<Directory Id="TARGETDIR" Name="SourceDir"/>
<Feature Id="Complete"
Title="Client Setup"
Description="Client Setup"
Level="1">
<ComponentRef Id="InteropDll" />
</Feature>
<!--
Using the Wix UI library
WixUI_InstallDir does not allow the user to choose
features but adds a dialog to let the user choose a
directory where the product will be installed
-->
<Property Id="WIXUI_INSTALLDIR">INSTALLDIR</Property>
<UI Id="WixUI_InstallDir">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="InstallDir" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Property Id="ARPNOMODIFY" Value="1" />
</UI>
<UIRef Id="WixUI_Common" />
</Product>
</Wix>
回答1:
Try to change the GUID of the components which are not uninstalling. I tried the same and it worked for me. It may be because the GUID is already registered in the registry by some other product.
The cause is generally messed up component reference count in the registry - often it happens on dev-boxes during development. Can also often happen to Installshield packages due to their use of the SharedDllRefCount concept (legacy, non-MSI reference counting).
Some technical details: Change my component GUID in wix? Test on a clean virtual to verify the problem is real and not a dev-box issue. Changing component GUIDs can have repercussions (patching problems etc...).
回答2:
Make sure that no other MSI packages are keeping your components installed.
Specifically, go into Control Panel / Programs and Features, and make sure that there isn't an "old" version of your program still installed.
回答3:
Would be worth checking the following registry key to see if your files are listed. This can cause the uninstaller to ignore the components as it believes them to be shared.
HKLM\Software\Microsoft\Windows\CurrentVersion\SharedDlls
回答4:
I somehow got my project in the state where every single one of my components couldn't be uninstalled. I have no idea how. I wrote a program that will take a .wixproj file and change all of the component GUIDs to new GUIDs and that solved the issue (after I manually deleted the files). This is based off of user593287's answer.
The argument should be the path to your project file. An example of running this from the command line would be:
GuidFixer.exe MyProject.csproj
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace GuidFixer
{
public class Program
{
public static void Main(string[] args)
{
string projectFileName = args[0];
string path = Path.GetDirectoryName(projectFileName);
List<string> files = new List<string>();
XmlDocument projectDocument = new XmlDocument();
projectDocument.Load(projectFileName);
XmlNamespaceManager manager = new XmlNamespaceManager(projectDocument.NameTable);
manager.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
// Finds all of the files included in the project.
XmlNodeList nodes = projectDocument.SelectNodes("/msbld:Project/msbld:ItemGroup/msbld:Compile", manager);
foreach (XmlNode node in nodes)
{
string fileName = Path.Combine(path, node.Attributes["Include"].Value);
files.Add(fileName);
}
foreach (string fileName in files)
{
// Lets only do .wxs files
if (!Path.GetExtension(fileName).Equals(".wxs", StringComparison.CurrentCulture))
{
continue;
}
// This will only update files that aren't readonly, make sure
// you check out your files from source control before running.
FileAttributes attributes = File.GetAttributes(fileName);
if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
continue;
}
bool modified = false;
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true; // space inside tags are still lost
doc.Load(fileName);
foreach (XmlNode node in doc.GetElementsByTagName("Component"))
{
Guid guid = Guid.NewGuid();
string value = guid.ToString("B").ToUpper();
node.Attributes["Guid"].Value = value;
modified = true;
}
// Only update files that were modified, to preserve formatting.
if (modified)
{
doc.Save(fileName);
}
}
}
}
}
I made some changes to it without testing it, so good luck, it's pretty straightforward though.
回答5:
I encountered a similar problem, which appeard not to be present any more when I converted all guids into uppercase (as required in some specification for compatiblity issues). Did not test exensively whether this was really the solution to the problem. Maybe this is the same as the previous answer.
来源:https://stackoverflow.com/questions/7532863/wix-not-removing-files-on-uninstall