Preventing multiple instance standalone desktop gui applications


K

Kent Yang

I need to have only one instance of a Desktop GUI application running.
What is the best way to do this? The only answer I can find
searching throught the archives was to use a socket. Is this the best
way?

I thought about using rmi (registry) and binding a unique name however
the problem is if the appliction start the registry, when it exits, it
takes the registry down with it.

Is there a cleaner way to do this. I've seen this in several IDE(s)
Eclipse and JBuilder. How is it done in those apps?

Thanks in advance,

Kent
 
Ad

Advertisements

P

Paul Lutus

Kent said:
I need to have only one instance of a Desktop GUI application running.
What is the best way to do this? The only answer I can find
searching throught the archives was to use a socket. Is this the best
way?

That depends. I often use a flag file. This has the advantage that, in a
multi-user environment, each user has a separate flag file, so each user
can only have one instance running, but there can be as many single
instances as there are users.

I put the flag file in the user's home directory under a subdirectory with
the same name as the application, a scheme that has been worked out in
Linux/Unix environments over time, and one that works fine in Windows as
well.
 
S

Steve W. Jackson

Paul Lutus said:
:Kent Yang wrote:
:
:> I need to have only one instance of a Desktop GUI application running.
:> What is the best way to do this? The only answer I can find
:> searching throught the archives was to use a socket. Is this the best
:> way?
:
:That depends. I often use a flag file. This has the advantage that, in a
:multi-user environment, each user has a separate flag file, so each user
:can only have one instance running, but there can be as many single
:instances as there are users.
:
:I put the flag file in the user's home directory under a subdirectory with
:the same name as the application, a scheme that has been worked out in
:Linux/Unix environments over time, and one that works fine in Windows as
:well.

I've used a similar technique, though i call it a lock file. In fact, I
go further and apply a FileLock on the file, which I hold until I'm
ready to shut down. If the lock attempt fails, it's because the file is
locked by another instance. If it succeeds, than any pre-existing file
could've been left behind by a crashed instance of my app (rare though
that is). It works well for me, with the odd caveat that I can actually
remove the file manually on Linux while the app is running to bypass
this restriction.

= Steve =
 
J

Jean-Francois Briere

If you have JDK1.4+, you can use a flag file with a lock mechanism.
Here is a little utility class that create/lock a file on user.home folder
and with name based on the app name provided:

--------------------------------------------------------------------------------
import java.io.*;
import java.nio.channels.*;

public class UniqueApp
{
private String appName;
private File file;
private FileChannel channel;
private FileLock lock;

public UniqueApp(String appName) {
this.appName = appName;
}

public boolean isAppActive() {
try {
file = new File(System.getProperty("user.home"), appName + ".tmp");
channel = new RandomAccessFile(file, "rw").getChannel();

try {
lock = channel.tryLock();
}
catch (OverlappingFileLockException e) {
closeLock();
return true;
}

if (lock == null) {
closeLock();
return true;
}

Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
closeLock();
deleteFile();
}
});

return false;
}
catch (Exception e) {
closeLock();
return true;
}
}

private void closeLock() {
try {
lock.release();
}
catch (Exception e) {
}
try {
channel.close();
}
catch (Exception e) {
}
}

private void deleteFile() {
try {
file.delete();
}
catch (Exception e) {
}
}
}
--------------------------------------------------------------------------------

And here is a simple test:

--------------------------------------------------------------------------------
public class UniqueAppTest {
public static void main(String[] args) {
new UniqueAppTest().test();
}

void test() {
UniqueApp ua = new UniqueApp("MyAppId");

if (ua.isAppActive()) {
System.out.println("App is already active.");
}
else {
System.out.println("App is NOT already active.");
try {
System.out.print("Hit <Enter> key to finish");
System.in.read();
}
catch (Exception e) {
}
}
}
}
--------------------------------------------------------------------------------
 
F

FISH

I need to have only one instance of a Desktop GUI application running.
What is the best way to do this? The only answer I can find
searching throught the archives was to use a socket. Is this the best
way?


It's a commonly used technique, as it allows the second instance to
communicate with the first, passing over responsibility for opening
any files set are arguments.


-FISH- ><>
 
J

Jacob

Kent said:
I need to have only one instance of a Desktop GUI application running.
What is the best way to do this? The only answer I can find
searching throught the archives was to use a socket. Is this the best
way?

I'll not add on to the fine answers already given.

But just because something is technically possible
doesn't necesserily mean it is a good idea. As a
user I find this kind of program behaviour a pain in
the neck. Often it is possible to change the application
model/logic so it _can_ coexist with other instances;
Possibly on the expence of programming effort.

I don't say it is possible in your case, but please
make sure you _try_ before you chose the simple
way out :)
 
Ad

Advertisements

P

Paul Lutus

Jacob said:
I'll not add on to the fine answers already given.

But just because something is technically possible
doesn't necesserily mean it is a good idea. As a
user I find this kind of program behaviour a pain in
the neck. Often it is possible to change the application
model/logic so it _can_ coexist with other instances;
Possibly on the expence of programming effort.

I don't say it is possible in your case, but please
make sure you _try_ before you chose the simple
way out :)

There can be excellent reasons to do this. It is not necessarily a sign of
prorgammer laziness. If the program reads and writes to its own
configuration file, it is very confusing to a user to have multiple
instances running, and it seems inconsistent to spend time reconfiguring an
application, only to have the changes wiped out because of a minimized
extra instance that is closed automatically when the system is shut down.

For example, that is why my Web editor Arachnophilia, very
user-configurable, uses this approach. Earler versions allowed multiple
instances, and this was a disaster and a clear programming error. People
would spend hours reconfiguring the user interface, only to see their work
wiped out in a flash.

This should not prevent multiple users from having their own instances, but
it should prevent a single user from launching more than one.
 
S

steve

I need to have only one instance of a Desktop GUI application running.
What is the best way to do this? The only answer I can find
searching throught the archives was to use a socket. Is this the best
way?

I thought about using rmi (registry) and binding a unique name however
the problem is if the appliction start the registry, when it exits, it
takes the registry down with it.

Is there a cleaner way to do this. I've seen this in several IDE(s)
Eclipse and JBuilder. How is it done in those apps?

Thanks in advance,

Kent

use a small server program. open a port. ( less than 20 lines of code)
when you launch your app , check if you get an answer on the port, if so
there is already an app running.
if not then launch a small server.

DO NOT use a flag file, if your app crashes or the disk gets corrupted, all
sorts of things can happen. ( i have tired many different forms of flag files
etc, but there is always one user who manages to beat the system, or corrupt
it)

With the server method, it always cleans up on the JVM exit, same with a
crash.

JustOne StartTracker = new JustOne();

if (StartTracker.doit() == false) {
try {
.........
program call routines
}
}
else
//it is already running so exit
StartTracker.stopTask();
System.exit(1);
}





package SimpleServer;

import java.io.*;

import java.net.*;


//this package starts a java server listening on port 8181
//it does this to stop the java program from being launched more than once
// as the user only needs 1 copy running, also it causes client memory
issues. if
//more than 1 copy of the program is running
public class SimpleServer extends Thread {
public static final int port = 8181;
ServerSocket serverSocket = null;
Socket clientSocket = null;

public void run() {
try {
// Create the server socket
serverSocket = new ServerSocket(port, 1);

while (true) {
// Wait for a connection
clientSocket = serverSocket.accept();

// System.out.println("*** Got a connection! ");
clientSocket.close();
}
} catch (IOException ioe) {
System.out.println("Error in SimpleServer: " + ioe);
System.exit(0); // we can do nothing else
}
}
}


package Server;

import SimpleServer.*;

import java.io.*;

import java.net.*;


//we have not started the error logger yet, ( we cannot, in case there is a
second instance running
//therefore we have to rely on the normal system errror caller
public class JustOne {
SimpleServer sds = null;
boolean keepRunning = true;
private boolean status = true; //say it is already running
private Runnable r = null;

//this is to be called when the program finally exits.
public void stopTask() {
keepRunning = false;
}

public boolean doit() {
status = false; // say it is only the first copy

try {
Socket clientSocket = new Socket("localhost",
SimpleServer.port);

status = true;
} catch (Exception e) {
//this starts a new thread before the modal
r = new Runnable() {
public void run() {
newServer();
}
};
new Thread(r).start();
status = false; // say it is only the first copy
}

// finally {
return status;

// }
}

public void newServer() {
sds = new SimpleServer();
sds.start();

while (keepRunning == true) {
try {
// System.out.print(".");
Thread.sleep(5 * 60);
} catch (Exception e) {
e.printStackTrace();
System.exit(0); // we can do nothing else
}
}
}
}
 
J

Jacob

Paul said:
There can be excellent reasons to do this. It is not necessarily a sign of
prorgammer laziness. If the program reads and writes to its own
configuration file, it is very confusing to a user to have multiple
instances running, and it seems inconsistent to spend time reconfiguring an
application, only to have the changes wiped out because of a minimized
extra instance that is closed automatically when the system is shut down.

All programs (of a certain size and complexity) access persistent
session information. That a program has this feature is no excuse
to make it a "singelton" application.

Technically, session information is no different from _data_ (as
stored in a database). If concurrent modification is an issue
then your session storage strategy is to simple.

But of course, the user runs a certain *risk* when launching
several instances of a program that stores configuration. This
is a risk that he is aware of and must take the consequences of.
The user should understand that when changing color in app A, exiting
app A (=> store settings), and then exiting app B (=> store settings),
then the color setting will be lost for the next session. This
will be the user responsibility. The programmer is responsible for
ensuring that the session info is never corrupted it any way.
It takes some effort.

I have many standard programs running that solves this problem
just fine, and I have written quite a few as well.
 
P

Paul Lutus

Jacob said:
All programs (of a certain size and complexity) access persistent
session information. That a program has this feature is no excuse
to make it a "singelton" application.

This is not an excuse, this is a necessity. One program instance can store
state information, end of story.
 
L

Larry Barowski

steve said:
use a small server program. open a port. ( less than 20 lines of code)
when you launch your app , check if you get an answer on the port, if so
there is already an app running.
if not then launch a small server.

The simple server you presented does not allow two users
(or two accounts) logged into one machine at the same time
to use the application. You also need to consider that any
chosen port may be used by another application. These
problems can be solved, but I would still recommend a flag
file. If the app won't run on less than Java 1.4, using a lock
as mentioned elsewhere in this thread will eliminate the
problem of a left-over flag file after a crash. Otherwise,
just give the user the option of running anyway (with a
stern warning to make sure the app is not already running)
if the lock file is present.
 
Ad

Advertisements

S

steve

The simple server you presented does not allow two users
(or two accounts) logged into one machine at the same time
to use the application. You also need to consider that any
chosen port may be used by another application. These
problems can be solved, but I would still recommend a flag
file. If the app won't run on less than Java 1.4, using a lock
as mentioned elsewhere in this thread will eliminate the
problem of a left-over flag file after a crash. Otherwise,
just give the user the option of running anyway (with a
stern warning to make sure the app is not already running)
if the lock file is present.

Jez.
1. the port can be reconfigured.
2. he did not request 2 users on the same machine, but to prevent multiple
instances of the application from running.

a simple call to "system properties " to get the user can fix this.


allowing a user to run multiple instances "with a stern warning" is just
stupid, It would require hte user to have intimate knowlege of the app , and
if it is middleware, could cause a serious problem.

flag files do not work reliably they rely on a non-real world situation
sorry!!

steve
 
S

steve

All programs (of a certain size and complexity) access persistent
session information. That a program has this feature is no excuse
to make it a "singelton" application.

Technically, session information is no different from _data_ (as
stored in a database). If concurrent modification is an issue
then your session storage strategy is to simple.

But of course, the user runs a certain *risk* when launching
several instances of a program that stores configuration. This
is a risk that he is aware of and must take the consequences of.
The user should understand that when changing color in app A, exiting
app A (=> store settings), and then exiting app B (=> store settings),
then the color setting will be lost for the next session. This
will be the user responsibility. The programmer is responsible for
ensuring that the session info is never corrupted it any way.
It takes some effort.

I have many standard programs running that solves this problem
just fine, and I have written quite a few as well.

you obviously have only ever written programs for Einstein like users.

A recent (real) case to highlight this:

A java program running on linux accessing an oracle database.
program did not start fast enough, for said user. ( startup time about 10
seconds)


at about 5 seconds Said used clicked on program icon 20 times to make it go
faster.

multiple applications launched, java kicked in linux swap files , after 5
minutes use switched off computer at power button, because it had "hung"

result corrupted disk & corrupted flag files ( not cleaned up) + 20 unclosed
connections to the oracle database.


conclusions:

1.A user can find a way to **** any system.
2. Users are generally morons.

Steve
 
L

Larry Barowski

steve said:
Jez.
1. the port can be reconfigured.

You missed my point. The code you provided was too simple, but
you did not say "Of course, this is not sufficient to use in a real
world program."
2. he did not request 2 users on the same machine, but to prevent multiple
instances of the application from running.

He did not specify preventing multiple instances per system
or per-user, so we can assume neither. When you presented
a solution, you did not indicate that it was per-system.

If this is an end-user application, then the goal is probably a
single instance per-user. User-switching on XP means that
even Windows-only apps must now handle multiple users
per system.
a simple call to "system properties " to get the user can fix this.

Well, sort of. You need some method of assigning different
ports to different users.
allowing a user to run multiple instances "with a stern warning" is just
stupid, It would require hte user to have intimate knowlege of the app , and
if it is middleware, could cause a serious problem.

No, it's "just stupid" only if the result could be disastrous.
If the result could be the application not remembering
the high score for a video game, then it is quite
reasonable.
flag files do not work reliably they rely on a non-real world situation

Using file locking (Java 1.4) on flag files is just as reliable
as using sockets.
 
K

Kent Yang

Thanks everyone for all the great responses.

My concern with socket approach is that one port will be dedicated to
the application. I know its only one port / resource. The other
concern is that I had socket applications that crash, and because it
wasn't close properly, the socket can not be reused for a little while
(probably because the OS resource not cleanup). So the port gets lock
out until a system restart or until the OS catches up.

The sample example posted by Jean-Francois Briere works great. I owe
you a beer.

It may sound like a strange request for this type of application
feature but there are instances where this is beneficial to very basic
users. Also, precedence have set by applications such as IDE(s),
JBuilder for example. I am guessing they use some native code to
bring up the current running instance.

Thanks again everyone for all the great responses.

Kent
 
G

Gordon Beaton

My concern with socket approach is that one port will be dedicated
to the application. I know its only one port / resource. The other
concern is that I had socket applications that crash, and because it
wasn't close properly, the socket can not be reused for a little
while (probably because the OS resource not cleanup). So the port
gets lock out until a system restart or until the OS catches up.

In practice, reusing a server port is never a problem.

Even if the ServerSocket constructor doesn't set SO_REUSEADDR (i.e.
setReuseAddress(true)) before binding the socket, you can. Although I
believe it does by default.

/gordon
 
Ad

Advertisements

S

steve

You missed my point. The code you provided was too simple, but
you did not say "Of course, this is not sufficient to use in a real
world program."


He did not specify preventing multiple instances per system
or per-user, so we can assume neither. When you presented
a solution, you did not indicate that it was per-system.

If this is an end-user application, then the goal is probably a
single instance per-user. User-switching on XP means that
even Windows-only apps must now handle multiple users
per system.


Well, sort of. You need some method of assigning different
ports to different users.


No, it's "just stupid" only if the result could be disastrous.
If the result could be the application not remembering
the high score for a video game, then it is quite
reasonable.


Using file locking (Java 1.4) on flag files is just as reliable
as using sockets.

O.K you obviously are set in your ways (as am I), and are determined to find
every bone in the chicken egg
 
Ad

Advertisements

K

Kyle Cordes

Larry Barowski said:
chosen port may be used by another application. These
problems can be solved, but I would still recommend a flag
file. If the app won't run on less than Java 1.4, using a lock
as mentioned elsewhere in this thread will eliminate the
problem of a left-over flag file after a crash. Otherwise,


I use this approach, with very good results.

There are two issues with the socket approach, which while they might not
come up for some users, made that approach inappropriate for my project:

1) Some "personal" firewall software will put up a warning message when a
piece of software opens a listening socket, resultings in confused users and
support calls

2) Some customers like to deploy software using Terminal Services, Citrix,
etc., where there can be many users on one machine; each needs to be able to
run their own copy of the software, but none should be able to run more than
one copy. This is automatic with the lock-file-in-home-dir approach, but
with a listening socket, you'd need to find some way to have each user use a
differnet listening socket.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top