Como fazer com que o programa não seja executado duas vezes?
Se o programa já estiver sendo executado deve impedir que ele seja executado outra vez.
Eu acho o jeito mais facil é verificar se existe um arquivo de controle no disco, se nao existir, criar um arquivo no disco na abertura do programa , dai se outra copia for aberta, vai verificar que o arquivo ja existe e cai fora. Importante, o programa so deve sair ao apagar o arquivo, para nao dar problema.
Por exemplo
PROCEDURE Main()
LOCAL cLockFile := "programa.lock"
LOCAL hFile
// Tenta criar o arquivo de trava
IF File(cLockFile)
? "O programa já está em execução."
RETURN
ENDIF
// Cria o arquivo de trava
hFile := FCreate(cLockFile)
IF hFile == -1
? "Não foi possível criar o arquivo de trava."
RETURN
ENDIF
// Executa o programa principal
? "Programa em execução..."
// Aqui vem o código principal do seu sistema
// Aguarda uma tecla para simular o uso
Inkey(0)
// Ao sair, remove o arquivo de trava
FClose(hFile)
FErase(cLockFile)
RETURN
Buen día
Lo hago de esta forma en windows modo consola
Al principio del programa después de mi conexión a la base de datos
sql server 2019 y/o postgres
Procedure Main()
IF EstaRodando()
CLS
SETMODE(25,80)
PLSWAIT(.T.,"El sistema se esta ejecutando. Saliendo ...")
INKEY(2)
PLSWAIT(.F.)
SR_EndConnection(nCnn)
CLS
QUIT
ENDIF
Return
//---------------------
FUNCTION EstaRodando()
LOCAL aProcs:={}, lEstaRodando:=.F., nVezes:=0, cExeName
cExeName:=SubStr(HB_ArgV(0), RAT("\", HB_ArgV(0)) + 1 )
WIN_GETPROCESSLIST( aProcs, cExeName )
AEval( aProcs, {|x| nVezes++ } )
IF nVezes > 1
lEstaRodando:=.T.
ENDIF
RETURN lEstaRodando
Saludos!!
O chatgpt me deu essa mesma solução ontem, testei no servidor e deu certo, mas falta testar em pelo menos 1 ou 2 computadores clientes onde os usuários do sistema trabalham. No caso para multiusuário o nome do arquivo programa.lock precisa incorportar o nome de usuário do Windows. Também é interessante colocar hFile e cLockFile como variável pública para chamar essa parte do fechamento em uma rotina EXIT PROCEDURE para garantir que ele sempre será executado saindo por bem ou por mal (dando erro) do programa.
FUNCTION MAIN()
************************************************************************
*** IMPEDIR QUE O PROGRAMA SEJA EXECUTADO DUAS VEZES PELO MESMO USUÁRIO
************************************************************************
LOCAL cUser
PUBLIC nHNOTWICE, cLockFile
***************************************************
*** TOCAR SOM: SNDPLAYSOUND( cWavTada, 1 )
***************************************************
*** SOM OK
PUBLIC cWavTada, cWavOk, cWavErro
cWavTada := "c:\windows\media\tada.wav"
cWavOk := "c:\windows\media\Windows Logon.wav"
*** SOM ERRO
cWavErro := "c:\windows\media\Windows Foreground.wav"
***************************************************
************************************************************************
*** IMPEDIR QUE O PROGRAMA SEJA EXECUTADO DUAS VEZES PELO MESMO USUÁRIO
************************************************************************
cUser := GetEnv("USERNAME")
cLockFile := "LOCK_" + cUser + ".LCK"
// Tenta criar o arquivo de lock exclusivo
nHNOTWICE := FCreate( cLockFile, FO_EXCLUSIVE + FO_READWRITE )
IF nHNOTWICE == -1
SNDPLAYSOUND( cWavErro, 1 )
Alert( "Já existe uma instância do sistema aberta para o usuário " + cUser + "!" )
RETURN NIL
ENDIF
************************************************************************
EXIT PROCEDURE SAIR
*******************
// A EXIT PROCEDURE é executada sempre que o programa fecha normalmente ou por erro.
// Assim garante que as medidas serão tomadas antes de sair.
DbCommitAll()
SET RELATION TO // DbClearRelation()
DbCloseAll()
CLEAR
SET COLOR to
SETMODE(25,80)
************************************************************************
*** IMPEDIR QUE O PROGRAMA SEJA EXECUTADO DUAS VEZES PELO MESMO USUÁRIO
************************************************************************
// Libera o arquivo de lock
FClose( nHNOTWICE )
FILEDELETE( cLockFile )
************************************************************************
QUIT
Era algo assim que eu estava procurando, uma função que me desse o que já está sendo executado no computador. Vou testar essa WIN_GETPROCESSLIST( aProcs, cExeName ), precisa incluir alguma lib específica ou código pragma para importar comando de linguagem C?
No necesitas ninguna Lib y/o lenguaje C
Tal y como esta funciona
Saludos!!