我需要安装程序在安装程序开始复制新文件之前删除旧的安装目录(如果存在)。此文件夹包含程序使用过程中生成的一些文件和子文件夹,它们不包含在安装程序中。因此,我创建了自定义操作来执行此操作。
所以,一些代码。首先,自定义操作代码(没什么特别的):
[CustomAction]
public static ActionResult RemoveOldDatabase(Session session)
{
bool removeDatabase = session.CustomActionData["RemoveDatabase"] == "true";
string installDir = session.CustomActionData["InstallDir"];
if (removeDatabase)
{
try
{
Directory.Delete(installDir, true);
}
catch (Exception ex)
{
session.Log(ex.StackTrace);
}
}
return ActionResult.Success;
}
和 wix 代码(它定义了自定义操作调用):
<CustomAction Id="actionCheckServerName" BinaryKey="actionBinary" DllEntry="CheckServerName" Execute="immediate" Return="check" />
<CustomAction Id="actionInstall" BinaryKey="actionBinary" DllEntry="Install" Execute="deferred" HideTarget="no" Impersonate ="no" Return="check"/>
<CustomAction Id="actionUninstall" BinaryKey="actionBinary" DllEntry="Uninstall" Execute="deferred" HideTarget="no" Impersonate ="no" Return="check"/>
<CustomAction Id="actionRemoveOldDatabase" BinaryKey="actionBinary" DllEntry="RemoveOldDatabase" Execute="deferred" HideTarget="no" Impersonate ="no" Return="ignore"/>
<CustomAction Id="actionGetNetworkComputers" BinaryKey="actionBinary" DllEntry="GetNetworkComputers" Execute="immediate" Return="check"/>
<CustomAction Id="SetInstallParameters" Return="check" Property="actionInstall" Value="InstallDir=[INSTALLDIR];ServerName=[SERVER_LIST];InstallMode=[SETUP_MODE];Single=[single];RemoveDatabase=[REMOVE_DATABASE]" />
<CustomAction Id="SetUninstallParameters" Return="check" Property="actionUninstsall" Value="UnInstallDir=[INSTALLDIR];ServerName=[SERVER_LIST];UnInstallMode=[INSTALL_MODE]" />
<CustomAction Id="SetRemoveOldDatabaseParameters" Return="check" Property="actionRemoveOldDatabase" Value="InstallDir=[INSTALLDIR];RemoveDatabase=[REMOVE_DATABASE]" />
<InstallExecuteSequence>
<Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND</Custom>
<Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
<Custom Action="SetRemoveOldDatabaseParameters" Before="ProcessComponents"/>
<Custom Action="actionRemoveOldDatabase" After="SetRemoveOldDatabaseParameters">NOT Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
<Custom Action="SetInstallParameters" Before="actionInstall"/>
<Custom Action="SetUninstallParameters" Before="RemoveFiles">Installed AND NOT REINSTALL AND NOT UPGRADINGPRODUCTCODE</Custom>
<Custom Action="actionInstall" Before="InstallFinalize">NOT Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
<Custom Action="actionUninstall" After="SetUninstallParameters">Installed AND NOT REINSTALL AND NOT UPGRADINGPRODUCTCODE</Custom>
</InstallExecuteSequence>
有什么问题?如您所见,应该在安装程序开始复制新文件之前触发 actionRemoveOldDatabase(参数已由 SetRemoveOldDatabaseParameters 设置)。所以 - 只有旧文件应该被删除 - 但这不会发生。如果我这样做,操作actionRemoveOldDatabase,安装目录将在安装程序复制新文件后被删除。因此,安装程序复制的所有新文件都将被删除。
我不明白为什么?如何仅删除旧的、已经存在的文件夹以及为什么我的自定义操作会删除所有复制的文件?
[编辑] 看来我已经知道原因了。在这种情况下,Install Dir 正在使用中(可能是 Windows 安装程序将其锁定)并且在安装结束后被释放。自定义操作将等到文件夹被释放,然后将其删除。不幸的是,为时已晚 - 文件夹已包含新文件。
你知道任何解决方法吗?