Вопрос по c# – Запустить один экземпляр программы

3

у меня есть одна проблема с этим ?! Я использую этот способ для запуска только одного экземпляра программы. это очень хорошо. но когда я использую этот способ в другом приложении. когда я запускаю одну из этих программ с помощью ярлыка с рабочего стола, обе программы запускаются и отображаются на рабочем столе. примечание: обе программы запускаются в системе Windows, попробуйте.

    static bool ok;
    static Mutex mutex = new Mutex(true, "{123Newsoft-Cleaner Portable Program123}",out ok);

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]

    static void Main()
    {
        //Application.EnableVisualStyles();
        //Application.SetCompatibleTextRenderingDefault(false);
        //Application.Run(new Form1());

        if (mutex.WaitOne(TimeSpan.Zero, true))  
        {

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);


            var mainForm = new Form1c();

            try
            {                                    

                    mainForm.Visible = false;


                    mainForm.WindowState = FormWindowState.Normal;                  

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Application.Run(mainForm);               

        }
        else
        {

            NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOWME, IntPtr.Zero, IntPtr.Zero);

        }

// ---------------- в основной форме

    protected override void WndProc(ref Message M_C)
    {

        if (M_C.Msg == NativeMethods.WM_SHOWME)
        {               
            ShowMe();
        }
        base.WndProc(ref M_C);
    }

    //*************
    private void ShowMe()
    {

        if (WindowState == FormWindowState.Minimized)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        // get our current "TopMost" value (ours will always be false though)
        bool top = TopMost;
        // make our form jump to the top of everything
        TopMost = true;
        // set it back to whatever it was
        TopMost = top;

    }  

Ваш Ответ

2   ответа
1

Чтобы добавить к тому, что написал Ханс Пассант, я добавил в основную форму дополнительный метод, который обрабатывает восстановление окна и его активацию. Это должно было обернуть вызов требуемого условия формы.

Таким образом, добавленный метод в форме:

/// <summary>
/// Recovers this instance of the form.
/// </summary>
public void RestoreFromTray()
{
   if(this.InvokeRequired)
   {
      this.Invoke(new Action(RestoreFromTray) );
      return;
   }
   this.Visible = true;
   this.WindowState = FormWindowState.Normal;
   this.Activate();
}

Затем в Гансе метод, я изменил переопределение на просто:

protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) 
{
    ((formClassName)this.MainForm).RestoreFromTray();
}

Где formClassName - имя класса формы.

Я думаю, что что-то пропустил - я добавил тест InvokeRequired, чтобы убедиться, что окно восстановлено в правильном потоке. Где я понял это неправильно?
Если вам это нужно, то вы делаете что-тоvery неправильно. Вид ошибки, который собирается повесить ваше приложение в какой-то дождливый день, который требуетthis kind of debugging. Never отображать пользовательский интерфейс в рабочих потоках, класс SystemEvents съест вашу печень.
8

Это уже хорошо поддерживается .NET Framework. Вы хотите использовать класс WindowsFormsApplicationBase. Установите для свойства IsSingleInstance значение true. Вы можете переопределить метод OnStartupNextInstance, чтобы делать все что угодно, когда запускается другой экземпляр. Как и восстановление окна первой инстанции. Перепишите ваш файл Program.cs, чтобы он выглядел так:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;   // Add reference to Microsoft.VisualBasic

namespace WindowsFormsApplication1 {
    class Program : WindowsFormsApplicationBase {
        [STAThread]
        static void Main(string[] args) {
            var app = new Program();
            app.Run(args);
        }
        public Program() {
            this.IsSingleInstance = true;
            this.EnableVisualStyles = true;
            this.MainForm = new Form1();
        }
        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) {
            if (this.MainForm.WindowState == FormWindowState.Minimized) this.MainForm.WindowState = FormWindowState.Normal;
            this.MainForm.Activate();
        }
    }
}
Будьте предупреждены: Вы должны остерегаться пересечения нитей. Вы захотите использовать InvokeRequired в форме, чтобы убедиться, что вы не пересекаете потоки.
Это отлично работает для 3.5. Посмотрите на комментарий, используйте Project + Add Reference.
Спасибо:) я использую .net 3.5 это не работает: Microsoft.VisualBasic.ApplicationServices; pepero
mersi.its work.un увы, есть старая проблема. Когда запускаешь одно приложение, показывай оба :( pepero
Привет еще раз. Предварительная проблема решена. Но другое это:8pic.ir/images/xzwh8dkwx7j3oozxjk8m.png     показать значок на панели задач? pepero

Похожие вопросы