remarks net cref c# .net com inno-setup unmanaged

c# - cref - Descargar una DLL de.NET de un proceso no administrado



remarks c# (5)

Estoy extendiendo mi script Inno-Setup con el código que mejor puedo implementar en C # en una DLL administrada. Ya sé cómo exportar métodos desde una DLL administrada como funciones para usar en un proceso no administrado. Se puede hacer mediante el tejido de IL y hay herramientas para automatizar esto:

Entonces, después de exportar, puedo llamar a mis funciones desde el script de Pascal en un instalador Inno-Setup. Pero luego hay un problema: la DLL parece que ya no se puede descargar. El uso de UnloadDLL(...) Inno-Setup UnloadDLL(...) no tiene ningún efecto y el archivo permanece bloqueado hasta que se cierra el instalador. Debido a esto, la instalación espera 2 segundos y luego falla al eliminar mi archivo DLL del directorio temporal (o directorio de instalación). De hecho, realmente permanece allí hasta que alguien limpia el disco.

Sé que los ensamblajes administrados ya no se pueden descargar de un dominio de aplicación, a menos que se cierre el dominio de aplicación completo (el proceso finaliza). Pero, ¿qué significa para el proceso de host no administrado?

¿Hay una mejor manera de permitir que Inno-Setup descargue o elimine mi archivo DLL después de cargarlo y usarlo?


Como se sugiere en este Artículo del Proyecto de Código: https://www.codeproject.com/kb/threads/howtodeletecurrentprocess.aspx

llame a un cmd con argumentos como se muestra a continuación.

Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + Application.ExecutablePath);

Pero básicamente, como sugirió @Sean, asegúrese de no esperar a que cmd.exe se cierre en su script.


Como se sugiere en otras respuestas, puede iniciar un proceso separado al final de la instalación que se hará cargo de la limpieza, una vez que finalice el proceso de instalación.

Una solución simple es crear un archivo por lotes ad-hoc que se repite hasta que se pueda eliminar el archivo DLL y luego también se elimine la carpeta temporal (ahora vacía) y ella misma.

procedure DeinitializeSetup(); var FilePath: string; BatchPath: string; S: TArrayOfString; ResultCode: Integer; begin FilePath := ExpandConstant(''{tmp}/MyAssembly.dll''); if not FileExists(FilePath) then begin Log(Format(''File %s does not exist'', [FilePath])); end else begin BatchPath := ExpandConstant(''{%TEMP}/') + ''delete_'' + ExtractFileName(ExpandConstant(''{tmp}'')) + ''.bat''; SetArrayLength(S, 7); S[0] := '':loop''; S[1] := ''del "'' + FilePath + ''"''; S[2] := ''if not exist "'' + FilePath + ''" goto end''; S[3] := ''goto loop''; S[4] := '':end''; S[5] := ''rd "'' + ExpandConstant(''{tmp}'') + ''"''; S[6] := ''del "'' + BatchPath + ''"''; if not SaveStringsToFile(BatchPath, S, False) then begin Log(Format(''Error creating batch file %s to delete %s'', [BatchPath, FilePath])); end else if not Exec(BatchPath, '''', '''', SW_HIDE, ewNoWait, ResultCode) then begin Log(Format(''Error executing batch file %s to delete %s'', [BatchPath, FilePath])); end else begin Log(Format(''Executed batch file %s to delete %s'', [BatchPath, FilePath])); end; end; end;


La forma fácil de hacer lo que quiere es a través de un dominio de aplicación. Puede descargar un dominio de aplicación, pero no el inicial. Entonces, la solución es crear un nuevo dominio de aplicación, cargar su DLL administrado y luego descargar el dominio de aplicación.

AppDomain ad = AppDomain.CreateDomain("Isolate DLL"); Assembly a = ad.Load(new AssemblyName("MyManagedDll")); object d = a.CreateInstance("MyManagedDll.MyManagedClass"); Type t = d.GetType(); double result = (double)t.InvokeMember("Calculate", BindingFlags.InvokeMethod, null, d, new object[] { 1.0, 2.0 }); AppDomain.Unload(ad);

Aquí es cómo se ve el código DLL ...

namespace MyManagedDll { public class MyManagedClass { public double Calculate(double a, double b) { return a + b; } } }


Puede agregar una secuencia de comandos por lotes (en la forma de ejecutar cmd -c) para que se ejecute al final de la configuración que espera a que el archivo se elimine y lo elimine. (solo asegúrese de configurar la opción inno para que no espere a que se complete el proceso cmd)

También puede hacer que su programa instalado lo detecte y lo elimine en la primera ejecución.


Si bien no es exactamente una respuesta a su pregunta, ¿no puede simplemente marcar la DLL que se eliminará la próxima vez que se reinicie la computadora?