PDA

Ver la Versión Completa : evitar doble ejecucion en el programa...


uper
01-07-2005, 23:13:19
Saludos

tengo una pregunta para implementar el codigo de evitar doble ejecucion de la aplicacion por medio de semaforos, en mi caso en la forma principal ejecuto en el evento Oncreate codigo para las excepciones, y en el evento onshow lo uso para lanzar una forma de password.

el codigo de semaforos es este:
procedure TfrmPrinc.FormCreate(Sender: TObject);
var Sem : THandle;
begin
Sem := CreateSemaphore(nil,0,1,'PROGRAM_NAME');
if ((Sem <> 0) and (GetLastError = ERROR_ALREADY_EXISTS)) then
begin
CloseHandle( Sem );
ShowMessage('This program is already running.'+ 'Este programa ya se está ejecutando...');
Halt;
end;

end;

lo que hice es declarar un procedimiento llamado procedure Ejecucion(); en la seccion private del form principal, y luego lo llamo en oncreate

Ejecucion;
Application.OnException:= EcepcionException;
CargarDiccionario(ExtractFilePath(Application.ExeName) + NombreDiccio);
//para que capte las excepciones.

se ejecuta sin problemas pero si lo ejecuto otra vez me da el error programado de doble ejecucion pero despues me da el error que ha efectuado operacion no admitida, y el error runtime error 216 at 000587b9.

yo lo probe en una aplicacion sencilla en oncreate y funciona por que no le estoy agregando mas codigo de las excepciones, ahora que lo estoy implementando no resulta, hay algo para evitar esto.

mucha gracias.

marcoev
02-07-2005, 03:31:19
encontre el siguiente codigo en trucomania


Simplemente detectaremos si hay otro ejecutable ejecutándose que se llame igual que el nuestro.

-Añade 'TLHelp32' en el uses de tu form
-Añade esta función en el implementation de la form:

function ProgramaAbiertoDosVeces:Boolean;
var
Datos :TProcessEntry32; {Estructura interna de datos de un proceso}
hID :DWord; {identificador del proceso}
Snap :Integer;
NombreArchivo :String; {path del archivo original}
Repetido :Boolean; {true si el programa se ha abierto dos veces}
Handle1 :Hwnd; {thandle}
Contador :Integer; {Contador de aperturas}

begin
Contador:=0;
NombreArchivo:=Application.Exename;
Repetido:=False;
GetWindowThreadProcessId(Handle1,@hID);
Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
try
Datos.dwSize:=SizeOf(Datos);
if(Process32First(Snap,Datos))then
begin
repeat
if NombreArchivo=StrPas(Datos.szExeFile) then
begin
Inc(contador);
if Contador>=2 then Repetido:=true;
end;
until (not(Process32Next(Snap,Datos))) or (Repetido);
end;
finally
Windows.CloseHandle(Snap);
end;
Result:=Repetido;
end;

-Ahora, pon este código en el evento OnCreate de la form principal:

procedure TForm1.FormCreate(Sender: TObject);
begin
if ProgramaAbiertoDosVeces then
begin
showmessage('El programa ha sido abierto mas de una vez');
Application.terminate;
end;
end;

edgusano
02-07-2005, 17:31:34
Pues. Yo utilizo una UNIT que tiene ROMAN publicada en su pagina del club delphi que sirve para eso, por demas es excelente, pruebala.

serhasae
03-07-2005, 00:41:23
Donde esta la unit esa, podrias ponerla Edgusano. No la veo. O que la ponga roman. saludos.

roman
03-07-2005, 01:46:25
http://www.clubdelphi.com/users/roman

// Saludos

uper
04-07-2005, 19:44:40
saludos

tengo un error que me marca en la funcion declarada en la parte de private:
private
function ProgramaAbiertoDosVeces:Boolean; ---->>error.
{ Private declarations }

--->>[Warning] uSistema.pas(99): Variable 'Handle1' might not have been initialized

en donde debe declararse esta variable, ya la coloque afuera despues de la declaraciones privadas y publicas y aun asi da el error
en este caso esta dentro de la funcion:

var
Handle1 :Hwnd; {thandle}

gracias

raco
07-07-2005, 01:00:05
Yo tambien he utilizado este metodo y me funciona muy bien, lo unico que tienes q hacer es seguir las instrucciones de la pagina. Agrega el archivo .pas a tu proyecto igual como viene en la pagina y agregalo al modulo del programa principal (dpr) en la clausula uses, como dice en la pagina para que se ejecute primero. Es todo lo que tienes que hacer.

cyberpablis
20-08-2016, 17:02:24
Directamente en el DPR:

// Verifico que no exista una instancia previa del programa en ejecución.-
Application.Title := 'Mi aplicacion';
if CreateFileMapping($FFFFFFFF, nil, PAGE_READONLY, 0, 32, 'PABLOR_TAGGED') <> 0 then
if GetLastError() = ERROR_ALREADY_EXISTS then
begin
Application.MessageBox('Ya existe una instancia de la aplicación ejecutándose', 'Atención', MB_ICONWARNING);
ExitProcess(1);
end;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;

Angel.Matilla
28-03-2017, 19:10:44
Estaba buscando información sobre otra cosa y he ido a dar con este hilo. Aunque es ya de hace unos meses os pongo aquí como lo resuelvo yo en BCB.

En el fichero que lanza la aplicación (el .cpp asociado a su homónimo .bpr):
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
HWND OtraVentana;
AnsiString cVersion = "Mi aplicación";

OtraVentana = FindWindow(NULL, cVersion.c_str());
if (OtraVentana != NULL)
{
Application->MessageBox("¡¡¡LA APLICACIÓN YA ESTÁ ACTIVA!!!", cVersion.c_str(), 48);
ShowWindow(OtraVentana, SW_RESTORE);
SetForegroundWindow(OtraVentana);
return 0;
}
try
{
Application->Initialize();
Application->Title = cVersion;
Application->CreateForm(__classid(TfPersona), &fPersona);
Application->Run();
}
catch(Exception &exception)
{
Application->ShowException(&exception);
}
catch(...)
{
try
{
throw Exception("");
}
catch(Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
Me parece un método sencillo y elegante.

MAXIUM
28-03-2017, 19:36:02
Mutex, no olviden el Mutex.

Google: delphi + mutex + example