Accueil > > > INSTANCE UNIQUE D'UNE APPLICATION
INSTANCE UNIQUE D'UNE APPLICATION
Information sur la source
Description
La demande revenant souvent sur les forums (et ayant cherché moi-même par le passé), j'ai développé une classe permettant de gérer le fait qu'une application ne doit être lancée qu'une seule fois. Son utilisation est très simple, il suffit de construire un objet UniqueInstance, en passant en paramètre le port de communication à utiliser, le message à communiquer si une application est déjà lancée, et les actions à effectuer lorsqu'une nouvelle instance a essayé d'être lancée (typiquement, passer l'application courante en premier-plan).
Source
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.Scanner;
- import java.util.logging.Logger;
-
- /**
- * Cette classe permet d'assurer l'unicité de l'instance de l'application. Deux applications ne peuvent pas être lancées
- * simultanément. Voici un exemple typique d'utilisation :
- *
- * <pre>
- * // Port à utiliser pour communiquer avec l'instance de l'application lancée.
- * final int PORT = 32145;
- * // Message à envoyer à l'application lancée lorsqu'une autre instance essaye de démarrer.
- * final String MESSAGE = "nomDeMonApplication";
- * // Actions à effectuer lorsqu'une autre instance essaye de démarrer.
- * final Runnable RUN_ON_RECEIVE = new Runnable() {
- * public void run() {
- * if(mainFrame != null) {
- * // Si la fenêtre n'est pas visible (uniquement dans le systray par exemple), on la rend visible.
- * if(!mainFrame.isVisible())
- * mainFrame.setVisible(true);
- * // On demande à la mettre au premier plan.
- * mainFrame.toFront();
- * }
- * }
- * });
- *
- * UniqueInstance uniqueInstance = new UniqueInstance(PORT, MESSAGE, RUN_ON_RECEIVE);
- * // Si aucune autre instance n'est lancée...
- * if(uniqueInstance.launch()) {
- * // On démarre l'application.
- * new MonApplication();
- * }
- * </pre>
- *
- * @author rom1v
- */
- public class UniqueInstance {
-
- /** Port d'écoute utilisé pour l'unique instance de l'application. */
- private int port;
-
- /** Message à envoyer à l'éventuelle application déjà lancée. */
- private String message;
-
- /** Actions à effectuer lorsqu'une autre instance de l'application a indiqué qu'elle avait essayé de démarrer. */
- private Runnable runOnReceive;
-
- /**
- * Créer un gestionnaire d'instance unique de l'application.
- *
- * @param port
- * Port d'écoute utilisé pour l'unique instance de l'application.
- * @param message
- * Message à envoyer à l'éventuelle application déjà lancée, {@code null} si aucune action.
- * @param runOnReceive
- * Actions à effectuer lorsqu'une autre instance de l'application a indiqué qu'elle avait essayé de
- * démarrer, {@code null} pour aucune action.
- */
- public UniqueInstance(int port, String message, Runnable runOnReceive) {
- assert port > 0 && port < 1 << 16 : "Le port doit être entre 1 et 65535";
- assert message != null || runOnReceive == null : "Il y a des actions à effectuer => le message ne doit pas être null.";
- this.port = port;
- this.message = message;
- this.runOnReceive = runOnReceive;
- }
-
- /**
- * Créer un gestionnaire d'instance unique de l'application. Ce constructeur désactive la communication entre
- * l'instance déjà lancée et l'instance qui essaye de démarrer.
- *
- * @param port
- * Port d'écoute utilisé pour l'unique instance de l'application.
- */
- public UniqueInstance(int port) {
- this(port, null, null);
- }
-
- /**
- * Essaye de démarrer le gestionnaire d'instance unique. Si l'initialisation a réussi, c'est que l'instance est
- * unique. Sinon, c'est qu'une autre instance de l'application est déjà lancée. L'appel de cette méthode prévient
- * l'application déjà lancée qu'une autre vient d'essayer de se connecter.
- *
- * @return {@code true} si l'instance de l'application est unique.
- */
- public boolean launch() {
- /* Indique si l'instance du programme est unique. */
- boolean unique;
-
- try {
- /* On crée une socket sur le port défini. */
- final ServerSocket server = new ServerSocket(port);
-
- /* Si la création de la socket réussit, c'est que l'instance du programme est unique, aucune autre n'existe. */
- unique = true;
-
- /* Si il y a des actions à faire lorsqu'une autre instance essaye de démarrer... */
- if(runOnReceive != null) {
-
- /* On lance un Thread d'écoute sur ce port. */
- Thread portListenerThread = new Thread() {
-
- @Override public void run() {
- /* Tant que l'application est lancée... */
- while(true) {
- try {
- /* On attend qu'une socket se connecte sur le serveur. */
- final Socket socket = server.accept();
-
- /* Si une socket est connectée, on écoute le message envoyé dans un nouveau Thread. */
- new Thread() {
-
- @Override public void run() {
- receive(socket);
- }
- }.start();
- } catch(IOException e) {
- Logger.getLogger("UniqueInstance").warning("Attente de connexion de socket échouée.");
- }
- }
- }
- };
-
- /* Le Thread d'écoute de port est démon. */
- portListenerThread.setDaemon(true);
-
- /* On démarre le Thread. */
- portListenerThread.start();
- }
- } catch(IOException e) {
- /* Si la création de la socket échoue, c'est que l'instance de n'est pas unique, une autre n'existe. */
- unique = false;
-
- /* Si des actions sont prévues par l'instance déjà lancée... */
- if(runOnReceive != null) {
- /*
- * Dans ce cas, on envoie un message à l'autre instance de l'application pour lui demander d'avoir le
- * focus (par exemple).
- */
- send();
- }
- }
- return unique;
- }
-
- /**
- * Envoie un message à l'instance de l'application déjà ouverte.
- */
- private void send() {
- PrintWriter pw = null;
- try {
- /* On se connecte sur la machine locale. */
- Socket socket = new Socket("localhost", port);
-
- /* On définit un PrintWriter pour écrire sur la sortie de la socket. */
- pw = new PrintWriter(socket.getOutputStream());
-
- /* On écrit le message sur la socket. */
- pw.write(message);
- } catch(IOException e) {
- Logger.getLogger("UniqueInstance").warning("Écriture sur flux de sortie de la socket échoué.");
- } finally {
- if(pw != null)
- pw.close();
- }
- }
-
- /**
- * Reçoit un message d'une socket s'étant connectée au serveur d'écoute. Si ce message est le message de l'instance
- * unique, l'application demande le focus.
- *
- * @param socket
- * Socket connecté au serveur d'écoute.
- */
- private void receive(Socket socket) {
- Scanner sc = null;
-
- try {
- /* On n'écoute que 5 secondes, si aucun message n'est reçu, tant pis... */
- socket.setSoTimeout(5000);
-
- /* On définit un Scanner pour lire sur l'entrée de la socket. */
- sc = new Scanner(socket.getInputStream());
-
- /* On ne lit qu'une ligne. */
- String s = sc.nextLine();
-
- /* Si cette ligne est le message de l'instance unique... */
- if(message.equals(s)) {
- /* On exécute le code demandé. */
- runOnReceive.run();
- }
- } catch(IOException e) {
- Logger.getLogger("UniqueInstance").warning("Lecture du flux d'entrée de la socket échoué.");
- } finally {
- if(sc != null)
- sc.close();
- }
-
- }
-
- }
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Logger;
/**
* Cette classe permet d'assurer l'unicité de l'instance de l'application. Deux applications ne peuvent pas être lancées
* simultanément. Voici un exemple typique d'utilisation :
*
* <pre>
* // Port à utiliser pour communiquer avec l'instance de l'application lancée.
* final int PORT = 32145;
* // Message à envoyer à l'application lancée lorsqu'une autre instance essaye de démarrer.
* final String MESSAGE = "nomDeMonApplication";
* // Actions à effectuer lorsqu'une autre instance essaye de démarrer.
* final Runnable RUN_ON_RECEIVE = new Runnable() {
* public void run() {
* if(mainFrame != null) {
* // Si la fenêtre n'est pas visible (uniquement dans le systray par exemple), on la rend visible.
* if(!mainFrame.isVisible())
* mainFrame.setVisible(true);
* // On demande à la mettre au premier plan.
* mainFrame.toFront();
* }
* }
* });
*
* UniqueInstance uniqueInstance = new UniqueInstance(PORT, MESSAGE, RUN_ON_RECEIVE);
* // Si aucune autre instance n'est lancée...
* if(uniqueInstance.launch()) {
* // On démarre l'application.
* new MonApplication();
* }
* </pre>
*
* @author rom1v
*/
public class UniqueInstance {
/** Port d'écoute utilisé pour l'unique instance de l'application. */
private int port;
/** Message à envoyer à l'éventuelle application déjà lancée. */
private String message;
/** Actions à effectuer lorsqu'une autre instance de l'application a indiqué qu'elle avait essayé de démarrer. */
private Runnable runOnReceive;
/**
* Créer un gestionnaire d'instance unique de l'application.
*
* @param port
* Port d'écoute utilisé pour l'unique instance de l'application.
* @param message
* Message à envoyer à l'éventuelle application déjà lancée, {@code null} si aucune action.
* @param runOnReceive
* Actions à effectuer lorsqu'une autre instance de l'application a indiqué qu'elle avait essayé de
* démarrer, {@code null} pour aucune action.
*/
public UniqueInstance(int port, String message, Runnable runOnReceive) {
assert port > 0 && port < 1 << 16 : "Le port doit être entre 1 et 65535";
assert message != null || runOnReceive == null : "Il y a des actions à effectuer => le message ne doit pas être null.";
this.port = port;
this.message = message;
this.runOnReceive = runOnReceive;
}
/**
* Créer un gestionnaire d'instance unique de l'application. Ce constructeur désactive la communication entre
* l'instance déjà lancée et l'instance qui essaye de démarrer.
*
* @param port
* Port d'écoute utilisé pour l'unique instance de l'application.
*/
public UniqueInstance(int port) {
this(port, null, null);
}
/**
* Essaye de démarrer le gestionnaire d'instance unique. Si l'initialisation a réussi, c'est que l'instance est
* unique. Sinon, c'est qu'une autre instance de l'application est déjà lancée. L'appel de cette méthode prévient
* l'application déjà lancée qu'une autre vient d'essayer de se connecter.
*
* @return {@code true} si l'instance de l'application est unique.
*/
public boolean launch() {
/* Indique si l'instance du programme est unique. */
boolean unique;
try {
/* On crée une socket sur le port défini. */
final ServerSocket server = new ServerSocket(port);
/* Si la création de la socket réussit, c'est que l'instance du programme est unique, aucune autre n'existe. */
unique = true;
/* Si il y a des actions à faire lorsqu'une autre instance essaye de démarrer... */
if(runOnReceive != null) {
/* On lance un Thread d'écoute sur ce port. */
Thread portListenerThread = new Thread() {
@Override public void run() {
/* Tant que l'application est lancée... */
while(true) {
try {
/* On attend qu'une socket se connecte sur le serveur. */
final Socket socket = server.accept();
/* Si une socket est connectée, on écoute le message envoyé dans un nouveau Thread. */
new Thread() {
@Override public void run() {
receive(socket);
}
}.start();
} catch(IOException e) {
Logger.getLogger("UniqueInstance").warning("Attente de connexion de socket échouée.");
}
}
}
};
/* Le Thread d'écoute de port est démon. */
portListenerThread.setDaemon(true);
/* On démarre le Thread. */
portListenerThread.start();
}
} catch(IOException e) {
/* Si la création de la socket échoue, c'est que l'instance de n'est pas unique, une autre n'existe. */
unique = false;
/* Si des actions sont prévues par l'instance déjà lancée... */
if(runOnReceive != null) {
/*
* Dans ce cas, on envoie un message à l'autre instance de l'application pour lui demander d'avoir le
* focus (par exemple).
*/
send();
}
}
return unique;
}
/**
* Envoie un message à l'instance de l'application déjà ouverte.
*/
private void send() {
PrintWriter pw = null;
try {
/* On se connecte sur la machine locale. */
Socket socket = new Socket("localhost", port);
/* On définit un PrintWriter pour écrire sur la sortie de la socket. */
pw = new PrintWriter(socket.getOutputStream());
/* On écrit le message sur la socket. */
pw.write(message);
} catch(IOException e) {
Logger.getLogger("UniqueInstance").warning("Écriture sur flux de sortie de la socket échoué.");
} finally {
if(pw != null)
pw.close();
}
}
/**
* Reçoit un message d'une socket s'étant connectée au serveur d'écoute. Si ce message est le message de l'instance
* unique, l'application demande le focus.
*
* @param socket
* Socket connecté au serveur d'écoute.
*/
private void receive(Socket socket) {
Scanner sc = null;
try {
/* On n'écoute que 5 secondes, si aucun message n'est reçu, tant pis... */
socket.setSoTimeout(5000);
/* On définit un Scanner pour lire sur l'entrée de la socket. */
sc = new Scanner(socket.getInputStream());
/* On ne lit qu'une ligne. */
String s = sc.nextLine();
/* Si cette ligne est le message de l'instance unique... */
if(message.equals(s)) {
/* On exécute le code demandé. */
runOnReceive.run();
}
} catch(IOException e) {
Logger.getLogger("UniqueInstance").warning("Lecture du flux d'entrée de la socket échoué.");
} finally {
if(sc != null)
sc.close();
}
}
}
Conclusion
Exemple d'utilisation...
// Port à utiliser pour communiquer avec l'instance de l'application lancée.
final int PORT = 32145;
// Message à envoyer à l'application lancée lorsqu'une autre instance essaye de démarrer.
final String MESSAGE = "nomDeMonApplication";
// Actions à effectuer lorsqu'une autre instance essaye de démarrer.
final Runnable RUN_ON_RECEIVE = new Runnable() {
public void run() {
if(mainFrame != null) {
// Si la fenêtre n'est pas visible (uniquement dans le systray par exemple), on la rend visible.
if(!mainFrame.isVisible())
mainFrame.setVisible(true);
// On demande à la mettre au premier plan.
mainFrame.toFront();
}
}
});
UniqueInstance uniqueInstance = new UniqueInstance(PORT, MESSAGE, RUN_ON_RECEIVE);
// Si aucune autre instance n'est lancée...
if(uniqueInstance.launch()) {
// On démarre l'application.
new MonApplication();
}
Historique
- 28 octobre 2006 14:37:48 :
- problèmes d'espacements dans le code source copié
Sources du même auteur
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
Unique instance de programme [ par indiana_jules ]
Salut, j'aimerais pouvoir n'avoir qu'une seule instance de mon programme qui tourne. Existe-t-il un moyen propre de le faire ? (sans passer par un Ser
java et une application windows [ par benmor ]
Bonjours à tous,Donc voila mon probleme, j'ai fait une petite application java afin de procèder a des actions répétitives.Cette ap
transformation d'une application java en une applet [ par steflanul ]
bonsoir!! je suis désolé mais je n'arrive toujours pas à transformer mon application en une applet! il me dit toujours apllet non initi
Tester une application J2EE [ par lnp ]
Salut tout le monde,On m'a dit qu'il existe des applications qui testent les applications J2EE...Est-ce que quelqu'un peut me dire où trouver ce
comment configueur un serveur smtp pour une application java (mail) [ par zazou1 ]
salut a tous,vous pouvez m'aidez pour configueur un serveur smtp sur windows XP (pour une application java (e_mail)).merci d'avance.
Deploiment application erreur [ par mael974 ]
Bonjour a tous.g trjs un ti souci lors du deploiement de mon appli (sous tomcat) !! Voici la structure (tres simple) : ds le web_apps jai mon reper
chat/FTP sécurisé [ par kabaouhanen ]
pour réaliser une application chat/FTP sécurisée(cryptographie) quelle est le language le plus convenable pour cette application. Merci
application web I THINK [ par khaledirb7 ]
Je doit développer une applicationen adoptant une architecture trois tiers , je veut utiliser jbuilder comme outil de développementet o
ajax et servlet [ par bf83 ]
bonjour tout le monde,je fais une application avec les servlets et je veux utiliser la notion d'ajax cda l'objet xmlhttprequest .je sais les utilsier
[J2ME] Compilation OK ==> nokia pas OK [ par JuJu ]
Bonjour, j'ai un problème avec une application J2ME. L'application marche à la perfection sur emulateur Wireless toolkit mais est inutilisab
|
Derniers Blogs
UNE JOLIE-HORLOGE ET PAS QU'UN PEU !UNE JOLIE-HORLOGE ET PAS QU'UN PEU ! par neodante
Pour les possesseurs d'iPhone, ça y est Bijin Tokei - qui se traduit littéralement en Français par " Jolie Horloge " - est arrivé et GRATUITEMENT s'il vous plaît ! Après la version Tokyo, Hokkaido, night club, racing, Gal, "pour les mademoiselles'", . voi...
Cliquez pour lire la suite de l'article par neodante TECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICESTECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICES par ROMELARD Fabrice
Animé par: Gaetan Bouveret et Julien Chomarat Business Connectivity Services (BCS) est dans SharePoint 2010 la version 2 de Business Data Catalog (BDC dans SharePoint 2007). Il s'agit de la solution permettant de visualiser des données provenan...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice [DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE par orion
Comme de nombreux geek, je suis un grand amateur de série TV et je rate régulièrement des épisodes de mes séries préférés. Une solution s'offre à vous avec ce merveilleux site : Tv Gorge - www.tvgorge.com Moteur de recherche à l'appui, vous pouvez ...
Cliquez pour lire la suite de l'article par orion TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|