Impedir que se abra o aplicativo que já estyiver em execução

56 respostas
rsantini

Olá,

Alguém saberia me responder como faço para evitar que um aplicativo em execução se abra novamente?

Obrigado.

56 Respostas

ricardolecheta

que aplicativo? um desenvolvido por vc tipo em swing?

rsantini

sim, um aplicativo desenvolvido por mim com Swing…

ricardolecheta

abre o programa, cria um arquivo em algum lugar… por exemplo “programa.lock”…

ao abrir seu aplicativo vc testa para ver se existe este arquivo, se existir vc nao abre :slight_smile:

alguem tem outra sugestão? :wink:

keller

se for usar esta dica nao esqueça de fazer um window listener para deletar o arquivo no fechar da janela senao seu programa nao abrira mais… :lol:

paulohbmetal

É mais isso daí pode ter um probleminha.

Por exemplo, se a máquina do usuário desligar com uma queda de energia…Lá vai o suporte sair removendo arquivo de bloqueio.

O ideal seria se a máquina virtual conseguisse identificar a aplicação. :roll:

Vixe agora também quero saber como…

:?:

A Paz!!

danieldestro

Será que um System.setProperty() não funciona?

danieldestro

Tentei isso:

public class A { public static void main( String[] args ) { System.out.println("Status: "+System.getProperty("motherfucker")); if( System.getProperty("motherfucker") != null ) { System.out.println("Already running... bye!"); return; } System.setProperty("motherfucker","ready"); System.out.println("Status: "+System.getProperty("motherfucker")); try { Thread.sleep(15000); } catch( Exception e ) {} System.out.println("bye!"); } }

Mas não funcionou! :cry:

Luca

Olá

Ao entrar na aplicação tente abrir um ServerSocket com uma porta maluca qualquer. Trecho de exemplo:

try { ServerSocket ss = new ServerSocket(qqport); ss.close(); // conseguiu!!!, estou sozinho } catch (IOException ex) { // Não conseguiu, já tem outro aberto }

[]s
Luca

danieldestro

Uma solução mais louca que a outra.
UHAUahuAHUAuAhuahuhUAhUAhuauAuhUAHuA…

paulohbmetal

Luca:
Olá

Ao entrar na aplicação tente abrir um ServerSocket com uma porta maluca qualquer. Trecho de exemplo:

try { ServerSocket ss = new ServerSocket(qqport); ss.close(); // conseguiu!!!, estou sozinho } catch (IOException ex) { // Não conseguiu, já tem outro aberto }

[]s
Luca

Putz, mais que gato!!! :shock: :shock: :shock: :shock: :shock:

:lol: :lol:

A Paz!!

velo

Naum existem uma maneira de gravar alguma coisa na RAM?

Um objeto, ou um arquivo, sei lah…

Tipo um disco virtual, mas sem precisar iniciar esse serviço no SO…

pcalcado

Duas VMs diferentes? Nope.

[]s

T

Você sabe que isso é meio chato de fazer, mesmo em um programa 100% C++. Em C++ e ambiente Windows, por exemplo, não funciona bem aquela história de criar uma janela escondida com um determinado título e checar se a janela já existe - às vezes isso não dá certo. (principalmente para aqueles caras mais impacientes, que dão um “multiple-click” para iniciar um programa.) Eu em particular acho que isso deveria ser gerenciado pelo sistema operacional (onde você deixaria apenas uma cópia por máquina, ou uma cópia por usuário).

O esquema do arquivo de “lock” é bem estilão Unix, e como no Unix, de vez em quando dá pau. Você pode até tentar um esquema com java.nio e usar FileLock - criar um arquivo, se não existir, e associar um “lock” a ele; se não conseguir fazer o lock, então é porque uma cópia do aplicativo já deve estar rodando. Se o aplicativo sair do ar, o lock será liberado do arquivo.

Luca

Olá

Insisto, o esquema dos sockets funciona legal. Usamos isto no Banco Postal e nunca deu problemas. Antes usávamos lock de arquivos (feito na mão porque era j2sdk 1.3.1) e deu problemas.

[]s
Luca

T

Beleza, porque portas em sockets são o único recurso global “garantido” de existir em qualquer sistema operacional decente (com rede, é claro) que o Java suporta.
Obrigado pela informação.
Só completando, sempre se lembrar que a tal “porta maluca” não pode ser menor que 1024 ou 5000 (agora não sei o número certo) porque isso costuma dar problemas com Unix / Linux e usuários não administrativos (root).

pcalcado

thingol:

Só completando, sempre se lembrar que a tal “porta maluca” não pode ser menor que 1024 ou 5000 (agora não sei o número certo) porque isso costuma dar problemas com Unix / Linux e usuários não administrativos (root).

tem que ser > 1024

[]s

Rubem_Azenha

Luca:
Olá

Insisto, o esquema dos sockets funciona legal. Usamos isto no Banco Postal e nunca deu problemas. Antes usávamos lock de arquivos (feito na mão porque era j2sdk 1.3.1) e deu problemas.

[]s
Luca

e se o cara tem um firewall corporativo chato?

pcalcado

microfilo:

e se o cara tem um firewall corporativo chato?

Só se o tal firewall estiver na máquina do aplicxativo, porque o que o Luca sugeriu foi um loopback.

[]s

velo

Acho que esse eh o caso em que se necessita uma solução em JNI… :frowning:

Luca

Olá

JNI para abrir um socket com a própria máquina?

[]s
Luca

hmichel

No caso de mais de um aplicativo aberto, as IDEs java, cito NetBeans e Eclipse, utilizam arquiuvos de lock.
O Eclipse exige que tenha-se que exluir o arquivo caso haja uma saida inexperada do sistema. O NetBeans, avisa que o sistema esta aberto, ou sofreu uma saida repentina e pergunta se deseja realemente continuar (ele então exclui o arquivo e cria novamente).

[]'s

velo

Luca:
Olá

JNI para abrir um socket com a própria máquina?

[]s
Luca

Usar JNI pra fazer algum tipo de trava em memoria RAM… tipo gravar um arquivo na RAM ao inves do HD…

Sei lah, deve dar, o duro é como :frowning:

VELO

danieldestro

Se o Eclipse e o NetBeans usam file locking, use vc também. O hmichel já deu uma ótima referência.

pcalcado

Gravar em MP? Dois processos? Memória compartilhada. A complexidade é mil vezes maior que abrir um socket.

File locking é usado em muitos lugares, existem milhares de textos sobre o tema.

[]s

velo

pcalcado:
Gravar em MP? Dois processos? Memória compartilhada. A complexidade é mil vezes maior que abrir um socket.

File locking é usado em muitos lugares, existem milhares de textos sobre o tema.

[]s

Mas que era uma API massa, isso eh. Poh, se tivesse um JAR prontinho pra isso fica facil :smiley: :lol:

pcalcado

Não entendi:

O que exatamente você ia ganhar nesse método que valesse a pena perder a portabildiade e apelar pra JNI?

velo

pcalcado:
Não entendi:

O que exatamente você ia ganhar nesse método que valesse a pena perder a portabildiade e apelar pra JNI?

Ah, um lock em memória RAM é mais transparente que um lock em disco. Se faltar luz e o cara tiver aquele desligamento súbito, quando ligar o PC denovo o programa não vai estar travado.

Quando você fala de um usuario mais experimentado, uma janelinha avisando do problema resolve, se bobiar o cara nem vai esperar a janelinha, vai direto na pasta e vai apagar o lock, agora, quando você fala de um manipulador de mouse, vixi, se aparecer qualquer coisa diferente do normal ele jah liga pro help desk.

Bom, jah vi gente “chamando” por ajuda pq os botões F + 1 não abria o help. Ou seja, pedindo ajuda pra achar um botão no teclado.

Mas todos casos toh começando a estudar JNI (comecei a ler um pouco ontem :D), se eu aprender como fazer ajudo :smiley:

Luca

Olá

Por isso sugiro usar sockets ao invés de locks de arquivos. O fato das IDEs usarem não significa que é a melhor solução, significa apenas que elas usam um monte de arquivos e que simplesmente podem fazer lock de algum. Criar um arquivo especialmente para lock foi a fonte dos problemas que nos fez migrar para sockets.

Não entendo como alguém pode achar lock de arquivos ou elocubrações dependentes da arquitetura do sist. operacional mais simples do que tentar abrir um socket com uma porta > 1024 e verificar se dá exceção.

[]s
Luca

ricardolecheta

concordo com o Luca, sockets parece bem simples, e a galera ja ta inventando moda demais :slight_smile:

T

Ainda bem que não puseram isso (checar se o programa já está rodando) como uma API do Java.
Pelo que acho, provavelmente eles iriam usar um lock de arquivos, e isso ia dar esses problemas que foram apontados. (Isso ocorre com o java.util.logging, que usa um lock, e sempre dá problemas. Por isso é que uso o tal do log4j mesmo.)
O grande problema é que normalmente quando existe um recurso no Java padrão (como o java.util.logging), muitas empresas requerem que se use esse recurso, mesmo que saibamos que ele "está com problemas’ e você saiba que seria melhor usar algo mais usado mas não exatamente padrão (como o log4j, que é um padrão “de fato”.)

Provavelmente ia dar alguns problemas como a nova API “isReachable” que é uma forma de você determinar se um determinado host está no ar. Ela tenta usar ICMP ECHO e se não conseguir tenta usar ECHO (UDP ou TCP). Sempre tem alguém que esbarra em algum problema nessa API.

cv1

A solucao do Luca eh genial. As IDEs deveriam eh fazer isso ao inves de usar file locks. Outra vantagem eh que vc pode usar o socket pra alguma comunicacaozinha (do tipo “quando o usuario clicar no icone da aplicacao e ela ja estiver aberta, mande um ‘ping’ pra porta e caso a app ja esteja aberta, ela toma foco, ou pisca na barra de tarefas, pra atrair a atencao do usuario ao fato de que ele ja tem a app aberta”).

Luca

Olá

cv:
A solucao do Luca eh genial.

Nada como receber um elogio mas na verdade a solução não foi escrita por mim, apenas participei das idéias. Detalhando mais ela fica assim:

Na inicialização da sua aplicação faça o seguinte teste (repare que se isLocked retorna true é porque já está travada por outro):

//import AppLock;

.  .  .  .  .  .  .  .  .  .  .

AppLock appLock = null;
// port é qq número acima de 1024, de preferencia leia em um arq. de properties
int port = 44444;  

if ( AppLock.isLocked(port ) ) {
        JOptionPane.showMessageDialog(null,  "Aplicação já aberta", "ERRO", JOptionPane.ERROR_MESSAGE);
        System.exit(1);
} else {
        // Aplicação livre, vamos trava-la
        appLock = new AppLock(port);
        try {
                appLock.lock();
        } catch (IOException ioex) {
                ioex.printStackTrace();
        }
}

.  .  .  .  .  .  .  .  .  .  .

E crie uma classe AppLock tal como abaixo:

import java.io.IOException;
import java.net.ServerSocket;


public class AppLock {

	int port ;
	ServerSocket serverSocket ;
	
// ------------------------------------------------------------------	
	public AppLock(int lockport) {
		port = lockport;
	}
	
//	------------------------------------------------------------------	
	public void lock() throws IOException {
		serverSocket = new ServerSocket(port);
	}

//	------------------------------------------------------------------
	public void unlock() {
		try {
			serverSocket.close();
		} catch (IOException ioex) {
		}
	}

//	------------------------------------------------------------------
	public static boolean isLocked(int lockport) {
		boolean retorno = false;
		try {
			ServerSocket ss = new ServerSocket(lockport);
			ss.close();
		} catch (IOException ioex) {
			retorno = true;
		}
		return retorno;
	}

}

[]s
Luca

danieldestro

public static boolean isLocked(int lockport) { boolean retorno = false; try { ServerSocket ss = new ServerSocket(lockport); ss.close(); } catch (IOException ioex) { retorno = true; } return retorno; }

Mas aqui você abre o SocketServer e em seguida o fecha, certo?
Isso não liberaria a porta novamente?

Luca

Olá

Repare no seguinte: primeiro preciso testar se já está travado. Então tento abrir o ServerSocket. Caso tenha sucesso, preciso fecha-lo para depois mais adiante realmente abri-lo. Isto foi feito assim, é claro que pode ser modificado se alguém quiser fazer o travamento DENTRO do método booleano isLocked de verificação de travamento. Ficou assim por questões de lógica e não de performance.

[]s
Luca

danieldestro

Ah tá! Achei que já estava sem entender nada.

velo

Luca

Olá

E receber minha completa desaprovação pois como afirmei nas mensagens que postei aqui e como repeti claramente em mensagens privadas, o código que postei aqui tem dono, faz parte de um projeto profissional, eu não tinha autorização para coloca-lo aqui mas coloquei com o intuito de ajudar aos colegas.

Em mensagem privada ao Velo afirmei que como eu coloquei aqui no GUJ ele podia adaptar em seus projetos mas sem publicar. E publicar como API no java.net é sacanagem.

Acho que depois desta não coloco mais código nenhum aqui.

[]s
Luca

velo

keller

sacanagem. isso é malvadesa! :evil:
mas Luca você sabia que estaria se expondo a isso…
e velo o cara pediu via pm pra que nao publicasse [apesar de ele ter publicado] muita sacanagem… :?

velo

MP


Olá

Esquece, isto tem dono. Eu apenas participei do projeto, publiquei por minha conte e risco. Só participei da idéia e não fui eu que escrevi o código (que pode ser melhorado). E além disso é apenas uma classe, não pode ser considerada uma API.

Se quiser usar tudo bem porque a idéia eu já tinha exposto desde meu primeiro post na thread, mas passar para a frente como uma API não faz sentido.

[]s
Luca

Como falei, naum usei nada do fonte q ele passou, nada mesmo. Tanto eh q naum tem o problema de abrir o serverSocket, fechar e abrir denovo… como disse, usei a ideia, mas nada de fonte.

Tava querendo ajudar, mas jah q o problema tah sendo grande vou tirar do ar.

VELO

Luca

Olá

Eu passei a ideía do serversocket de forma clara e ninguém fez fé. Eu insisti na idéia e aí uns poucos acreditaram. Eu coloquei o código em retribuição ao CV que acreditou e porque que ele é um cara que já ajudou muita gente aqui. Mas deixei nas mensagens que o código não era meu e que eu só participei das idéias para confecção. E idéias são mais importantes do como as variáveis são denominadas.

Precisava publicar? Eu não disse claramente para você usar privadamente?

[]s
Luca

Luca

Olá

Obrigado

[]s
Luca

velo

Luca:
Olá

Eu passei a ideía do serversocket de forma clara e ninguém fez fé. Eu insisti na idéia e aí uns poucos acreditaram. Eu coloquei o código em retribuição ao CV que acreditou e porque que ele é um cara que já ajudou muita gente aqui. Mas deixei nas mensagens que o código não era meu e que eu só participei das idéias para confecção. E idéias são mais importantes do como as variáveis são denominadas.

Precisava publicar? Eu não disse claramente para você usar privadamente?

[]s
Luca

Blz, jah apaguei o link sem publicidade naum evolui… mas dah um look no codigo, c vai ver, naum tem nada a ver.

F

Bah… tópico antigo que me quebrou o maior galho.

E realmente a solução funciona.

Até. :thumbup:

F

Concordo, tópico muito bom, me tireou muitas dúvidas, ajudou bastante!!!

abraço galera!

ferrarezi
Me basiei pra fazer uma rotina que checa se o firebird está rodando ou não...
public class fbcheck {

    public static void main(String[] args) {

   boolean runing = false;
   try
   {
        ServerSocket ss = new ServerSocket(3050);
        ss.close();
    } catch (Exception e){runing = true;}

    if (runing) JOptionPane.showMessageDialog(null,  "firebird rodando");
    else JOptionPane.showMessageDialog(null,  "firebird parado");
    }

}
bruxel

to escrevendo pra dizer q por ServerSocket não funcionou comigo. rsrsrs

dreampeppers99

bruxel:
to escrevendo pra dizer q por ServerSocket não funcionou comigo. rsrsrs

:shock: Como? Houve algum erro? tentou debugar pra ver o comportamento?

bruxel

procurei por erros, porem simplesmente passa, desabilitei o firewall, mas nada

dreampeppers99

Poste o código onde você abre a porta (lembre-se que esse objeto que abre a porta deve existir enquanto a aplicação existir).

bruxel
boolean runing = false;

        try
        {
            ServerSocket ss = new ServerSocket( 3050 );
        }

        catch ( Exception e )
        {
            runing = true;
        }

        if ( runing )
        {
            JOptionPane.showMessageDialog( null, "sistema ja esta rodando" );
        }

        else
        {
            JOptionPane.showMessageDialog( null, "abrindo sistema" );
        }
bruxel

alguma ideia dreampeppers99

dreampeppers99
try  
 {  
     ServerSocket ss = new ServerSocket( 3050 );  
 }

Talvez tenha haver com o ciclo de vida dessa "variavel local"! Continuo pensando que pra funcionar ss deveria ser um atributo de uma classe que não tem seu ciclo de vida interrompido durante a execução do sistema. Caso contrário o "servidor" é finalizado pelo GC e a porta fica livro para o SO fechá-la.
Sacou?

Tente criar algo assim:

public class Locker{
private static ServerSocket ss;

public void teste(){
        boolean runing = false;
        try
        {
            ss = new ServerSocket( 3050 );
        }

        catch ( Exception e )
        {
            runing = true;
        }

        if ( runing )
        {
            JOptionPane.showMessageDialog( null, "sistema ja esta rodando" );
        }
        else
        {
            JOptionPane.showMessageDialog( null, "abrindo sistema" );
        }
}

}
ferrarezi

Acho que você esqueceu de fechar a porta…

ss.close();

Por isso não está estourando a excessão, aí “runing” não fica verdadeiro…

bruxel

valeu dreampeppers99,

era isto mesmo

bruxel

ferrarezi:
Acho que você esqueceu de fechar a porta…

ss.close();

Por isso não está estourando a excessão, aí “runing” não fica verdadeiro…

não posso fechar a conexão senão o sistema fecha a porta, e ai sim sempre vou ter a porta liberada

Criado 7 de janeiro de 2005
Ultima resposta 28 de abr. de 2011
Respostas 56
Participantes 17