Wix在卸载时未删除文件

34

我看到了其他人关于这个问题的提问,但是我无法让它对我起作用。我正在尝试适应Wix,以便我们可以迁移我们的vdproj(感觉我们在这里向前迈了1步,后退了4步...最基本的事情已经变得完全不容易处理了...但我确实看到了在构建安装程序时具有完全的声明性标记语言的价值)。

我在SharpDevelop中的wixproj中有以下的wxs。

安装是成功的。卸载没有任何作用,仍然保留安装文件夹和dll。什么是问题所在?

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>

配置看起来没问题。你尝试创建详细的卸载日志来查看发生了什么吗?http://setupanddeployment.com/debugging/msi-log。搜索InstallValidate和RemoveFiles操作,看看它们做了什么。 - rmrrm
不确定为什么,但这似乎是随机开始工作的... - Jeff
6个回答

57
尝试更改未卸载的组件的GUID。我尝试了相同的方法,并且它对我起作用了。可能是因为GUID已经被其他产品在注册表中注册。
引起问题的通常是注册表中混乱的组件引用计数 - 在开发过程中通常会在开发环境中发生。由于使用SharedDllRefCount概念(遗留的、非MSI引用计数),在Installshield包中也经常会发生这种情况。
一些技术细节:在wix中更改我的组件GUID? 在干净的虚拟机上测试以验证问题是否真实存在而不是开发环境问题。更改组件GUID可能会产生后果(补丁问题等)。

2
每次进行单独的构建时,您是否需要生成新的Guid以确保卸载工作正常? - TheWommies
这个解决方案对我来说比我尝试过的其他很多方案都有效。谢谢! - gab
如果您正在使用heat.exe/Harvest[http://wixtoolset.org/documentation/manual/v3/overview/heat.html] WIX工具来生成组件清单,则可能需要查看控制组件GUID定义的“-ag”和“-gg”开关。使用“-ag”将基于文件位置自动生成一致的GUID,但是“-gg”似乎每次都会生成新的GUID。 - Armin Sadeghi
我有一个有效的GUID,但我感觉在之前我还在调试时,GUID可能会与某个先前版本的安装程序搞乱了。无论如何,只使用“*”就可以很好地解决问题。 - neminem
2
就像neminem所说的那样,GUID可能会在频繁的设置构建中出现问题,这些构建可能以某种方式失败。更改GUID会断开与错误链接的联系,并且在大多数情况下都能正常工作。为了确保补丁程序可以正确运行,最好也更改密钥路径的文件名(如果尝试)。这是GUID /密钥路径概念的快速解释,以及何时应更改GUID而不是:https://dev59.com/l3M_5IYBdhLWcg3wXx_Z#1422121 - Stein Åsmul
显示剩余2条评论

9

确保没有其他MSI软件包保留您的组件安装。

具体而言,请进入“控制面板/程序和功能”并确保不存在“旧”的程序版本仍在安装中。


5

值得检查以下注册表键,看看你的文件是否列出。这可能会导致卸载程序忽略组件,因为它认为它们是共享的。

HKLM\Software\Microsoft\Windows\CurrentVersion\SharedDlls

1
我们发现我们的DLL文件就在这个SharedDlls注册表位置中。我们为我们的DLL文件组件使用了SharedDllRefCount="yes"。我们将其更改为"no",并从该注册表键中删除了我们的DLL条目,现在在卸载时它正确地删除了该DLL文件! - Josh P

4
我不知道怎么回事,我的项目每个组件都无法卸载。我写了一个程序,可以将.wixproj文件的所有组件GUID更改为新的GUID,并解决了这个问题(在我手动删除文件后)。这是基于user593287的答案。
参数应该是您项目文件的路径。从命令行运行的示例如下: 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);
                }
            }
        }        
    }
}

我进行了一些更改,但没有经过测试,所以祝你好运,但它非常简单明了。


很有帮助。我会为未来的用户记录下来,虽然它不能处理*.wxs作为文件参数,但如果你明确地拼写出文件名,它是可以工作的。(使用*.wxs会导致“路径中存在非法字符”的System.IO.Path异常。) - Pauli Price

1

我遇到了类似的问题,当我把所有的GUID转换成大写字母时(在某些规范中为了兼容性要求),这个问题似乎不再存在。没有进行过充分的测试以确定这是否真正是解决问题的方法。也许这与之前的答案相同。


0

我曾经遇到过类似的问题。我按照上述步骤进行了操作,但是文件仍然无法卸载,而日志也没有显示任何错误信息。

直到我移除了

<!--DEBUG: use C:\Laser-Wix\ as base path for now-->
<SetDirectory Id="LaserDir" Value="[WindowsVolume]Laser-WIX" />

从我的 wxs 文件中(我用它来将安装位置重新定向到另一个文件夹以进行开发操作),实际上已经删除了这些文件。

希望这能对某些人有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接