How to ensure there is only one instance of the application?


#1

Please give me some ideas.
(on windows ,rust)

------This is a stupid question…


#2

I think we need more context to be able to help.
The question is to general to be able to give you an advice.

Do you need to ensure there is a single instance of the application or do you ask about the singleton pattern?
In general it is advised to avoid the Singleton pattern since it makes your application hard to maintain, perform worse in most cases and hard to debug.

I update too: It’s not a stupid question, it just needs to offer more context.


#3

Yes, i need to ensure there is a single instance of the application.


#4

It’s not solved yet :slight_smile:
I think it’s a very good question, I am also curios how to do that.
I haven’t seen yet a library that offers this(on Windows).


#5

I believe the usual approach is to create something system-wide to identify the “current” instance. This could be a top-level window with a specific name and class, or some global named pipe, or a file in a well-known location, or listening on a socket…

I don’t know of any “official” way of doing this.


#6

Not that I do not have a windows machine readily available to test, but AFAIK this works by acquiring a named Mutex from the Windows kernel using this api. Note that these Mutexes can be global. If a second process tries to acquire that Mutex, this should fail.

I’m not sure there are any bindings for that functionality already.


#7

The problem there is that I don’t think you can use that to communicate with the existing process. Usually, when you’re only allowing one instance, you want to pass information on further invocations to the existing process so they can handle them.

But if you only want to block additional instances, that would probably do the job.


#8

Obviously. For that, you will probably have to use other facilities or combine two. It seems to be the cleanest way described in the MSDN blogs, though :). ( https://blogs.msdn.microsoft.com/abhinaba/2008/05/01/ensuring-only-one-instance-of-an-application-can-be-run-and-then-breaking-that-approach/ )


#9

I am currently working on a Rust library that provides a lightweight wrapper around Windows kernel objects and handles. It is still in a very early stage of development (no documentation or tests yet). Right now it includes wrappers for (named) mutexes, events, semaphores, waitable timers, file mappings (shared memory) and anonymous pipes. Named pipes are on the to-do list.

If you only need to check if another instance of your program is already running, using any named kernel object will suffice (for example a mutex). If you also want to pass information to the other instance, a combination of a named mutex and a named file mapping (shared memory) will work. Alternatively, you could use a named pipe.

If anyone is interested, I will put my code on GitHub and provide an example. Expect a lot of APIs to change though. Alternatively you could look at another crate called miow and use NamedPipe from this crate or just use the raw Windows API bindings from winapi and kernel32-sys.


#10

I’d think the best bet is to create a file in the temp directory that gets deleted when the program exits. If the file exists when starting tell the user that it appears another instance is running and ask if they are sure they want to continue.

It’s not fool proof but if you don’t crash the likelihood of a left over instance of the file is low. And if they do start a second instance the consequences are their own damn fault. :slight_smile:

You could even write the PID to the file, so that when starting you could check if that PID is still active. You would probably have to call some Windows APIs to find out that information.


#11

In that case, couldn’t you just create a new file with exclusive (write) access and keep the file open until the process exits? A second instance would not be able to create/open the file until the first instance terminates. It’s not even necessary to delete the file afterwards.


#12

Even better, that’s a great idea.


#13

An example using my library. Note that it doesn’t matter what kind of named kernel object we use. I chose a mutex but the mutex’s functionality is not actually used (although it could be really useful).

# Cargo.toml
# ...

[dependencies]
minwin = { git ="https://github.com/Jascha-N/minwin-rs" }
// src/main.rs

extern crate minwin;

use std::thread;
use std::time::Duration;

use minwin::named::CreateNamedError;
use minwin::prelude::*;
use minwin::sync::Mutex;

fn main() {
    match Mutex::create_named("MyUniqueObjectName") {
        Ok(_) => {
            println!("First instance!");
            // Program code goes here. The sleep statement is just a placeholder.
            thread::sleep(Duration::from_secs(10));
        }
        Err(CreateNamedError::AlreadyExists(_)) => {
            println!("Process already running!");
        }
        Err(error) => {
            println!("An error occurred: {}", error);
        }
    }
}

The Ok match clause can be written more explicitly:

// ...
        Ok(mutex) => {
            println!("First instance!");
            // Program code goes here. The sleep statement is just a placeholder.
            thread::sleep(Duration::from_secs(10));
            mem::drop(mutex);
        }
// ...

Again, this library is still in a very unfinished state and the API is almost guaranteed to change.


#14

What is the mem::forget() supposed to do? If it does not release the mutex (which I assume), why not just hold it explicitly until the process exits? Or did you mean drop()?


#15

Oops, I actually meant mem::drop().


#16

This version actually tries to acquire a lock and is possibly more robust (?), but I don’t think it’s necessary.

extern crate minwin;

use std::{mem, thread};
use std::time::Duration;

use minwin::named::CreateNamedError;
use minwin::prelude::*;
use minwin::sync::{TryLockError, Mutex};

fn main() {
    let mutex = match Mutex::create_named("MyUniqueObjectName") {
        Ok(mutex) | Err(CreateNamedError::AlreadyExists(mutex)) => mutex,
        Err(error) => panic!("An error occurred creating the mutex: {}", error)
    };

    let lock = match mutex.try_lock() {
        Ok(guard) | Err(TryLockError::Abandoned(guard)) => guard,
        Err(TryLockError::WouldBlock) => panic!("Process already running!"),
        Err(error) => panic!("An error occurred while trying to acquire the mutex: {:?}", error)
    };
    
    println!("First instance!");
    // Program code goes here. The sleep statement is just a placeholder.
    thread::sleep(Duration::from_secs(10));

    mem::drop(lock);
}

(Don’t abuse panics like I did in this example.)


#17

You could return Ok(guard) in the first branch and an Err() in the following and append an expect(error) to make it more rustic.

Edit: you would need to find a way for printing the error then, or is this already done by expect()?


#18
  • temp file
    test for locked status by other application (keep lock till application ended, thus it doesn’t matter if the app crashes and the file is still existent)
  • local port
    can be a problem if the port is already claimed by another application
  • registry entry under windows with a link to the current PID: check for existence
  • task read