Un tema recurrente en WPF es como conseguir que solo haya una instancia de tu aplicación, existen varios métodos para ello que vamos a ir viendo.
1.Comprobando si existe el proceso.
Quizá sea la forma mas simple, en la lista de procesos chequeamos si ya existe
1 public partial class App : Application
2 {
3 protected override void OnStartup(StartupEventArgs e)
4 {
5 // Get Reference to the current Process
6 Process thisProc = Process.GetCurrentProcess();
7 // Check how many total processes have the same name as the current one
8 if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1)
9 {
10 // Si ya existe sacamos un mensaje.
11 MessageBox.Show("La aplicación ya se esta ejecutando.");
12 Application.Current.Shutdown();
13 return;
14 }
15
16 base.OnStartup(e);
17 }
18 }
El único problema que tiene este método es que si a tu aplicación se le pasa argumentos no nos serviría.
2.Usando WindowsFormsApplicationBase
En la librería Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase existe una característica que nos permite controlar si ya se esta ejecutando nuestra aplicación y soluciona el problema anterior. Realmente se utiliza igual que en Windows Forms, eliminamos los ficheros App.xaml y App.cs de manera que quitamos el punto de entrada de nuestra aplicación, añadimos la clase Main con el siguiente código.
1 class Program
2 {
3 [STAThread]
4 public static void Main(string[] args)
5 {
6 WindowsFormsApp wrapper = new WindowsFormsApp();
7 wrapper.Run(args);
8 }
9 }
La clase Wrapper tendría el código:
1 class WindowsFormsApp : WindowsFormsApplicationBase
2 {
3 private App _wpfApp;
4
5 public WindowsFormsApp()
6 {
7 // habilitar una unica instancia
8 IsSingleInstance = true;
9 }
10
11 protected override bool OnStartup(StartupEventArgs e)
12 {
13
14 _wpfApp = new App();
15 _wpfApp.Run();
16
17 return false;
18 }
19
20 protected override void OnStartupNextInstance(
21 StartupNextInstanceEventArgs e)
22 {
23 if (e.CommandLine.Count > 0)
24 {
25 _wpfApp.ProcessArguments(e.CommandLine.ToArray());
26 }
27 }
28 }
Por ultimo la clase App
1 class App : Application
2 {
3 protected override void OnStartup(StartupEventArgs e)
4 {
5 base.OnStartup(e);
6
7 MainWindow window = new MainWindow();
8 window.Show();
9 }
10
11 public void ProcessArguments(string[] args)
12 {
13 //Procesamos los parametros
14
15 }
16 }
Como veis sencillo, aunque a mi no me gusta, ya que metemos características de Winforms, tenemos que añadir librerías y es demasiado código para lo que queremos hacer.
3.Utilizando Mutex
Yo es la que utilizo siempre, es bastante sencilla de implementar y de mantener.
1 private static bool FirstInstance
2 {
3 get
4 {
5 bool created;
6 string name = Assembly.GetEntryAssembly().FullName;
7
8 Mutex mutex = new Mutex(true, name, out created);
9 return created;
10 }
11 }
Si recordamos como funciona Mutex, la primera instancia que lo crea pasa a ser propietaria del thread y con la variable created, controlamos si es la instancia que ha creado Mutex, sino es asi nos devolverá un false , de manera que nuestra App.Xaml.cs quedaría
1 protected override void OnStartup(StartupEventArgs e)
2 {
3 if (FirstInstance)
4 base.OnStartup(e);
5 else
6 {
7 MessageBox.Show("Application is already running.");
8 Application.Current.Shutdown();
9 }
10 }
Como veis mas sencillo que en el caso anterior y mucho mas elegante.
Libros de WPF recomendados
|