Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 12-06-2014
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Aplicación con parámetro cuando ya hay una instancia igual funcionando

En mi sistema tengo un "tipo nuevo" de ficheros que he asociado a mi aplicación (extensión .ccq -por ejemplo-); De forma que cuando el usuario pulsa doble click desde el explorador sobre un fichero de tipo .CCQ, se abre mi aplicación (y como parámetro le llega el path del fichero); Hasta aquí sin problemas.

ACTUALMENTE:
Si la aplicación ya está abierta, al pulsar doble click sobre un fichero .CCQ el sistema abre una segunda instancia de mi aplicación que recibe el correspondiente parámetro (nombre de fichero). Esto es la situación normal (no la que yo quiero).

ME GUSTARÍA:
Que el sistema no abriera una segunda instancia de la aplicación -AP2- (si ya hay una funcionando -AP1-). Es un tema que se puede solucionar fácil y además ya lo hemos hablado otras veces aquí en el club. El problema es que si no ejecuto/lanzo esa segunda instancia de la aplicación -AP2-, me gustaría que la primera -AP1- (que tengo funcionando) recibiera "de alguna forma" la información que llegaba a la segunda (el path del fichero que se ha seleccionado con doble click en el explorador).

¿Me explico?

Se me han ocurrido algunas cosas, pero tal vez hay alguna solución sencilla que se me está pasando de largo.
Espero vuestras ideas.

Un saludo.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #2  
Antiguo 12-06-2014
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.557
Poder: 25
egostar Va camino a la fama
Que tal amigo,

Yo pensaría en algo sencillito, usaría un socket en cada aplicación para enviarla si es que ya existe una instancia corriendo del programa en cuestión, la otra pues es la que a mi me da algo de problema, con los mensajes del API, pero eso se lo dejo a mis buenos amigos "API-ceros" que todos ya conocemos

Saludos
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney
Responder Con Cita
  #3  
Antiguo 12-06-2014
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Memory mapped files.

// Saludos
Responder Con Cita
  #4  
Antiguo 12-06-2014
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Yo uso con buenos resultados el componente cyAppInstances de Cindy Components. Creo que hace lo que necesitas y se trata de un proyecto de código abierto (apoyado por donaciones) así que puedes al menos echar un vistazo y hasta tal vez usarlo directamente.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #5  
Antiguo 13-06-2014
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola Germán.

Creo que parte de la solución sería con lo que dice Román:
Cita:
Empezado por roman Ver Mensaje
Memory mapped files.
De lo cual por cierto, no sé si recuerdas, se desprende aquel tema de los objetos superglobales.

Creo que con eso (memoria compartida) y un evento de bajo nivel (usando funciones como CreateEvent, OpenEvent y WaitForSingleObject) podrías obtener el funcionamiento que deseas.

Sin embargo no está en mi experiencia un caso igual al que planteas, por lo que seguro vendrán mejores consejos en los siguientes mensajes.

Un saludo.
Responder Con Cita
  #6  
Antiguo 13-06-2014
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Hola a todos.
Gracias por las respuestas. Bueno, están bastante cerca de lo que tenía en mente, así que veo que no voy mal encaminado...


Cita:
Empezado por egostar Ver Mensaje
Yo pensaría en algo sencillito, usaría un socket en cada aplicación para enviarla
Gracias Egostar. Pensaba aun en algo más sencillo que sockets.

Cita:
Empezado por roman Ver Mensaje
Memory mapped files.
Cita:
Empezado por Al González Ver Mensaje
Hola Germán.
Creo que parte de la solución sería con lo que dice Román:
De lo cual por cierto, no sé si recuerdas, se desprende aquel tema de los objetos superglobales.
Esa era una de las opciones. En concreto ya hay otros mensajes en el club que hablan de ellos (Román ya sales en algunos):
http://www.clubdelphi.com/foros/showthread.php?t=22626
http://www.clubdelphi.com/foros/showthread.php?t=24659

Al, no recordaba la unidad mencionada. Ahora que me lo has dicho le he echado un vistazo y como el resto de la librería tiene una pinta fantástica.

Finalmente no es la opción escogida, tal vez por simplicidad, he acabado usando mensajes (WM_COPYDATA).

Cita:
Empezado por dec Ver Mensaje
Yo uso con buenos resultados el componente cyAppInstances de Cindy Components[/url]. Creo que hace lo que necesitas y se trata de un proyecto de código abierto (apoyado por donaciones) así que puedes al menos echar un vistazo y hasta tal vez usarlo directamente.
Gracias David. He oído hablar en varias ocasiones de estos componentes, pero nunca me los había mirado en detalle.
Para el tema de la instancia se puede usar el componente cyAppInstances, como comentas, aunque he preferido utilizar la unit (UIApp) que Román tiene en su web, que hace el mismo trabajo (de esa forma me evito instalar un componente más).

Cuando miraba en enlace, he visto que justo debajo hay otro componente que se llama TCyCommunicate y que va más encaminado a la solución que finalmente he adoptado. La de utilizar Mensajes. En concreto WM_COPYDATA.

También hemos hablado otras veces en el club y hay buenos ejemplos de este método aquí:
http://clubdelphi.com/foros/showthread.php?t=81589
http://clubdelphi.com/foros/showthread.php?t=82410

Además de los hilos comentados había llegado a este enlace que también describe este sistema:
http://voiceofgeek.blogspot.com.es/2...in-delphi.html

Finalmente he añadido a la unit de Román un procedimiento más, que justo después de activar la "instancia previa" de la aplicación que ya está ejecutándose, le envía un mensaje con el parámetro (el path del fichero).
Algo así:

Código Delphi [-]
// Le envía el primer parámetro por mensaje (si existe)
procedure SendMessageParam;
var
  copyDataStruct: TCopyDataStruct;
  str:string;
  receiverHandle: THandle;
  res : integer;
begin
  // Si no hay parámetros, salimos...
  if (ParamCount <= 0) then Exit;

  // rellenar la estructura con los datos
  Str := ParamStr(1);
  copyDataStruct.dwData := 9999;  // Por seguridad para detectar que es el mensaje correcto
  copyDataStruct.cbData := 1 + Length(Str) ;
  copyDataStruct.lpData := PChar(Str);

  // Buscar la aplicación para enviar datos
  receiverHandle := FindWindow(PChar('TFormMainQC'), nil) ;
  if receiverHandle = 0 then begin
    Exit;
  end;

  // DEBUG!!!!
  MessageDlg('Enviando Mensaje ' + IntToStr(receiverHandle), mtInformation, [mbOK], 0);

  // enviar los datos
  res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Application.Handle),
          Integer(@copyDataStruct)) ;
end;

Para completar el código, os pongo el de recepción:

Código Delphi [-]
// procedimiento para recibir mensajes (parametros)
procedure TFormMainQC.WMCopyData(var Msg: TWMCopyData);
var
  str:string;
begin
  // Recuperamos la parte de la cadena
  str := PChar(Msg.CopyDataStruct.lpData);

  // Si no es la misma aplicaciones, salimos...
  if (Msg.CopyDataStruct.dwData <> 9999) then begin
    Exit;
  end;
  
  // Ejecutar la acción necesaria
  ...

Finalmente me ha parecido la más sencilla y rápida.
Si le veís algun problema comentadlo, aun estoy a tiempo... ;-)

AÑADIDO: Antes de preguntar estuve realizando algunas búsquedas en el foro (y fuera de él) y llegué a bastantes hilos (algunos de ellos los he colocado arriba). No hice mal la búsqueda, pero está claro que no la hice bien al 100%.
Hoy revisando otra vez, he encontrado un hilo al que no llegué ayer y que habla justamente de este problema.
"Abrir fichero asociado si la aplicacion ya esta activa."
http://clubdelphi.com/foros/showthread.php?t=64015
Lo mejor de todo es que Román es justo quien da la solución uilizando el mensaje WM_COPYDATA
Y aporta este link como complemento:
http://www.delphidabbler.com/article...part=2#cmdline
Donde ya está programado un procedimiento justo para lo que necesito (SendParamsToPrevInst)...


Código Delphi [-]
function SendParamsToPrevInst(Wdw: HWND): Boolean;
var
  CopyData: TCopyDataStruct;
  I: Integer;
  CharCount: Integer;
  Data: PChar;
  PData: PChar;
begin
  CharCount := 0;
  for I := 1 to ParamCount do
    Inc(CharCount, Length(ParamStr(I)) + 1);
  Inc(CharCount);
  Data := StrAlloc(CharCount);
  try
    PData := Data;
    for I := 1 to ParamCount do
    begin
      StrPCopy(PData, ParamStr(I));
      Inc(PData, Length(ParamStr(I)) + 1);
    end;
    PData^ := #0;
    CopyData.lpData := Data;
    CopyData.cbData := CharCount * SizeOf(Char);
    CopyData.dwData := cCopyDataWaterMark;
    Result := SendMessage(
      Wdw, WM_COPYDATA, 0, LPARAM(@CopyData)
    ) = 1;
  finally
    StrDispose(Data);
  end;
end;

Un saludo a todos.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.

Última edición por Neftali [Germán.Estévez] fecha: 13-06-2014 a las 09:52:49.
Responder Con Cita
  #7  
Antiguo 13-06-2014
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Muchas gracias por el informe tan detallado, Germán. Le va a servir a muchos colegas que tengan la misma necesidad.

Ya había olvidado el mensaje wm_CopyData, me parece que es buena alternativa. Aunque yo usaría la clase TSuperGlobalObject, por simplicidad.

Un abrazo.

Última edición por Al González fecha: 13-06-2014 a las 17:12:52.
Responder Con Cita
  #8  
Antiguo 13-06-2014
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Qué bueno que usaste uiapp

Sin embargo, creo recordar que algunas personas han reportado que con delphis y/o windows modernos ya no funciona del todo bien. Habría que verificar.

Por otro lado, está bien eso de ahorrar unidades pero los memory mapped files, te resolverían no sólo el paso del path sino también la ejecución de una sóla instancia.

Finalmente, me he vuelto flojo y yo usaría lo que te propone dec

Por cierto dec, no deja de sorprenderme tu sapiencia de software libre muy útil. No estaría de más si nos hicieras un compendio de todo el que conozcas

// Saludos
Responder Con Cita
  #9  
Antiguo 13-06-2014
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

No creas Román... siempre "tiro" de Google y de Torry's, sobre todo. Lleva mucho tiempo rondándome la idea de hacer un sitio web del estilo de Torry's pero un poco más "moderno" (pa' meter la pata a lo peor) pero hasta el día de hoy no he hecho nada en absoluto. Por lo demás lo que pasa es que casualmente uso el componente que he mencionado en este hilo, y, claro, me he acordado enseguida de que igual podría ser útil para Germán también.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #10  
Antiguo 16-06-2014
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por roman Ver Mensaje
Sin embargo, creo recordar que algunas personas han reportado que con delphis y/o windows modernos ya no funciona del todo bien. Habría que verificar.
Gracias Román.
Necesitaré verificarlo, pues el programa tiene que correr sin problemas en versiones nuevas.
Reportaré lo que encuentre.

Un saludo.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
una sola instancia de la aplicacion morfeo21 Varios 6 24-10-2014 03:40:50
Instancia de SQL Server no accesible desde aplicacion C# Faust MS SQL Server 0 14-10-2011 19:37:50
Crear unica instancia de aplicacion en red zugazua2001 Varios 1 07-05-2008 16:56:23
Cuando el Nombre del campo es el parametro Camilo SQL 6 06-08-2007 18:35:00
Cómo detectar una instancia de una aplicación Ana Tudela API de Windows 1 30-06-2005 12:20:13


La franja horaria es GMT +2. Ahora son las 16:00:36.


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
Copyright 1996-2007 Club Delphi