[FAQ C#] Comment ne lancer qu'une seule instance de mon application WPF ?
Bonjour,
Je voudrais quelque précision sur un article dans la FAQ.
Je veux donc tester si mon application est déja lancé.
le lien est la
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
static void Main()
{
// En utilisant using, app.Dispose() est appelée automatiquement
// Merci CSharp ;-)
using (SingleInstanceApp app = new SingleInstanceApp("{123456789 - ABCD - EFEG - XXXX}"))
{
if (app.IsRunning())
MessageBox.Show("Application déjà lancée");
else
Application.Run(new Form1());
}
} |
J'ai une question à propos de ce bout de code.
J'ai copié ce bout de code au lancement de mon application, et je peux encore lancer mon application plusieurs fois.
single instance application WPF,complement Mutex
bonjour gregory,tu as avais demande comme lancer ton application comme single instance et tu avais demande si on peut utiliser "using et mutex"
voici l'astuce de bout de code qu'il faut ajouter à app.cs c'est une proc main shared :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Threading;
namespace WpfAppMutex
{
/// <summary>
/// Logique d'interaction pour App.xaml
/// </summary>
public partial class App : Application
{
private static bool isNew;
[System.STAThreadAttribute()]
public static void Main()
{
using (System.Threading.Mutex m = new System.Threading.Mutex(true, "CeciEstUneValeurChaineQuiDoitEtreUnique", out isNew))
{
// si la valeur de retour isNew=true
// le mutex a ete accorde par le systeme au -thread application-
// avec le nom demande (chaine )
if (isNew)
{
WpfAppMutex.App app = new WpfAppMutex.App();
app.InitializeComponent();
app.Run();
}
// isNew=false
// le mutex avec le nom specifie est deja attribue à un autre thread
else
{
MessageBox.Show("L'application WpfAppMutex est deja demarree", "WpfAppMutex", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
}
}
}
}
} |
ensuite tu navigue dans l'explorateur de solution ->app.xaml clic droit ->proprietes et dans action de generer tu le met à Page.
(sinon il te sort sub main existe deja).
inconvenient :
- ce genre de solution a un defaut,tu ne peux gerer les arguments de ligne de commande (application type MIDI ouvrant un document avec une extension perso et qui doit visualiser plusieurs doc a la fois avec un clic sur le fichier
,type Ms Word par exemple).
Il faut transmettre les arguments(nom de fichier) de Instance 2,instance 3
....etc à l'instance 1 deja demarre.
2 eme Solution -Official Site MSDN -pour cela Microsoft a bidouille une methode -de derniere minute - que voici :
- elle utilise une synchronization avec un WaiHandle
1/code a mettre dans app.xaml.cs
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace WpfSingleInstanceByEventWaitHandle
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
WpfSingleInstance.Make("WpfInstanceUniqueWaitHandle", this);
base.OnStartup(e);
}
}
} |
2/code de la classe manager WpfSingleInstance qui est appele par la classe app (rajout fichier WpfSingleInstance.cs) que tu dois ajouter à ton projet WPF:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
using System;
using System.Threading;
using System.Windows;
namespace WpfSingleInstanceByEventWaitHandle
{
public static class WpfSingleInstance
{
internal static void Make(String name, Application app)
{
EventWaitHandle eventWaitHandle = null;
String eventName = Environment.MachineName + "-" + Environment.CurrentDirectory.Replace('\\', '-') + "-" + name;
bool isFirstInstance = false;
try
{
eventWaitHandle = EventWaitHandle.OpenExisting(eventName);
}
catch
{
// it's first instance
isFirstInstance = true;
}
if (isFirstInstance)
{
eventWaitHandle = new EventWaitHandle(
false,
EventResetMode.AutoReset,
eventName);
ThreadPool.RegisterWaitForSingleObject( eventWaitHandle, waitOrTimerCallback, app, Timeout.Infinite, false);
// not need more
eventWaitHandle.Close();
}
else
{
eventWaitHandle.Set();
// For that exit no interceptions
Environment.Exit(0);
}
}
private static void waitOrTimerCallback(Object state, Boolean timedOut)
{
Application app = (Application)state;
app.Dispatcher.BeginInvoke(new activate(delegate()
{ Application.Current.MainWindow.Activate();}),null);
}
private delegate void activate();
}
} |
3/ code exemple -xaml- pour la forme (code ordinaire)
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
<Window x:Class="WpfSingleInstanceByEventWaitHandle.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid Margin="10" VerticalAlignment="Center" HorizontalAlignment="Center">
<RichTextBox BorderThickness="0">
<FlowDocument>
<Paragraph TextAlignment="Center" FontWeight="bold">
WpfSingleInstanceByEventWaitHandle
</Paragraph>
<Paragraph>
WPF application Single Instance in one line of code
</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
</Window> |
4/ code behind de la forme(code ordinaire)
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfSingleInstanceByEventWaitHandle
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
} |
pour le build rien de special
bon code.......