2010-07-09 17 views
8

Często piszę aplikacje .net, które obsługują tylko jedną instancję. Dawniej używałem .net-remoting, a teraz WCF, aby wykryć, czy już działa instancja mojej aplikacji i skupić się na tej instancji..NET 4 instancja pojedynczej aplikacji

Moje pytanie brzmi, czy w przypadku .net4 dostępne jest lepsze rozwiązanie do uzyskania aplikacji pojedynczej instancji (czy ogólnie dostępne jest lepsze rozwiązanie, ponieważ ładowanie zestawu WCF lub zdalnego na samym początku aplikacji ma zły wpływ wydajność)

Aktualizacja

Dzięki za wszystkie stanowiska. Odpowiedź na moje pierwsze pytanie wydaje się być "nie, nie ma nic nowego, aby osiągnąć aplikacje pojedynczej instancji w .net 4".

Dzięki wszystkim dodatkowym informacjom zmienię obecne projekty, aby korzystać z Mutexa w celu zapewnienia pożądanej funkcjonalności. Przyjąłem odpowiedź Boba Moore'a, ponieważ zawiera ona najwięcej informacji, ale dzięki wszystkim, którzy zamieścili przydatne informacje.

+1

nic specjalnego. net 4. wcf i remoting dźwięk jak ogromny narzut dla takiego prostego zadania – Andrey

+0

możliwy duplikat [Jaki jest prawidłowy sposób tworzenia aplikacji pojedynczej instancji?] (http: // stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-application) – ChrisF

+0

@Andrey: Tak, rzeczywiście, to narzut, ale muszę powiedzieć, że w większości aplikacji I używać WCF/Remoting i tak usprawiedliwia to ich użycie. Ale moment załadowania zespołu jest zły, ponieważ wydłuża czas potrzebny do załadowania/zainicjowania aplikacji. – HCL

Odpowiedz

11

Tradycyjny sposób na to polega na muteksie, np.

bool bNew = true; 
using (Mutex mutex = new Mutex(true, "MYAPP_0D36E4C9-399D-4b05-BDA3-EE059FB77E8D", out bNew)) 
{ 
    if (bNew) 
    { 
     // blah, blah, 
     Application.Run(new MainForm()); 
    } 
} 

Edit:

znalazłem ten kod do powoływania SetForegroundWindow on-line, dzięki czemu można znaleźć drugą instancję aplikacji i doprowadzić ją do przodu:

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetForegroundWindow(IntPtr hWnd); 


Process me = Process.GetCurrentProcess(); 
foreach (Process process in Process.GetProcessesByName (me.ProcessName)) 
{ 
    if (process.Id != me.Id) 
    { 
     SetForegroundWindow (process.MainWindowHandle); 
     break; 
    } 
} 

pamiętać, że w nowoczesnych wdrożeń systemu Windows możesz tylko oddać pierwszy plan.

+0

Czy działa to również w środowiskach Terminal-Server? – HCL

+1

Mutex może być na sesję lub na całym komputerze. – GvS

+0

A jak aktywować istniejącą aplikację (daj się skupić)? PInvoke? – HCL

2

Do tego celu używam Mutex i FindWindow.

chodzi swój komentarz na inną odpowiedź:
uzyskać informacje na temat lokalnych i globalnych muteksy w usługach terminalowych, follow this link.

Klient usług terminalowych przetwarza może używać nazwy obiektów z „Global \” lub „Local \” prefix jawnie utworzyć obiekt w globalnej lub nazwa sesji przestrzeni.

Jest to kod używam, aby uaktywnić okno:

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool IsIconic(IntPtr hWnd); 

[DllImport("user32.dll")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
private const int SH_SHOW = 5; 
private const int SH_RESTORE = 9; 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetForegroundWindow(IntPtr hWnd); 

public void Activate(IntPtr hwnd) 
{ 
    if (IsIconic(hwnd)) 
     ShowWindow(hwnd, SH_RESTORE); 
    else 
     ShowWindow(hwnd, SH_SHOW); 

    SetForegroundWindow(hwnd); 
} 
2

Jest prostszy sposób - z pomocą klasy WindowsFormsApplicationBase z Microsoft.VisualBasic.ApplicationServices: (przykład dla VB.net!)

using System; 
using System.Collections.Generic; 

public class SingleInstanceApplicationWrapper : 
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 
{ 
    public SingleInstanceApplicationWrapper() 
    { 
    IsSingleInstance = true; 
    } 

    private MyApp m_app; 
    protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e) 
    { 
    // here we create our WPF application 
    m_app = new MyApp(); 
    m_app.Run(); 
    return false; 
    } 

    protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e) 
    { 
    m_app.DispatchCommandLineParams(e.CommandLine); 
    } 
} 

public class MyApp : System.Windows.Application 
{ 
    protected override void OnStartup(System.Windows.StartupEventArgs e) 
    { 
    base.OnStartup(e); 
    DispatchCommandLineParams(e.Args); 
    } 
    public void DispatchCommandLineParams(IEnumerable<string> cmdParams) 
    { 
    // process command line parameters 
    Console.WriteLine(this.GetHashCode() + " - dispatched"); 
    } 
} 
public class Program 
{ 
    [STAThread] 
    public static void Main(string[] args) 
    { 
    var wrapper = new SingleInstanceApplicationWrapper(); 
    wrapper.Run(args); 
    } 
} 
Powiązane problemy