Boa noite a todos!
Tenho esta dúvida: Como impedir uma nova execução do aplicativo que já está rodando? (ou seja, ao invés de rodar um novo, ele retorna o que já está em execução)
Grato pela ajuda!
Boa noite a todos!
Tenho esta dúvida: Como impedir uma nova execução do aplicativo que já está rodando? (ou seja, ao invés de rodar um novo, ele retorna o que já está em execução)
Grato pela ajuda!
Bom, eu não sei exatamente sobre como retornar o que já está em execução. Porém conheço duas estratégias que utilizam para evitar duas instancias de um mesmo programa de rodar ao mesmo tempo.
A primeira é manter um arquivo locked para a aplicação, ao tentar rodar ou instancia e tentar dar o lock ele vai se deparar com um problema e assumir que já há uma instancia rodando. Essa eu sei que tem alguns problemas, não me lembro exatamente qual.
A outra é utilizar um socket para a instancia, e funciona de forma semelhante, ao tentar rodar outra instancia é verificado que o socket já está ocupado.
Algo que achei e que parece retornar a instancia que está rodando ao tentar executar outra:
http://www.rbgrn.net/content/43-java-single-application-instance
Não cheguei a testar, mas estava num fórum americano que confio bastante…
Valeu
Com Java não sei se é possível ver se um determinado programa está em execução, mas com C, usando a API do Windows, com toda certeza você consegue implementar algo. Você pode criar uma DLL em C que faça esta verificação, e usa-la com Java. Ou, se preferir, você pode fazer uma gambiarra. Ao abrir seu programa, você cria um arquivo cujo conteúdo é 1. Ao fechar, você apaga todo o conteúdo deste arquivo, e escreve 0 nele. Assim, sempre ao abrir seu programa, faça a leitura verifique o conteúdo deste arquivo. Se for 1, é porque já têm uma instância aberta, se for 0, não está aberto e você pode abrir normalmente. Só que como eu disse, é uma típica gambiarra, não recomendo que o faça.
valeu gente!
vou dar uma estudada neste assunto…
tem uma boa solucao do luca com sockets… pesquise aqui…
Você pode utilizar os parametros de inicialização da JVM, conforme abaixo:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=6676
Com isso só será possível um único processo utilizando a porta 6676…
oi joão!
eu coloco este código em qual parte do meu aplicativo?
Olá SandroSoftwares, blz?
Você pode adicionar estas informações no .bat ou .sh que inicia sua app…
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=6676 -cp $CLASS_PATH -jar RoboTeste.jar
Sua aplicação é um processo batch (robô) ??
cara, minha aplicação é um software de cadastro… eu não tenho um bat que inicia… pode me explicar melhor?
Se sua aplicação é Java, você pode utilizar a lista de parametros apresentada pelo link abaixo no momento da inicializção da JVM onde seu aplicativo irá ser executado.
Essa solução funciona bem, pois somente um único socket pode estar aberto numa porta por vez.
1. Abra um ServerSocket numa porta qualquer;
2. Se o Socket não abrir, dê o erro e saia da aplicação.Essa solução funciona bem, pois somente um único socket pode estar aberto numa porta por vez.
Exato! Era esta a solução do luca
1. Abra um ServerSocket numa porta qualquer;
2. Se o Socket não abrir, dê o erro e saia da aplicação.Essa solução funciona bem, pois somente um único socket pode estar aberto numa porta por vez.
Poderia exemplificar com código?
Nossa, precisava mesmo?
Declare seu serversocket como:
private static ServerSocket s;
try {
s = new ServerSocket(9581);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Desculpe, mas só uma aplicação pode ser executada por vez.");
}
E não esqueça de fazer “close” no socket antes de fechar a aplicação.
1. Abra um ServerSocket numa porta qualquer;
2. Se o Socket não abrir, dê o erro e saia da aplicação.Essa solução funciona bem, pois somente um único socket pode estar aberto numa porta por vez.
Realmente funciona legal, também usamos esta idéia em nossos sistemas =)
Só quero adicionar uma observação. O brunoskrebs sugeriu você utilizar um arquivo de lock, e isso para mim é a melhor solução.
O eclipse gerencia o uso dos workspaces através de lock files (arquivo .lock dentro do diretório .metadata). Esse é o jeito que a maioria dos processos em unix também utilizam para evitar o processo repetido.
O problema disso é o programa terminar sem “limpar” o arquivo de lock. Isso vai causar o arquivo de lock ficar lá “sozinho” e vai parecer que você tem alguma instância executando, quando na verdade, não tem. A resolução disso é perguntar ao usuário se ele vê alguma outra instância executando e perguntar o que fazer com isso: sair da aplicação ou “roubar” o lock para si. O método de socket também tem problemas: se você não fechar o socket “direito” ou dependendo de como abre, ele pode ficar em “closeWait” e ocupar a porta quando você for abrir de novo logo em seguida.
Se for útil, eu posto depois um código-exemplo de como fazer isso, mas deve ser simples mesmo:
File lockFile = new File(".lock");
if (lockFile.exists()) {
//perguntar para o usuario se rouba o lock ou não
if (!roubar) {
throw new IllegalStateException("Instância em execução");
}
}
lockFile.deleteOnExit();
//segue a vida
Você pode evitar esse estado do socket chamando:
seuSocket.setReuseAddr(true);
http://download.oracle.com/javase/1.5.0/docs/api/java/net/ServerSocket.html#setReuseAddress(boolean)
O problema é do arquivo de lock é que alguns SOs mais antigos podem deixar o arquivo travado até que o computador seja reiniciado. Eu não me preocuparia com isso hoje em dia, mas era bastante chato na época do Windows 98.
Não quis dizer usar File.lock(). Só a existência do arquivo seria a trava. Usar File.lock() realmente é problemático e não deveria ser utilizado para isso/não tem para quê. Minha sugestão é só usar a existência do arquivo. Usando o .deleteOnExit(), a VM limpa o arquivo quando o programa terminar “bonito”.
Nesse caso nada garante que o usuário não irá abrir uma nova instância. Ele pode sozinho apagar o outro arquivo do disco ou, no código que você sugeriu, responder “sim” e abrir a segunda instância por conta própria.
Acho que tudo depende do quanto você confie no usuário, e o quão importante é impedir duas instâncias de abrirem simultaneamente.
rsrsrs… pra mim também precisava! mas agora tá rodando legal!
Inclusive ViniGodoy eu coloquei a chamada dentro do metodo main e o resultado é o seguinte:
Ele dá a mensagem quando tento executar simultaneamente…
mas eu não precisei colocar o “close” para fechar… (quando fecho o programa no X, automaticamente já me parece que o close é feito…)
Valeu mesmo!
Valeu a dica.
O único cuidado seria em relação a codificação da porta.
Funcionou perfeitamente.