Reputation: 877
I am working on flutter desktop app. I want to execute only single instance of app. But currently it allows me to run more than one instance. How can I allow only one .exe file of this application to run?
Upvotes: 12
Views: 4947
Reputation: 171
For People who want to achieve this on Linux:
So i went on a very long rabbit hole trying to implement a similar fix to the one above but for linux until i found a much simpler version.
You want to go to your my_application.cc file then near the bottom find the function below and change it as follows:
From:
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE,
nullptr)); }
To:
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
nullptr)); }
The G_APPLICATION_NON_UNIQUE flag explicitly says "Make no attempts to do any of the typical single-instance application negotiation," which is the opposite of what we want. https://docs.gtk.org/gio/flags.ApplicationFlags.html#can_override_app_id
Since we are aiming for a single-instance application, we can remove the G_APPLICATION_NON_UNIQUE flag when creating your application object.
By default, GApplication tries to become a single instance if you provide an application ID, and it uses D-Bus to communicate between instances.
Now in order to make it such that when another instance is attempted to be opened you can do the following to make it grab the exisitng one and focus it instead.
static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application);
GList *list = gtk_application_get_windows(GTK_APPLICATION(application));
GtkWindow* existing_window = list ? GTK_WINDOW(list->data) : NULL;
if (existing_window) {
gtk_window_present(existing_window);
} else {
// Put your existing code here
// this is will normally start like this
GtkWindow* window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// and end like this
gtk_widget_grab_focus(GTK_WIDGET(view));
}
}
I hope this helps someone as it was a struggle to find this information anywhere and its rather simple compared to the other routes i was trying.
Upvotes: 3
Reputation: 400
open windows/runnner/win32_cpp:
// add this function above CreateAndShow
bool CheckOneInstance()
{
HANDLE m_hStartEvent = CreateEventW( NULL, FALSE, FALSE, L"Global\\yourpackage" );
if(m_hStartEvent == NULL)
{
CloseHandle( m_hStartEvent );
return false;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle( m_hStartEvent );
m_hStartEvent = NULL;
// already exist
// send message from here to existing copy of the application
return false;
}
// the only instance, start in a usual way
return true;
}
bool Win32Window::CreateAndShow(const std::wstring& title,
const Point& origin,
const Size& size) {
//Add the check
if( !CheckOneInstance()){
return false;
}
Destroy();
....
}
Upvotes: 1
Reputation: 877
This is the customization in default flutter windows application properties, so we have to code in C++ for that purpose. A single window application instance can be achieved using a Mutex:
HANDLE hMutexHandle=CreateMutex(NULL, TRUE, L"my.mutex.name");
HWND handle=FindWindowA(NULL, "Test Application");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement(handle, &place);
switch(place.showCmd)
{
case SW_SHOWMAXIMIZED:
ShowWindow(handle, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(handle, SW_RESTORE);
break;
default:
ShowWindow(handle, SW_NORMAL);
break;
}
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(handle);
return 0;
}
Opening the win32_window.cpp file and adding this code snippet at the start in CreateAndShow()
method will restrict the application to a single instance.
Upvotes: 14
Reputation: 91
I am getting a compilation error.
The solution is this line at the end of the if block.
ReleaseMutex(hMutexHandle);
Upvotes: 9