Мне нужно, чтобы установщик удалил старый установочный каталог (если он существует), непосредственно перед тем, как установщик начнет копировать новые файлы. Эта папка содержит некоторые файлы и подпапки, созданные во время использования программы, и они не включены в программу установки. Из-за этого я создал специальное действие для этого.
Итак, немного кода. Во-первых, код пользовательского действия (ничего особенного):
[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 блокирует его) и освобождается после завершения установки. Пользовательское действие будет ждать, пока папка будет освобождена, а затем удалит ее. К сожалению, уже поздно - папка уже содержит новые файлы.
Вы знаете какой-нибудь обходной путь?