Ir al contenido


Foto

[RESUELTO] Como evitar que mi aplicacion se abra 2 veces en la misma pc


  • Por favor identifícate para responder
27 respuestas en este tema

#1 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 17 enero 2011 - 07:17

Hola a todos

La verdad que he encontrado muchos truquitos sobre este asunto, pero me encantaria leer las opiniones de los miembros del foro. La idea es evitar que mi aplicacion se abra dos veces y que si ya esta abierta se restaure.

Gracias por adelantado (y)
  • 0

#2 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 17 enero 2011 - 07:31

El codigo que estoy usando es de Rinconcito Delphi:
 

Prevenir dos ejecuciones simultaneas de tu aplicación
(Q3 Team)
Esto sirve para que no ejecuten tu programa más de una vez simultaneamente. Puede que quieras simplemente denegar la creación de la segunda instancia de tu aplicación, o puede que lo que quieras es que no sólo no se abra la segunda instancia, sino que se restaure la primera (que igual está minimizada, por ejemplo).
Hay muchas maneras de hacer esto. En este truco he querido poner una que me ha llamado la atención por su sencillez. En Delphi
1 el detectar una instancia anterior era tan fácil como chequear la variable hPrevinst, pero en Delphi 32 bits esta variable ya no existe, así que tenemos que buscar otra manera de detectar otra copia de nuestra aplicación.
Aqui la buscaremos con ayuda de FindWindow y un pequeño truco para simplificar la búsqueda:

Meteremos este código en el código del proyecto, para lo cual has de habilitar la pestaña de ver código del proyecto, que está en: View->Project Source



delphi
  1. program Project1;
  2.  
  3. uses
  4. Forms, Windows, Messages,
  5.   Unit1 in 'Unit1.pas' {Form1};
  6.  
  7. const
  8. CM_RESTORE = WM_USER + $1000;
  9.  
  10. var
  11. RvHandle : hWnd;
  12.  
  13. {$R *.RES}
  14.  
  15. begin
  16. {Si existe otra instancia ya ejecutandose, la activamos}
  17.  
  18. RvHandle := FindWindow('Mi programa Delphi', NIL);
  19.   if RvHandle > 0 then
  20. begin
  21. PostMessage(RvHandle, CM_RESTORE, 0, 0);
  22.     Exit;
  23.   end;
  24.  
  25. {Sino, haz lo normal}
  26.  
  27. Application.Initialize;
  28.   Application.CreateForm(TForm1, Form1);
  29.   Application.Run;
  30. end.

En la declaración de la form, añadiremos este código, (la constante y las dos procedures que hay en la parte public)



delphi
  1. const
  2. CM_RESTORE = WM_USER + $1000;
  3.  
  4. type
  5. TForm1 = class(TForm)
  6.     Label1: TLabel;
  7.     Label2: TLabel;
  8.     procedure FormCreate(Sender: TObject);
  9.   private
  10.     { Private declarations }
  11. public
  12.     { Public declarations }
  13. procedure CreateParams(var Params: TCreateParams); override;
  14.     Procedure RestoreRequest(var message: TMessage); message CM_RESTORE;
  15.   end;

Y en la implementation de la form, pondremos el código de las dos procedures que hemos definido:





delphi
  1. procedure TForm1.CreateParams(var Params: TCreateParams);
  2. begin
  3. inherited CreateParams(Params);
  4.   Params.WinClassName := 'Mi programa Delphi';
  5. end;
  6.  
  7. procedure TForm1.RestoreRequest(var message: TMessage);
  8. begin
  9. if IsIconic(Application.Handle) = TRUE then
  10. Application.Restore
  11.   else
  12. Application.BringToFront;
  13. end;


  • 0

#3 andres1569

andres1569

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 431 mensajes

Escrito 18 enero 2011 - 07:06

Me parece un buen truco, elegante y eficaz, siempre que se asegure uno de dar un nombre suficientemente retorcido para que no pueda ser compartido por otra aplicación  ;)

(Un pequeñito detalle, mejor definir esa cadena "Mi programa Delphi" como una constante, en el form principal por ejemplo, para evitar duplicidades (y) )

Saludos

PD: Por cierto, al leer este hilo, me he ido a buscar un componente que creó Román, de ClubDelphi, que servía para este propósito, pero su página personal ya no está operativa  ^o|
  • 0

#4 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 18 enero 2011 - 07:53

Si el proposito es solo "evitar" yo uso lo siguiente;



delphi
  1. CreateMutex(nil, False, 'MyAppId');
  2. if GetLastError <> 0 then Exit; // Halt; // SendMessage(FindWindow(


  • 0

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.459 mensajes
  • LocationMéxico

Escrito 18 enero 2011 - 08:23

Si el proposito es solo "evitar" yo uso lo siguiente;



delphi
  1. CreateMutex(nil, False, 'MyAppId');
  2. if GetLastError <> 0 then Exit; // Halt; // SendMessage(FindWindow(



:), caramba amigo, tu siempre tan corto de escritura :D :D :D (y)

Salud OS
  • 0

#6 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 18 enero 2011 - 08:59

Donde se supone que debo poner el codigo de cHackAll?
  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.459 mensajes
  • LocationMéxico

Escrito 18 enero 2011 - 09:02

Donde se supone que debo poner el codigo de cHackAll?


Pues yo lo pondría en el .dpr :)

Salud OS
  • 0

#8 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 19 enero 2011 - 07:27



delphi
  1. program Project1;
  2.  
  3. uses
  4. Windows, Forms,
  5. Unit1 in 'Unit1.pas' {Form1};
  6.  
  7. {$R *.res}
  8.  
  9. begin
  10.   CreateMutex(nil, False, 'MyAppId');
  11.   if GetLastError <> 0 then Exit;
  12.   Application.Initialize;
  13.   Application.CreateForm(TForm1, Form1);
  14.   Application.Run;
  15. end.



ó



delphi
  1. unit Unit1;
  2.  
  3. { etc, etc. }
  4.  
  5. var
  6.   Form1: TForm1;
  7.  
  8. implementation
  9.  
  10. {$R *.dfm}
  11.  
  12. initialization
  13. CreateMutex(nil, False, 'MyAppId');
  14. if GetLastError <> 0 then Halt;
  15. end.



ó



delphi
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3. CreateMutex(nil, False, 'MyAppId');
  4. if GetLastError <> 0 then Halt;
  5. end;



un ejemplo;



delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses Windows, Messages, Controls, Forms, Dialogs;
  6.  
  7. type
  8. TForm1 = class(TForm)
  9.   procedure FormCreate(Sender: TObject);
  10.   procedure User(var Msg: TMessage); message WM_USER;
  11. end;
  12.  
  13. var Form1: TForm1;
  14.  
  15. implementation
  16.  
  17. {$r *.dfm}
  18.  
  19. procedure TForm1.FormCreate(Sender: TObject);
  20. var Str: ShortString;
  21. begin
  22. Str := ClassName;
  23. CreateMutex(nil, False, PChar(Str + '.' + Caption));
  24. if GetLastError = 0 then Exit;
  25. DestroyWnd;
  26. Str[Byte(Str[0]) + 1] := #0;
  27. PostMessage(FindWindow(@Str[1], PChar(Caption)), WM_USER, 0, 0);
  28. Halt;
  29. end;
  30.  
  31. var Info: TFlashWInfo = (cbSize: SizeOf(Info); dwFlags: FLASHW_ALL or FLASHW_TIMERNOFG);
  32.  
  33. procedure TForm1.User(var Msg: TMessage);
  34. begin
  35. Info.hwnd := Application.Handle;
  36. FlashWindowEx(Info);
  37. end;
  38.  
  39. end.


  • 0

#9 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 22 enero 2011 - 07:08

Funciona todo bien, pero para no ser tan escueto y que el usuario sepa porque no se abre la aplicacion le puse esto:
en el uses adicionar:  dialogs



delphi
  1. begin
  2.   CreateMutex(nil, False, 'MyAppId');
  3.   if GetLastError <> 0 then
  4.   begin
  5.   showmessage('la aplicacion ya esta corriendo');
  6.   Exit;
  7.   end;
  8.  
  9.   Application.Initialize;
  10.   Application.CreateForm(TDMmonitorenred, DMmonitorenred);
  11.   Application.CreateForm(TFRMactivasred, FRMactivasred);
  12.   Application.CreateForm(TFRMoperadornota, FRMoperadornota);
  13.   Application.Run;
  14.   end.


  • 0

#10 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 30 enero 2011 - 07:06

Tengo un problema extraño con esto de evitar que una aplicacion se abra dos veces. Estoy abriendo un programa desde otro:



delphi
  1.   WinExec(PChar('c:\COBROS\PCOBROS.exe'),SW_SHOWNORMAL)



pero cada vez que le doy al boton, si le he puesto el codigo:



delphi
  1. program PCOBROS;
  2.  
  3. uses
  4.   Forms,Windows,Dialogs,Controls,
  5.   UFRMCOBROS in 'UFRMCOBROS.pas' {Form1},
  6.   UDMCOBROS in 'UDMCOBROS.pas' {DMCOBROS: TDataModule};
  7.  
  8. {$R *.res}
  9.  
  10. begin
  11. CreateMutex(nil, False, 'MyAppId');
  12.   if GetLastError <> 0 then
  13.   begin
  14.   showmessage('la aplicacion ya esta abierta');
  15.   Exit;
  16.   end;
  17.   Application.Initialize;
  18.   Application.CreateForm(TForm1, Form1);
  19.   Application.CreateForm(TDMCOBROS, DMCOBROS);
  20.   Application.Run;
  21.  
  22. end.



me envia el mensaje de que esta abierto, desde la primera vez que le doy.

Que esta pasando?
  • 0

#11 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.459 mensajes
  • LocationMéxico

Escrito 30 enero 2011 - 08:19

¿ No será que debes de colocar el nombre del programa en la función CreateMutex() ?



delphi
  1. program PCOBROS;
  2.  
  3. ::::::::
  4.  
  5. CreateMutex(nil, False, 'PCOBROS');
  6. ::::::::



Salud OS

Edito: Yo colocaría el nombre de la aplicación ya que si a todos los programas les asignara el mismo nombre ´MyAppId´ pudiese suceder lo que mencionas.
  • 0

#12 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 30 enero 2011 - 08:37

Gracias Egostar por Responder, dejame probar y te dejo saber
  • 0

#13 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 30 enero 2011 - 09:01

Efectivamente Egostar, creo que la edad ya me esta haciendo mal. Pero para eso estan ustedes los mas viejos que me sirven de consuelo *-) (y) :D

PD. Como se puede maximizar la aplicacion.

  • 0

#14 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.459 mensajes
  • LocationMéxico

Escrito 30 enero 2011 - 10:45

Efectivamente Egostar, creo que la edad ya me esta haciendo mal. Pero para eso estan ustedes los mas viejos que me sirven de consuelo *-) (y) :D

PD. Como se puede maximizar la aplicacion.


No importa amigo Luciano, lo mejor de llegar a viejo es que todos los dias vas a conocer amigos nuevos :D :D :D

Salud OS
  • 0

#15 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.111 mensajes
  • LocationMadrid - España

Escrito 31 enero 2011 - 05:34

Voy ha proponer un código que evita la ejecución doble de la aplicación, y además restaura el estado original de la ventana de principal de la primera ejecución de la aplicación. Ademas trae al primer plano la aplicación.

El código se coloca en el archivo .dpr que quedaría como sigue:



delphi
  1. program Project1;
  2.  
  3. uses
  4.   Windows, Forms,
  5.   Unit1 in 'Unit1.pas' {Form1};
  6.  
  7. {$R *.res}
  8. var
  9.   Buffer: array [0..MAX_PATH] of char;
  10.   c:      PCHAR;
  11.   Mutex:  THandle;
  12.   Pid:    DWORD;
  13.  
  14.  
  15. function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
  16. var
  17.   Mutex: THandle;
  18. begin
  19.   Result:= true;
  20.   GetWindowThreadProcessId(Handle, Pid);
  21.   if GetCurrentProcessId <> Pid then
  22.   begin
  23.     if GetWindowModuleFileName(Handle, @Buffer, sizeof(Buffer)) > 0 then
  24.     begin
  25.       c:= Buffer;
  26.       repeat Inc(c); if c^ = '\' then c^:= '*'; until c^ = #0;
  27.       Mutex:= CreateMutex(nil, FALSE, Buffer);
  28.       GetClassName(Handle, Buffer, Sizeof(Buffer));
  29.       if (GetLastError <> 0) and (lstrcmp('TApplication', Buffer) = 0) then
  30.       begin
  31.         ShowWindow(Handle, SW_RESTORE);
  32.         SetForegroundWindow(Handle);
  33.       end;
  34.       if Mutex <> 0 then CloseHandle(Mutex);
  35.     end;
  36.   end;
  37. end;
  38.  
  39. begin
  40.   GetModuleFileName(0, Buffer, MAX_PATH);
  41.   c:= Buffer;
  42.   repeat Inc(c); if c^ = '\' then c^:= '*'; until c^ = #0;
  43.   Mutex:= CreateMutex(nil, FALSE, Buffer);
  44.   if GetLastError <> 0 then
  45.   begin
  46.     EnumWindows(@EnumWindowsProc, 0);
  47.     exit;
  48.   end;
  49.  
  50.  
  51.   Application.Initialize;
  52.   Application.CreateForm(TForm1, Form1);
  53.   Application.Run;
  54.  
  55.  
  56.   if Mutex <> 0 then CloseHandle(Mutex);
  57. end.




Saludos.
  • 0

#16 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 31 enero 2011 - 07:46

Gracias por el codigo Escafandra, pero al tratar de arrancar el programa, me sale este error:
escafandra.png


delphi
  1. program Pmonitoreofirebird;
  2.  
  3. uses
  4.   Windows,
  5.   Dialogs,
  6.   Forms,
  7.   controls,
  8.   frmmonitoreoenred in 'frmmonitoreoenred.pas' {FRMactivasred},
  9.   UDMmonitorenred in 'UDMmonitorenred.pas' {DMmonitorenred: TDataModule},
  10.   UFRMNOTAS in 'UFRMNOTAS.pas' {FRMnotas},
  11.   UFRQcentral in 'UFRQcentral.pas' {FRQcentral},
  12.   Ufrmlogin in 'Ufrmlogin.pas' {FRMlogin},
  13.   UFRMSONIDO in 'UFRMSONIDO.pas' {SONIDO},
  14.   _busy in '_busy.pas',
  15.   FRMcierreproceso in 'FRMcierreproceso.pas' {FRMCIERRE},
  16.   Ufrmreconexion in 'Ufrmreconexion.pas' {FRMreconexion},
  17.   frmllamada in 'frmllamada.pas' {FRMLLAMADAS},
  18.   UFRMusuarios in 'UFRMusuarios.pas' {FRMusuarios},
  19.   FRPinformes in 'FRPinformes.pas' {FRMINFORME},
  20.   UFRMclientes in 'UFRMclientes.pas' {FRMclientes},
  21.   Ufrmoperadornota in 'Ufrmoperadornota.pas' {FRMoperadornota};
  22.  
  23. {$R *.res}
  24. var
  25.   Buffer: array [0..MAX_PATH] of char;
  26.   c:      PCHAR;
  27.   Mutex:  THandle;
  28.   Pid:    DWORD;
  29. function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
  30. var
  31.   Mutex: THandle;
  32. begin
  33.   Result:= true;
  34.   GetWindowThreadProcessId(Handle, Pid);
  35.   if GetCurrentProcessId <> Pid then
  36.   begin
  37.     if GetWindowModuleFileName(Handle, @Buffer, sizeof(Buffer)) > 0 then
  38.     begin
  39.       c:= Buffer;
  40.       repeat Inc(c); if c^ = '' then c^:= '*'; until c^ = #0;
  41.       Mutex:= CreateMutex(nil, FALSE, Buffer);
  42.       GetClassName(Handle, Buffer, Sizeof(Buffer));
  43.       if (GetLastError <> 0) and (lstrcmp('TApplication', Buffer) = 0) then
  44.       begin
  45.         ShowWindow(Handle, SW_RESTORE);
  46.         SetForegroundWindow(Handle);
  47.       end;
  48.       if Mutex <> 0 then CloseHandle(Mutex);
  49.     end;
  50.   end;
  51. end;
  52.  
  53. begin
  54.   GetModuleFileName(0, Buffer, MAX_PATH);
  55.   c:= Buffer;
  56.   repeat Inc(c); if c^ = '' then c^:= '*'; until c^ = #0;
  57.   Mutex:= CreateMutex(nil, FALSE, Buffer);
  58.   if GetLastError <> 0 then
  59.   begin
  60.     EnumWindows(@EnumWindowsProc, 0);
  61.     exit;
  62.   end;
  63.  
  64. {begin
  65.   CreateMutex(nil, False, 'Pmonitoreofirebird');
  66.   if GetLastError <> 0 then
  67.   begin
  68.     showmessage('la aplicacion ya esta abierta, revise si esta minimizada');
  69.     Exit;
  70.   end; }
  71.  
  72.   Application.Initialize;
  73.   Application.CreateForm(TDMmonitorenred, DMmonitorenred);
  74.   Application.CreateForm(TFRMactivasred, FRMactivasred);
  75.   Application.Run;
  76.  
  77. if Mutex <> 0 then CloseHandle(Mutex);
  78.  
  79.   end.


cual puede ser el problema?,  La unica diferencia que veo es que yo creo el datamodule primero y luego el form principal.
  • 0

#17 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.111 mensajes
  • LocationMadrid - España

Escrito 01 febrero 2011 - 03:24

Hemos sido víctimas de un gremlin. Parece ser que algo impide y retita los caracteres '\' del código publicado, como hize notar aquí. Al publicar el código no advertí que se habián elimidado dichos caracteres de las líneas como esta:


delphi
  1. repeat Inc(c); if c^ = '' then c^:= '*'; until c^ = #0;

que debían quedar así:

delphi
  1. repeat Inc(c); if c^ = '\' then c^:= '*'; until c^ = #0;


Este es el origen del error que has mostrado.

He reeditado el código del mensaje.

Por si acaso el gremlin ataca de nuevo, subo un archivo de ejemplo. ;)



Saludos.
  • 0

#18 andres1569

andres1569

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 431 mensajes

Escrito 01 febrero 2011 - 12:28

¿Y qué sabéis del gremlin? A mí me paso hace unas semanas en un mensaje cada vez que lo editaba, me dí cuenta de que todas las barras '\' me habían desaparecido  :| :| :|
  • 0

#19 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.111 mensajes
  • LocationMadrid - España

Escrito 01 febrero 2011 - 12:50

¿Y qué sabéis del gremlin? A mí me paso hace unas semanas en un mensaje cada vez que lo editaba, me dí cuenta de que todas las barras '\' me habían desaparecido  :| :| :|

Pues yo lo he notado con Chrome y FireFox, tiene que ver con pegar texto con el caracter '\'. Al parecer puede ser problema del foro y se está estudiando una actualización. ;)

Al citar tu mensaje me ha borrado el carácter en cuestión y he tenido que reconstituirlo. Ahora estoy usando Chrome.

Saludos.
  • 0

#20 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 01 febrero 2011 - 01:35

Pues a mi no me pasa lo que comentan, y uso FireFox.  ^o|

Saludos,
  • 0




IP.Board spam blocked by CleanTalk.