2010-07-09 4 views
8

Я часто пишу приложения .net, которые поддерживают только один экземпляр. Раньше я использовал .net-remoting, а теперь WCF, чтобы определить, работает ли уже экземпляр моего приложения и уделяет внимание этому экземпляру..NET 4 экземпляр приложения

Вопрос в том, есть ли с .net4 лучшее решение для достижения отдельных приложений экземпляра (или, как правило, имеется лучшее решение, поскольку загрузка WCF или удаленной сборки в самом начале приложения имеет плохое влияние производительности)

Update

Спасибо за все должности. Ответ на мой первоначальный вопрос, похоже, «нет, нет ничего нового для достижения отдельных приложений-экземпляров внутри .net 4».

Благодаря дополнительной информации, я буду изменять свои текущие проекты, чтобы использовать Mutex для обеспечения желаемой функциональности. Я принял ответ Боб Мура, потому что он имеет большую информацию, связанную с ним, но благодаря всем, кто опубликовал полезную информацию.

+1

ничего особенного для. net 4. wcf и удалять звук, как огромные накладные расходы для такой простой задачи – Andrey

+0

Возможный дубликат [Каков правильный способ создания одного экземпляра приложения?] (http: // stackoverflow.com/questions/19147/what-is-the-right-way-to-create-a-single-instance-application) – ChrisF

+0

@ Andrey: Да, это накладные расходы, но я должен сказать, что в большинстве приложений тезисы I использование WCF/Remoting в любом случае, это оправдывает их использование. Но момент загрузки сборки плох, потому что он продлевает время загрузки приложения/инициализации. – HCL

ответ

11

Традиционный способ сделать это с помощью мьютекса, например.

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:

Я нашел этот код для вызова SetForegroundWindow онлайн, так что вы можете найти другой экземпляр вашего приложения, и привести его вперед:

[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; 
    } 
} 

Обратите внимание, что в современных реализациях для Windows вы можете оставить только передний план.

+0

Работает ли это также в средах Terminal-Server? – HCL

+1

Мьютекс может быть за сеанс или машину. – GvS

+0

И как активировать существующее приложение (сфокусировать)? PInvoke? – HCL

2

Для этого используйте Mutex и FindWindow.

Что касается Вашего комментария на другой ответ:
Для получения информации о местных и глобальных мьютексах служб терминалов, follow this link.

службы терминалов клиент обрабатывает может использовать имена объектов с «Global \» или «Local \» приставка явно создать объект в глобальном или имени сеанса пространства.

Это код, я использую, чтобы активировать окно:

[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

Я хотел бы предложить Singleton-шаблон. Посмотрите на это: http://vbnotebookfor.net/2007/09/13/introduction-to-the-singleton-pattern-in-vbnet/

Greetz

+0

Извините, я не понимаю, как это помогает? Шаблон singleton работает в домене приложений, но не в разных процессах. – HCL

+0

-1 Это действительно работает только в рамках процесса. –

2

Там более простой способ - с помощью класса WindowsFormsApplicationBase из Microsoft.VisualBasic.ApplicationServices: (например, для 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); 
    } 
}