wails icon indicating copy to clipboard operation
wails copied to clipboard

Integrated Single Process Option of Wails app

Open Purple-CSGO opened this issue 3 years ago • 2 comments

Describe the solution you'd like

Currently wails does not have integrated option to make sure only 1 process is running at a time. Pls consider add this feature to wails. Thx.

Purple-CSGO avatar Apr 25 '22 06:04 Purple-CSGO

In the meantime, you can do something like this, not sure if it is a good method, but it seem to work for me.

// Create a mutex to keep a program running on single instance. Return error if program is already running.
func CreateMutex(name string) (uintptr, error) {
	kernel32 := syscall.NewLazyDLL("kernel32.dll")
	procCreateMutex := kernel32.NewProc("CreateMutexW")
	ret, _, err := procCreateMutex.Call(0, 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(name))))
	switch int(err.(syscall.Errno)) {
	case 0:
		return ret, nil
	default:
		return ret, err
	}
}

Call the function in the main.go just before app := NewApp().

import (
    sysWindows "golang.org/x/sys/windows"
)
// Create mutex to keep app running in single instance
if _, mutexErr := CreateMutex("YourAppName"); mutexErr != nil {
        // Do whatever... for me, I call a messagebox...
	sysWindows.MessageBox(
		sysWindows.GetShellWindow(),
		syscall.StringToUTF16Ptr("Application is already running!"),
		syscall.StringToUTF16Ptr("Warning"),
		sysWindows.MB_OK|sysWindows.MB_ICONEXCLAMATION|sysWindows.MB_SYSTEMMODAL) //See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw for details
	os.Exit(0) //Exit if the program is already running
}

KiddoV avatar Jul 07 '22 18:07 KiddoV

I'd love to integrate this into the options as a callback. Thoughts?

leaanthony avatar Jul 07 '22 22:07 leaanthony

file locks is one of ways to go https://github.com/postfinance/single

avengerweb avatar Oct 10 '22 19:10 avengerweb

There's another way making this on windows - Events. This way your first process will know that new process is launched, and, for eaxample, bring your main window to front instead of openning second process.

CreateEventW SetEvent WaitForSingleObject

It will look something like this (in C, but porting it to Go is pretty straightforward):

HANDLE hEvent = CreateEventW(nullptr, false, false, L"Global\<appname>");
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    // If process is already running, fire event and exit
    SetEvent(hEvent);
    CloseHandle(hEvent);
    ExitProcess(0);
}

// If no processes is running, just wait for events
while (true) {
    DWORD result = WaitForSingleObject(hEvent, INFINITE);
    if (result == WAIT_OBJECT_0) {
        // New process is launched
        // Bring your main window to front or show a message
    }
}

NanoNik avatar Nov 12 '22 21:11 NanoNik

This has been implemented as a v3 plugin. Windows + Mac currently supported. EDIT: Linux too.

leaanthony avatar Aug 03 '23 22:08 leaanthony