Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Modo Correcto de Cerrar .Dll (https://www.clubdelphi.com/foros/showthread.php?t=65075)

Robin1 18-11-2009 17:35:55

Modo Correcto de Cerrar .Dll
 
Hola a todos, y un gran saludo.

El tema que me ocupa hoy, es el siguiente.

En días pasados, he estado trabajando en el desarrollo de una Dll (Se trata de un formulario en Delphi 7, con algunos controles WebBrowser, para ser compartido, con una aplicación hecha también en Delphi 7).

De este modo, mi .Dll la he escrito sin inconveniente alguno.

El llamado a la .dll desde el formulario principal, se hace perfectamente, pero he notado esto:

1) Si solo abro la aplicación principal, y trabajo con ella, y luego la cierro, sin haber llamado la Dll, todo va de maravilla.

2) Si abro la aplicación principal, y llamo la .Dll, esta carga, y puedo luego cerrarla, pero, a la hora de cerrar la aplicación principal, inicialmente genera un error en código exadecimal, para luego abrirse una ventana que genera un error 216 en tiempo de ejecución.

Haciendo pruebas, descubri, que si en el evento "OnClose" del Form principal agregaba estas lineas:

Código:

Application.Destroy;
 Exit;

Ya no se generaba dicho error, pero al revisar en el administrador de tareas de Windows, la aplicación sigue corriendo en memoria...

He leído que se trata en algunos casos de un virus, pero en mi caso, he probado en otra de mis máquinas, que recién acababa de formatear, para verificar que no se tratase de un virus.

¿Que puede ser?

Mil gracias por la ayuda, y un gran abrazo

Julián

rgstuamigo 18-11-2009 21:29:06

Bueno :rolleyes: pienso que esas lineas de codigo que mencionas son innecesaria.;).
Por otro lado mira este hilo.;).
Saludos...:)

gerardus 19-11-2009 09:24:23

Si la DLL usa cualquier parte de la VCL (Forms, reports, componentes, etc...) como parece ser que es tu caso, tanto la DLL como la aplicación que la llame tienen que estar enlazadas con la opción "Build with runtime packages". (Compiler | Options | packages | Checkear "Build with runtime packages")
De lo contrario, la aplicación y la DLL tendrán cada una su copia de la VCL, lo que suele dar estos problemas. Algunas variables globales como Application o Screen existen dos veces, etc...
En la lista de packages debes tener todos los packages que van a usar la aplicación y la DLL.
(De hecho, un runtime package no es más que una DLL con algunas funciones de registro propias de Delphi).

Cordialmente,

Gerard.

JosepGA 19-11-2009 09:27:37

hola,

te pongo un ejemplo resumido del fuente tal y como yo lo hago, mis primeras experiencias con Dlls me llevaron a averiguar que hay dos maneras de cargarlas, con la aplicación al iniciar o por requerimiento, yo lo hago de la segunda manera:

(***** unit FUNCION CARGA DLLS, LA CARGA Y LIBERA DE MEMORIA ******)
Código Delphi [-]

unit FuncionCargaDlls;

interface

Uses
  tGlobales, { Declaración para el Tipo de Variables Globales de la Aplicación en las Dlls }
  Globales, { Variables Globales de la Aplicación }
  AsignacionGlobales,

  SysUtils, StdCtrls, Windows, Forms, Classes, SQLExpr, DBClient, SimpleDS, Controls,

  CRSQLConnection;

Type

  tProcedimientoCargar = Procedure( vGlobales : tVariablesGlobales;
                                    Const tSQLConexionGeneral : tCRSQLConnection ); far;

  EDLLCargaError = Class( Exception );


  Procedure CargarRecursoDllExplicitamente( NombreDll : String;
                                            NombreProcedimiento : String;
                                            Const tSQLConexionGeneral, tSQLConexionGestion, tSQLConexionContabilidad : tCRSQLConnection );

implementation

Procedure CargarRecursoDllExplicitamente( NombreDll : String;
                                          NombreProcedimiento : String;
                                          Const tSQLConexionGeneral : tCRSQLConnection );
Var
  PunteroLibreria : tHandle;
  Procedimiento : tProcedimientoCargar;
Begin
  PunteroLibreria := LoadLibrary( PChar( NombreDll + '.DLL' ) );
  Try
    If PunteroLibreria = 0 Then
      Begin
        Raise EDLLCargaError.Create( 'Imposible Cargar la DLL ' + NombreDll );
      End
    Else
      Begin
        @Procedimiento := GetProcAddress( PunteroLibreria, PChar( NombreProcedimiento ) );
        If ( @Procedimiento = Nil ) Then
          RaiseLastWin32Error
        Else
          Procedimiento( VariablesGlobales,
                         tSQLConexionGeneral );
      End;
  Finally
    FreeLibrary( PunteroLibreria ); { Descarga la Libreria de Memoria }
  End;
End;


(****** APLICACION PRINCIPAL *******)

Código Delphi [-]

unit FuncionCargaDlls;

interface

Uses
  tGlobales, { Declaración para el Tipo de Variables Globales de la Aplicación en las Dlls }
  Globales, { Variables Globales de la Aplicación }
  AsignacionGlobales,

  SysUtils, StdCtrls, Windows, Forms, Classes, SQLExpr, DBClient, SimpleDS, Controls,

  CRSQLConnection;

type
  TFormMenu = class(TForm)
    ..
  private
    ..
  public
    ..

  end;

var
  FormMenu: TFormMenu;

implementation

Uses
  FuncionCargaDlls;

procedure TFormMenu.EjecutarOpcionClick(Sender: TObject);
begin
  CargarRecursoDllExplicitamente( 'DllEdiciones', 'NombreOpcionExportadaEjecutar1',
                                  FormDMMenuPrincipal.tSQLConexionGeneral );
end;

end.



(******** DLL ejecutada - source proyecto *****)

Código Delphi [-]
 
 Library DllEdiciones;

uses
  AsignarConfiguracionAplicacion,
  DeclaracionesOpcionesExportadas;

Exports
  NombreOpcionExportadaEjecutar1,
  NombreOpcionExportadaEjecutar2,
  ..
  NombreOpcionExportadaEjecutarn;

{$R *.RES}

Begin
  AsignarLaConfiguracionDeLasAplicaciones; // Inicializar configuraciones por defecto o lo que sea
End.



(** DLL ejecutada - fuente "DeclaracionesOpcionesExportadas" **)

Código Delphi [-]
  
  unit DeclaracionesOpcionesExportadas;

interface

Uses
  Forms,
  SQLExpr,
  SysUtils,
  CRSQLConnection,
  
  ModuloDatosEdiciones,
  tGlobales,
  Globales,
  AsignacionGlobales,

  FuenteFormularioEjecutar1,
  FuenteFormularioEjecutar2,
  ..
  FuenteFormularioEjecutarn;

procedure NombreOpcionExportadaEjecutar1( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;
procedure NombreOpcionExportadaEjecutar2( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;
..
procedure NombreOpcionExportadaEjecutarn( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;

implementation

procedure NombreOpcionExportadaEjecutar1( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;
Begin
  AsignacionValoresGlobales( vGlobales );

  ActivarConexionesModuloDeDatos( tSQLConexionGeneral );

  Application.CreateForm( tFormFuenteFormularioEjecutar1, FormFuenteFormularioEjecutar1 );
  With FormFuenteFormularioEjecutar1 do
    Try
      ShowModal;
    Finally
      Free;
    End;

  DesactivarConexionesModuloDeDatos( tSQLConexionGeneral );
End;

procedure NombreOpcionExportadaEjecutar2( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;
Begin
  AsignacionValoresGlobales( vGlobales );

  ActivarConexionesModuloDeDatos( tSQLConexionGeneral );

  Application.CreateForm( tFormFuenteFormularioEjecutar2, FormFuenteFormularioEjecutar2 );
  With FormFuenteFormularioEjecutar2 do
    Try
      ShowModal;
    Finally
      Free;
    End;

  DesactivarConexionesModuloDeDatos( tSQLConexionGeneral );
End;

..

procedure NombreOpcionExportadaEjecutarn( vGlobales : tVariablesGlobales; Const tSQLConexionGeneral : tCRSQLConnection ); Far; Export;
Begin
  AsignacionValoresGlobales( vGlobales );

  ActivarConexionesModuloDeDatos( tSQLConexionGeneral );

  Application.CreateForm( tFormFuenteFormularioEjecutarn, FormFuenteFormularioEjecutarn );
  With FormFuenteFormularioEjecutarn do
    Try
      ShowModal;
    Finally
      Free;
    End;

  DesactivarConexionesModuloDeDatos( tSQLConexionGeneral );
End;

end.


Espero que te sea de utilidad

Un saludo


La franja horaria es GMT +2. Ahora son las 00:51:13.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi