sitio - WiX[#filekey] no se está resolviendo y puede utilizarse como ruta en una CustomAction gestionada
verificar propiedad en wix (2)
Tengo un problema con el uso de CustomAction diferida, donde el parámetro se pasa como una referencia de identificación de archivo en el estilo [# file.Product.exe.config]:
<Component Id="comp.Product.exe.config"
Guid="{966DA007-E3F0-4BFE-94ED-63A66F82CA58}"
Win64="$(var.Win64)">
<File Id="file.Product.exe.config"
Name="Product.exe.config"
Source="$(var.SourcePath)/Product.exe.config"
KeyPath="yes" />
</Component>
Luego tengo una propiedad llamada ConfigurationFile que luego se transfiere a la acción personalizada diferida de la siguiente manera:
<Property Id="ConfigurationFile"
Value="[#file.Product.exe.config]" />
Anteriormente le asigné a la propiedad ConfigurationFile Value = "[APPLICATIONROOTDIRECTORY] / Product.exe.config" que funcionó bien, pero debido a que necesitamos instalar la configuración en una carpeta diferente (la razón por la que esto tenía que hacerse es irrelevante para este tema ), Tuve que cambiarlo para resolver la ubicación del archivo de configuración desde el instalador, usando la sintaxis [#file.Product.exe.config]
.
Cuando la acción personalizada recibe el parámetro, aún está en el formato [#file.Product.exe.config]
(es decir, sin resolver) y causa muchos problemas. Estuve un poco confundido porque, según el registro, parecía que debería estar funcionando. Resulta que Session.Log(
) resuelve esta referencia de archivo, lo que resultó en que el registro "mintiera" sobre el contenido real del argumento.
He intentado diferentes enfoques para "agrupar" esta cadena, incluida session.Format()
que da como resultado InvalidHandleException, usando el registro (como se indica a continuación) y otras formas sin suerte.
using (Record formatRec = new Record(0))
{
formatRec.FormatString = p0;
return formatRec.GetString(0) // Or formatRec.ToString();
}
Hay varias acciones personalizadas proporcionadas en WiX que manejan esta convención. Sin embargo, todavía tengo que descubrir cómo lo hacen. Todavía no hay suerte cuando se sumerge en el código fuente para estas acciones personalizadas.
Los argumentos de la acción personalizada se recuperan de Session.CustomActionData
.
¿Hay una buena manera de manejar esto?
Después de algunos cabellos grises y un poco de lenguaje grosero, se me ocurrió una solución. Se basa en la respuesta de @Zachary Youngs, sin embargo, se requieren algunas modificaciones.
El uso de una acción diferida no permite el acceso a las propiedades. Al utilizar la acción como acción inmediata de tipo 51 para establecer una propiedad, la referencia de la propiedad [#filekey] permaneció intacta.
Usar la siguiente solución funciona:
<!-- Custom action to set update [ConfigurationFile] to the resolved filename -->
<CustomAction Id="SetResolvedConfigurationFile"
BinaryKey="LocusCA"
DllEntry=''SetResolvedConfigurationFile''
Return="check"
Execute="immediate" />
<!-- Set CustomActionData for MergeConfiguratioFiles custom action -->
<CustomAction Id="SetMergeConfigurationFiles"
Property="MergeConfigurationFiles"
Execute="immediate"
Value="[ConfigurationFile]" />
<!-- Merge settings from old configuration file to the one being installed -->
<CustomAction Id=''MergeConfigurationFiles''
BinaryKey="LocusCA"
DllEntry=''MergeConfigFiles''
Return="check"
Execute="commit" />
<InstallExecuteSequence>
<Custom Action="SetResolvedConfigurationFile" Before="InstallFinalize">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom>
<Custom Action="SetMergeConfigurationFiles" After="SetResolvedConfigurationFile">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom>
<Custom Action="MergeConfigurationFiles" After="SetMergeConfigurationFiles">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom>
</InstallExecuteSequence>
La acción personalizada SetResolvedConfigurationFile es la siguiente:
[CustomAction]
public static ActionResult SetResolvedConfigurationFile(Session session)
{
// Set property ResolvedConfigurationFile
try
{
session["ConfigurationFile"] = session.FormatRecord(new Record(1) { FormatString = session["ConfigurationFile"] });
}
catch (Exception ex)
{
session.Log("Unable to find configuration file for merge from property ''ConfigurationFile''): " + ex);
return ActionResult.Failure;
}
return ActionResult.Success;
}
Usando session.FormatRecord para resolver el valor actual de [ConfigurationFile], y volver a escribirlo en la propiedad, la configuración existente de mi acción personalizada funciona.
Nota: el uso del atajo para cambiar mi acción MergeConfigurationFile para ejecutar inmediatamente no funciona, ya que los archivos que necesito fusionar todavía no existen. El uso de session.FormatRecord directamente dentro de MergeConfigurationFile da como resultado una InvalidHandleException al tratar de formatear cuando Execute = "commit", y el uso de Record.ToString () o Record.GetString () simplemente devuelve la referencia [#filekey].
Necesita una acción personalizada de tipo 51 para establecer la propiedad:
<CustomAction Id="SetProductConfigPath"
Property="ConfigurationFile"
Value="[#file.Product.exe.config]"
Execute="deferred"/>
<InstallExecute>
<Custom Action="SetProductConfigPath"
Before="InstallInitialize">/>
</InstallExecute>
Es posible que necesite ajustar la programación a algo que no sea ''InstallInitialize''.
Consulte la publicación de blog de MSI a WiX, Parte 5 - Acciones personalizadas: Introducción para una lista de todos los tipos de acciones personalizadas y publicación de blog. La propiedad no existe o está vacía cuando se accede desde acción personalizada diferida para obtener una explicación detallada de las acciones personalizadas diferidas.
Espero que esto ayude.