wix - subir - Agregar una nueva acción personalizada a un proyecto evita que se ejecute una acción personalizada existente
como agregar una nueva entrada en wix (3)
Esto es realmente bastante extraño, pero después de mucho tiempo buscando respuestas y probando muchas cosas diferentes intenté cambiar el nombre de la nueva CA de SetApplicationAutoStart a ConfigureApplicationAutoStart y eso dio como resultado que SetAppPoolLoadUserProfileTrue comenzara a funcionar correctamente otra vez
Tengo un proyecto de Acción personalizada que tiene varias CA utilizadas por los instaladores que crea mi empresa, algunas de las cuales se usan para manipular el IIs7 a través de la API de Administración de Microsoft.Web.
Agregué una nueva acción personalizada llamada SetApplicationAutoStart la clase que contiene las CA relacionadas con IIs. Esta acción personalizada se usa para establecer el atributo autoStart que fuerza a los II a precargar e iniciar los servicios de WCF para que el tiempo de respuesta inicial sea más corto.
Después de agregar esta acción, una CA existente llamada SetAppPoolLoadUserProfileTrue dejó de funcionar. Esta CA obliga a que la configuración en un sitio sea verdadera, incluso si el sitio predeterminado en la computadora se ha modificado para que esta configuración sea falsa, por lo que realmente necesitamos que funcione.
Los archivos de registro contienen las siguientes líneas cuando falla la acción.
MSI (s) (A0:18) [15:02:43:639]: Executing op: ActionStart(Name=SetAppPoolLoadUserProfileTrue,,)
Action 15:02:43: SetAppPoolLoadUserProfileTrue.
MSI (s) (A0:18) [15:02:43:641]: Executing op: CustomActionSchedule(Action=SetAppPoolLoadUserProfileTrue,ActionType=3073,Source=BinaryData,Target=SetAppPoolLoadUserProfileTrue,CustomActionData=AppPoolName=xxxxx)
MSI (s) (A0:18) [15:02:43:670]: Creating MSIHANDLE (377) of type 790536 for thread 50712
MSI (s) (A0:C8) [15:02:43:670]: Invoking remote custom action. DLL: C:/Windows/Installer/MSIBD82.tmp, Entrypoint: SetAppPoolLoadUserProfileTrue
CustomAction SetAppPoolLoadUserProfileTrue returned actual error code 1154 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (A0:C8) [15:02:43:673]: Closing MSIHANDLE (377) of type 790536 for thread 50712
MSI (s) (A0:18) [15:02:43:674]: Note: 1: 1723 2: SetAppPoolLoadUserProfileTrue 3: SetAppPoolLoadUserProfileTrue 4: C:/Windows/Installer/MSIBD82.tmp
Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. Action SetAppPoolLoadUserProfileTrue, entry: SetAppPoolLoadUserProfileTrue, library: C:/Windows/Installer/MSIBD82.tmp
MSI (s) (A0:18) [15:20:25:139]: Product: xxxxxxx -- Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. Action SetAppPoolLoadUserProfileTrue, entry: SetAppPoolLoadUserProfileTrue, library: C:/Windows/Installer/MSIBD82.tmp
Action ended 15:20:25: InstallFinalize. Return value 3.
Esto parece un problema al extraer el punto PE del PE para esta acción. Todas las demás CA del binario funcionan correctamente, incluida la nueva.
Experimenté exactamente el mismo síntoma que describes. Parece que hay un problema con el conjunto de herramientas de WiX. Mi versión de WiX tolset es 3.8, y también tuve una acción personalizada, que no se ejecutaría, y cambiar su nombre solucionó el problema. El compilador SFX simplemente compila el DLL roto sin ninguna indicación de un problema. Lo que empeora las cosas es que en mi caso esta fue una función que se suponía que se ejecutaría en la desinstalación con Result = "ignore", por lo que ni siquiera tendría ninguna indicación inmediata de que hay un problema después de ejecutar el instalador real.
Traté de experimentar para entender cuál es exactamente el problema con el nombre, y no encontré ninguna explicación satisfactoria. Parece que no importa dónde está en el código fuente la función ofensiva, qué es alfabéticamente (por ejemplo, las funciones tienen éxito que están antes y después alfabéticamente). Cargando DLL en depends.exe muestra que hay una exportación, pero al intentar rundll32 falla al encontrar esa exportación. Cambiar su nombre soluciona el problema. Además, a veces puede agregar otra función, y la falla tendrá éxito, pero la que acaba de agregar falla en su lugar.
Esto es lo que hice para solucionar el problema: escribí un programa C ++ que carga la acción personalizada compilada y verifica la exportación. Luego escribí una prueba de unidad, que verificó todas las exportaciones en acción personalizada. Obviamente, esto no soluciona el problema, pero al menos tendrá una falla en la prueba de unidad y sabrá que su instalador está roto. Aquí está el código de C ++ si estás interesado:
typedef int(__stdcall *CustomActionProc)(HANDLE);
int _tmain(int argc, _TCHAR* argv[])
{
if (argc != 3)
{
_tprintf(_T("Parameters: DLL, EntryPoint/n"));
return 1;
}
LPCTSTR dllName = argv[1];
LPCTSTR entryPoint = argv[2];
HMODULE hLib = LoadLibrary(dllName);
if (hLib == NULL)
{
_tprintf(_T("Error loading %s/n"), dllName);
return 1;
}
CustomActionProc procAddress =
(CustomActionProc) GetProcAddress(hLib, CStringA(entryPoint));
if (procAddress == NULL)
{
_tprintf(_T("Error locating entrypoint %s/n"), entryPoint);
return 1;
}
return 0;
}
Y la prueba de la unidad es:
[TestMethod]
public void TestCustomActionCanBeInvoked()
{
var asm1 = typeof(MyCustomActionsClass).Assembly;
var methods = asm1.GetTypes().SelectMany(t =>
t.GetMethods().Where(m => m.GetCustomAttributes(false)
.Where(a => a.GetType().Name == "CustomActionAttribute").Any()));
var binFolder = (new FileInfo(this.GetType().Assembly.Location)).DirectoryName;
var customActionsSfx = Path.Combine(binFolder, "MyCustomAction.CA.dll");
var testMsiExport = Path.Combine(binFolder, "TestMsiExport.exe");
foreach (var m in methods)
{
Trace.WriteLine("Method Name: " + m.Name);
var p = Process.Start(new ProcessStartInfo()
{
FileName = testMsiExport,
Arguments = "/"" + customActionsSfx + "/" " + m.Name,
UseShellExecute = false,
RedirectStandardOutput = true,
});
p.OutputDataReceived += (s, d) => Trace.WriteLine(d.Data);
p.BeginOutputReadLine();
p.WaitForExit();
if (p.ExitCode != 0)
{
Assert.Fail("Bad Sfx export detected! Export name: " + m.Name);
}
}
}
Espero que esto ayude a alguien en mi situación. Fue un día muy frustrante tratando de aclarar esto.
A mi me pasó lo mismo. "Galets" ya estaba apuntando en la dirección correcta, poniéndome en el buen camino (no hay representante para votar, lo siento).
Version corta:
MakeSfxCA produce dlls nativos que no siguen la especificación PE / COFF que conduce al comportamiento observado.
Versión larga:
- Construya una CA, por ejemplo, "HavocAction", que tenga tres puntos de entrada exportados (es decir, marcado con el atributo "CustomAction"), llamado "HavocEntryPointa", "HavocEntryPointB", "HavocZappEntryPoint" (tenga en cuenta la ortografía exacta). Los métodos pueden simplemente devolver "ActionResult.Success".
- Vamos con configuraciones simples, a) invocando solo "HavocEntryPointa", b) invocando solo "HavocEntryPointB"
- ==> La configuración "a)" funcionará, la configuración "b)" fallará
- Descomenta el atributo "CustomAction" en "HavocZappEntryPoint" y el comportamiento se invierte, es decir,
- ==> La configuración "a)" fallará, la configuración "b)" funcionará
Análisis mas extenso
Cuando vuelca el archivo CA.dll envuelto con
dumpbin / Exportaciones HavocAction.CA.dll
obtienes algo así como (extracto)
125 7C 00003A36
126 7D 00003A4C HavocEntryPointa
127 7E 00003A62 HavocEntryPointB
128 7F 00003A78 HavocZappEntryPoint
129 80 000042FC zzzEmbeddedUIHandler
130 81 000043B8 zzzInitializeEmbeddedUI
131 82 0000467F zzzShutdownEmbeddedUI
132 83 00003AA5 zzzzInvokeManagedCustomActionOutOfProcW
Esto es incorrecto (busque "pecoff_v83.docx", consulte las funciones exportadas de DLL no ordenadas léxicamente? ). Se supone que las entradas están ordenadas (por ASCII) para realizar una búsqueda binaria cuando se cargan métodos de la dll (las entradas "HavocEntryPointa" y "HavocEntryPointB" se intercambian).
Mi conjetura es que al cargar el código de la dll falla la búsqueda binaria, lo que da como resultado el error. Debido a la naturaleza de una búsqueda binaria, la eliminación de "HavocZappEntryPoint" invierte el efecto.
Observación con respecto a OP
Kjartan utilizó por primera vez "SetApplicationAutoStart" y "SetAppPoolLoadUserProfileTrue", que no se exportó correctamente a CA.dll debido a un pedido incorrecto; la letra mayúscula "P" aparece antes de la minúscula "l", pero esto fue intercambiado por MakeSfxCA. Su última opción, "ConfigureApplicationAutoStart" y "SetAppPoolLoadUserProfileTrue", se ordena conforme a la especificación PE / COFF.
PD: Esto es http://wixtoolset.org/issues/4502 ahora.
Actualizar
PPS: a partir de la versión WiX 3.9 RC3, se incluye la corrección de errores para este problema; todo funciona como se espera