Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Sesion de usuario entre "distintas" a aplicaciones. (https://www.clubdelphi.com/foros/showthread.php?t=74284)

Spk2000ar 09-06-2011 15:29:00

Sesion de usuario entre "distintas" a aplicaciones.
 
Hola!
Estoy desarrollando una aplicación con DelphiXE, para plataforma Win32, con base de datos PostgreSQL.
Las PC destino, pueden tener XP, W7 o W2003Srv, en sus versiones 32b y 64b.

La idea es la siguiente:
Desde un dock que funcionará como menú principal (es un ejecutable principal y separado), lanzaría los distintos módulos de la misma aplicación.
Cada módulo estará en ejecutables separados, ya que tienen funcionalidades muy distintas que bien pueden ser concurrentes para el mismo usuario que ya inicio sesión.
Ya tengo "armado" el esquema de usuarios (usuarios y perfiles de acceso).
El control de que módulos están en funcionamiento, se realizaría por una simple búsqueda de ventanas.
El dock se iniciará con windows.
El dock solo podrá cerrarse si no hay modulos ejecutándose.
El logueo del usuario se realizaría cuando se detecte que no existe otra ventana abierta y que no hay otra sesion abierta.
Si el login es existoso se registrará la sesión del usuario de alguna forma común, para que todos los módulos puedan leerlo y trabajar con dicho usuario (y su perfil).

Ahora bien, las dudas son las siguientes:
1) que función de búsqueda de ventanas es la recomendable, de forma tal de compatibilizar la versión para XP, W7, W2003, y sus versiones en 32 y 64 bits?
2) para el inicio automático con windows del dock para todos los usuarios, recomiendan el uso del registro de windows? la ubicación de la clave/valor en todas las versiones destino, es la misma?
3) donde me convendría registrar la sesion de este usuario actual en Windows en forma local (en una PC se loguea solo un usuario por vez), de forma tal que todos los modulos utilicen esa sesión.
4) como detecto si el dock se cuelga o se cierra forzosamente pero permanecen sesiones abiertas, en uso, con varias ventanas encadenadas abiertas? con un timer global a cada aplicación que chequee si el dock sigue funcionando? eso se ejecuta incluso sobre dialogos o ventanas modales?
5) Si no hay ventanas abiertas, y hay sesion abierta (se cerraron todas pero el dock quedó abierto)? tendría que mantener la sesión, pero como detecto que no es un error? tendría que mantener la hora en que no quedaron más ventanas abiertas y poner un timeout? como se les ocurre gestionar este evento?

Desde ya, mil gracias por cualquier aporte que pudieran acercar desde la experiencia propia!

luisgutierrezb 09-06-2011 16:27:21

Pues a mi se me ocurre lo siguiente, porque no usas un mensaje personalizado de windows, algo asi como wm_user+100 por ejemplo, donde comuniques a los programas con el dock, por ejemplo mandas un mensaje para que pedir usuario, puedes mandar mensajes desde el dock para saber si hay algun modulo en uso, etc, revisa la ayuda de win32 para que veas si te sirve

oesqueda 09-06-2011 16:33:58

Pides mucho, jejejeje, pero solo asi hacemos cosas maravillosas:

Mejor usar Paquetes en vez de ejecutables independientes (no son librerias DLL)
Quizas uso de memoria compartida entre ejecutables (API de Windows)

Saludos

Spk2000ar 09-06-2011 17:20:37

JEJE!!! Será maravilloso, pero vos tendrías que indicarme si es una característica de los desarrolladores en Delphi de siempre querer hacer algo más de lo que las herramientas nos permiten!!!! jeje.

El punto es que no tengo claro ninguno de los 2 temas.

luis: lo que proponés es comunicación vía DDE? se me ocurre que puede funcionar, pero se me ocurre que se complica aún más en aquellos casos "complejos" en los que "falla" el dock y deja ventanas abiertas.

oesqueda:nunca trabajé con paquetes.
Estos se compilan y desarrollan como cualquier aplicación que termine en un ejecutable?
Si actualizo uno, solo reemplazo ese paquete y listo, no?
Si los paquetes forman parte del Dock, se cargan dinámicamente compartiendo toda la memoria de la aplicación del dock? o se levantan todos juntos al iniciar el dock (indeseado)?
Otra... me resulta útil que cada modulo ejecutable/paquete, aparezca en la barra de tareas... y sea minimizable y cerrable desde ella... distribuirlos como ejecutables me permite eso, pero distribuirlos como paquetes???

oesqueda 09-06-2011 17:25:25

Los paquetes son los archivos BPL, la diferencia entre una DLL es que comparten memoria y puedes saber si esta abierta una ventana o no.
Pero si, es un tema no dificil, pero poco usado (creo yo) por los programadores Delphi.
Todo es posible en Delphi, eso te lo aseguro por experiencia propia, yo tengo un libro viejo La biblia de Delphi 6 (Marco Cantu claro esta) y ahi viene una buena explicacion de paquetes, que aun es viable para versiones mas nuevas. Aun esta a mi lado al programar ese LIBROTE jejejeje.

DDE ya esta descontinuado, no te metas por ahi y OLE maneja muchos puntores (por algo me quede en Delphi y no C++ jajajajaja).

Necesitas un ejecutable principal y de ahi cargas los paquetes, son librerias.
Si abres una opcion del sistema, cargas la libreria y con eso sabes que esta abierta alguna opcion del sistema, etc, etc.

Spk2000ar 09-06-2011 17:31:21

Esto se puede lograr?
Cita:

Empezado por Spk2000ar (Mensaje 403157)
Otra... me resulta útil que cada modulo ejecutable/paquete, aparezca en la barra de tareas... y sea minimizable y cerrable desde ella... distribuirlos como ejecutables me permite eso, pero distribuirlos como paquetes???

PD: Yo tenía la del Delphi 4!!!! arranqué con Delphi 1, me asenté en Delphi 7, y estoy comenzando con el XE... jeje... en fin...

oesqueda 09-06-2011 17:42:42

Asi es yo me quede en delphi 6 (con delphi 8 pense que era el final de delphi porque nada mas no sirvio, jejejeje).
Y estoy haciendo una nueva version de un sistema (despues de comprar un par de componentes y transportar otros) a Delphi XE y muchos conceptos aun son aplicables con alguna que otra pequeña adaptacion.

En el caso de este problema Spk2000ar, requieres aprender cosas nuevas y quizas no tengas el tiempo de investigar.

Al González 09-06-2011 18:56:17

Hola.

Cita:

Empezado por Spk2000ar (Mensaje 403132)
3) donde me convendría registrar la sesion de este usuario actual en Windows en forma local (en una PC se loguea solo un usuario por vez), de forma tal que todos los modulos utilicen esa sesión.

Cita:

Empezado por oesqueda (Mensaje 403153)
Quizas uso de memoria compartida entre ejecutables (API de Windows)

En caso de que optes por usar memoria compartida para guardar los datos de la sesión, te recomiendo hacerlo con un objeto superglobal. Te simplifica mucho las cosas sin tener que llamar directamente a ninguna de las funciones de la API de Windows.

Saludos.

Al González. :)

gatosoft 10-06-2011 06:41:09

No se si ponerme a llorar o saltar de alegria.... Al, esto del Objeto superglobal era lo que estaba buscando hace años...!!! mi mundo de posibilidades acaba de cambiar... voy a tirar todos mis programas a la basura para re-escribirlos basados en tu implmentación del objeto superglobal... (es en serio)

pero bueno, para efectos de ilustración de lo que estoy diciendo les muestro como resolví el problema que nuestro amigo Spk2000ar plantea al inicio del hilo, y entenderán por que la solución de Al me hace sentir que en todos estos años no he aprendido nada de Delphi...


Hace mucho tuve la misma necesidad que Spk2000ar... entonces cree una clase llamada TSesionAPPL... para mi empresa, por lo cual no podré compartir todo el codigo pero si las ideas básicas...


1. Escogí la estrategia de enviar mensajes entre aplicaciones, para lo cual me documenté un poco sobre las funciones:

SendMessage
AllocateHWnd
DeallocateHWnd

2. Habia un módulo principal (MAIN) que funcionaba como barra de menú, que llamaba a los módulos operativos... y le pasaba como parametro un archivo que generaba el MAIN, el cual, despues de ser leido por el módulo que fue llamado se borraba... (No sabia de los archivos mapeados en memoria sino hast hace poco, asi que no me juzguen tan duro)

3. para la implementación: Cree unos códigos de mensaje
Código Delphi [-]
MsgBOSE_PING = 998;
MsgBOSE_PONG = 999;
MsgBOSE_ENTRA_APPL = 1000;
MsgBOSE_SALE_APPL = 1001;
MsgBOSE_TERMINAR = 1002;

(BOSE es una abreviatura de un módulo)

4. La función que procesa los mensjaes la definí como:

Código Delphi [-]
Procedure TSesionAPPL.WndProc(var Message: TMessage);
var intIndice : Integer;
begin

///////////////////////////////////////////////
// DESCRIPCION:
// Procesa los mensajes entre aplicaciones
///////////////////////////////////////////////

  if Message.Msg = WM_USER+100 then
  begin
      Case Message.LParam of
      MsgBOSE_ENTRA_APPL:
         Begin
            if FlstAplicaciones.IndexOf(IntToStr(Message.wParam))=-1 then
               FlstAplicaciones.Add(IntToStr(Message.wParam));
         end;
      MsgBOSE_SALE_APPL:
         Begin
           intIndice := FlstAplicaciones.IndexOf(IntToStr(Message.wParam));
           FlstAplicaciones.Delete(intIndice);
           if assigned(FOnActivarMain) then
              FOnActivarMain(nil);
         end;
      MsgBOSE_PING:
         Begin
             if self.blnPuntoDeEntrada then
                SendMessage(Message.wParam, WM_USER + 100, Self.FhwnMain, MsgBOSE_PONG)
             else
                SendMessage(Message.wParam, WM_USER + 100, Self.FhwnModulo, MsgBOSE_PING);
         end;
      MsgBOSE_PONG:
         Begin
           //OK
         end;
      end; //Case
  end else
      Begin
        if Self.blnPuntoDeEntrada then
           DefWindowProc(FhwnMain, Message.Msg, Message.wParam, Message.lParam)
        else
           DefWindowProc(FhwnModulo, Message.Msg, Message.wParam, Message.lParam);
      end;//if .. else
end;

La anterior función es mas o menos transparante asi que no voy a entrar en detalles sobre ella...

5. al crear el objeto sesion, registraba la función de procesamiento de mensjaes...

Código Delphi [-]
Constructor TSesionAPPL.Create(strRutaINI_p, strArchivoINI_p:string; blnPtoEntrada_p:Boolean=False);
Begin
  inherited Create;

  if blnPuntoDeEntrada then
  begin
    FhwnMain := AllocateHWnd(WndProc);
    FhwnModulo := 0;
  end else //if
     Begin
       FhwnMain := 0;
       FhwnModulo := AllocateHWnd(WndProc);
     end;

end;

//El "punto de entrada" es el módulo principal...

6. El destructor del objeto sesion "des-registraba" el procedimiento de escucha de mensajes..

Código Delphi [-]
Destructor TSesionAPPL.Destroy;
Begin

 if Self.blnPuntoDeEntrada then
    Begin
    //Le informa al Main que va de salida
      DeallocateHWnd(FhwnMain);
    end else
        Begin
        SendMessage(Self.FhwnMain, WM_USER + 100, Self.FhwnModulo, MsgBOSE_SALE_APPL);
        DeallocateHWnd(FhwnModulo);
        end;

 inherited Destroy;
end;

7. El archivo de interambio generado por el Main, le pasaba el Handle al módulo, e inmediatamente le enviaba un mensaje de "ingreso a la aplicación"

Código Delphi [-]
 Self.FhwnMain := StrToInt(ObtenerParametro(strRutaCoockie_p,';',4,'0')); //El Handle del Aplication (MAIN)
      if not blnError then
      Begin
         //Le informa al Main que acaba de entrar a la aplicación
         SendMessage(Self.FhwnMain, WM_USER + 100, Self.FhwnModulo, MsgBOSE_ENTRA_APPL);


8. El mensaje para cerrar forzadamente los módulos era:


Código Delphi [-]
Procedure TSesionAPPL.CerrarModulos;
Var i:Integer;
Begin
  For i:=0 to FlstAplicaciones.Count-1 do
  Begin
    SendMessage(StrToInt(FlstAplicaciones[i]), WM_USER + 100,Self.FhwnMain, MsgBOSE_TERMINAR);
  end;//for i
end;


9. Bueno como dije, no puedo publicar mucho de este codigo, peor la idea era mas o menos esta...

Esto fue hace mucho y precisamente en estos días estaba pensando en redefinir la clase de una manera mas óptima (utilizando archivos mapeados en memoria) para utlizarla en nuevos proyectos, pero como dije, el Objeto superglobal de AL, cambia el panorama....

Muchas gracias AL... y espero haber sido claro en mi explicación anterior, pues como dije, fue solo a manera ilustrativa por si a alguien le sirve...

Spk2000ar 10-06-2011 12:00:12

En el momento en que estoy, y analizando lo que expusiste (gatosoft), ni voy a pensarlo... probaré el ejemplo de Al y saldré para adelante con ello.
En cuanto arme todo les cuento como quedó.
Mil gracias a todos!!!! (por ahora... jeje)


La franja horaria es GMT +2. Ahora son las 23:01:29.

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