Sorry it the title is hard to understand. I wasn't sure how to word it.
I have an application that should only be allowed to run one instance per user session. If the user clicks to launch the application again, I want to bring the one already to focus.
The window will likely have Visibility to collapsed.
If it's visible I know I can use
if (IsIconic(hWnd))
{
ShowWindowAsync(hWnd, swRestore);
}
SetForegroundWindow(hWnd);
but if the window is collapsed, is there a way for me to bring it back to visible?
The best way of accomplishing this is using a named mutex. Create the mutex using code such as: bool firstInstance; Mutex mutex = new Mutex(false, "Local\\" + someUniqueName, out firstInstance); // If firstInstance is now true, we're the first instance of the application; // otherwise another instance is running.
" This feature is already built in to Windows Forms. Just go to the project properties and click the "Single Instance Application" checkbox. "
If you look at App. xaml class of your WPF application, you will see the following XAML code. Here the StartupUri sets the startup Window of an application. If you want to change the Startup window to some other window, just change this value.
You're looking for the Mutex
Class. It's pretty complicated, but luckily the Singleton Pattern has been widely discussed. There are several good articles on it, but you can find a good implementation of it in the C# .NET Single Instance Application page on the Sanity Free Coding website. From the linked page:
static class Program {
static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
static void Main() {
if(mutex.WaitOne(TimeSpan.Zero, true)) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
mutex.ReleaseMutex();
} else {
MessageBox.Show("only one instance at a time");
}
}
}
Now you're probably wondering how to have a Main
method in a WPF Application, right? Well there's a few things that you have to do, but it's not difficult. See the Writing a custom Main() method for WPF applications article which explains this in detail. From that article:
You basically need to change the application’s build action from “Application Definition” to “Page”, create a constructor that calls “InitializeComponent”, and write your Main() by eventually calling one of the application’s “Run” method overloads. ... Don’t forget, also, to remove the “StartupUri” from the App.xaml, otherwise another copy of window will show up (unless you get an error because the URI points to a non existing XAML resource).
So by amalgamating these two resources, we can see that your App.xaml.cs
file should look something like this:
public partial class App : Application
{
private static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
private static MainWindow mainWindow = null;
App()
{
InitializeComponent();
}
[STAThread]
static void Main()
{
if(mutex.WaitOne(TimeSpan.Zero, true))
{
App app = new App();
mainWindow = new MainWindow();
app.Run(mainWindow);
mutex.ReleaseMutex();
}
else
{
mainWindow.WindowState = WindowState.Normal;
}
}
}
I removed the tag StartupUri
from the App.xaml file.
Change the Build Action of App.xaml, from ApplicationDefinition
to Page
(You can change it on the property window).
Add a reference to Microsoft.VisualBasic
(namespace to WindowsFormsApplicationBase).
On the class App.xaml.cs
, put this code:
public partial class App : Application
{
App()
{
InitializeComponent();
}
[STAThread]
static void Main()
{
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(new[] {"teste"});
}
}
public class SingleInstanceManager : WindowsFormsApplicationBase
{
SingleInstanceApplication app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
// First time app is launched
app = new SingleInstanceApplication();
app.Run();
return false;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
app.Activate();
}
}
public class SingleInstanceApplication : Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
// Create and show the application's main window
MainWindow window = new MainWindow();
window.Show();
}
public void Activate()
{
// Reactivate application's main window
this.MainWindow.WindowState = WindowState.Normal;
this.MainWindow.Activate();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With