نمایش نتایج 1 تا 7 از 7

نام تاپیک: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

  1. #1
    کاربر دائمی آواتار mohsen_f_b
    تاریخ عضویت
    مرداد 1385
    محل زندگی
    تهران
    سن
    32
    پست
    401

    جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    سلام
    این مقاله رو در یه سایت دیدم گفتم بزارم بربچه ها ازش استفاده کنند.

    مقدمه:

    یکی از مشکلاتی که معمولا برنامه نویسان برنامه های تحت ویندوز با آن روبرو هستند، اجرای فقط یک نمونه از برنامه در زمان اجرا می باشد.
    اجرای چند نمونه از برنامه می تواند مشکلاتی را در مورد دسترسی همزمان به اطلاعات و به اشتراک گزاردن منابع و غیره به وجود آورد. حتی ممکن است که کاربر لایسنس اجرای یک نمونه از برنامه را در هر زمان خریده باشد و در این صورت نباید بتواند چندین نمونه از برنامه را همزمان اجرا نماید.
    برای انجام این عمل روش های متفاوتی وجود دارد که هر کدام دارای مشکلاتی می باشند. در این مقاله به معرفی یکی از بهترین روش ها می پردازم.
    شروع:

    در این مقاله ما از کلاسی به نام Mutex استفاده می کنیم که در فضای نامی System.Threading قرار دارد و جزو کلاس هایی می باشد که جهت مدیریت دسترسی Thread ها و حتی Process های مختلف به حافظه استفاده می شود.
    قبل از اینکه به نوشتن قطعه کدهای مربوطه بپردازم، یاداوری می کنم که معمولا کلاس Program در برنامه های تحت ویندوز شبیه قطعه کد زیر می باشد.
     

    static class Program
    {
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(fals e);
    Application.Run(new Barber());
    }
    }



    اکنون قصد داریم که یک شرط بگذاریم تا اگر یک نمونه از برنامه در حال اجرا است و کاربر برنامه را مجددا اجرا کرد، به کاربر پیامی دهیم که یک نمونه از برنامه در حال اجرا است و از اجرا شدن نمونه دیگری از برنامه جلوگیری کنیم.
    قطعه کد کلاس Program را به شکل زیر تغییر می دهیم. قسمت های تغییر یافته به شکل bold شده، قابل مشاهده هستند.
     

    static class Program
    {

    static Mutex mutex = new Mutex(true, "{39d5e2c9-8791-4f77-a1f4-d0e81f1b1681}");

    [STAThread]
    static void Main()
    {
    if (mutex.WaitOne(TimeSpan.Zero, true))
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(fals e);
    Application.Run(new Form1());

    mutex.ReleaseMutex();
    }
    else
    {
    MessageBox.Show("در حال حاضر یک نمونه از برنامه در حال اجرا می باشد");
    }


    }
    }



    اکنون به بررسی قطعه کد بالا می پردازم.
    ابتدا یک نمونه شی استاتیک از نوع کلاس Mutex ایجاد نموده ایم و یک نام منحصر به فرد به آن نسبت داده ایم. این نام در حقیقت یک شناسه GUID می باشد.
    سپس داخل متد Main که برنامه ما از آنجا اجرا می شود یک شرط گذاشته ایم.
    خروجی متد WaitOne از کلاس Mutex یک مقدار منطقی می باشد. در صورتی که برای اولین بار این متد فراخوانی شود، مقدار بازگشتی آن true می باشد و تا زمانی که متد ReleaseMutex فراخوانی نشده باشد، خروجی تابع WaitOne برای سایر فراخوانی ها برابر false خواهد بود.
    بنابراین هنگامی که برای اولین بار تابع WaitOne فراخوانی می شود مقدار true را بر می گرداند و برنامه اجرا می شود و تا زمانی که برنامه در حال اجرا می باشد، اگر نمونه های دیگری از برنامه را اجرا کنیم، مقدار false را برمی گرداند.
    دقت کنید که فراموش نکنید که حتما Mutex را پس از خروج از برنامه ReleaseMutex کنید. همانطور که ما در بالا این عمل را انجام داده ایم.
    برای درک بهتر، برنامه بالا را اجرا کنید و عملکرد آن را ملاحظه نمایید.
    فعال نمودن نسخه ی در حال اجرای برنامه :

    با اعمالی که تاکنون انجام دادیم، می توانیم به کاربر اعلام کنیم که در حال حاضر یک نمونه از برنامه در حال اجرا می باشد. ولی حالت ایده آل تری نیز وجود دارد.
    بهتر است هنگامی که کاربر برای بار چندم قصد اجرای برنامه را دارد، نسخه ای از برنامه ای که در حال حاضر در حال اجرا می باشد را به صورت TopMost به کاربر نمایش دهیم زیرا ممکن است که برنامه در حالت Minimize بوده و کاربر آن را مشاهده ننماید.
    برای انجام این کار کلاسی به نام NativeMethods می نویسیم که حاوی چند API سیستمی می باشد و از آن ها در برنامه استفاده خواهیم نمود.
     

    internal class NativeMethods
    {
    public const int HWND_BROADCAST = 0xffff;
    public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
    }



    تذکر :

    با توجه به اینکه این API ها به صورت ثابت مورد استفاده قرار می گیرند و نیاز به تغییری در آن ها نیست، از تشریح عملکرد آن ها در برنامه خودداری می کنم.
    اکنون کلاس Program را به شکل زیر تغییر می دهیم. قسمت های تغییر نموده به صورت bold مشخص شده اند.
     

    static class Program
    {

    static Mutex mutex = new Mutex(true, "{39d5e2c9-8791-4f77-a1f4-d0e81f1b1681}");

    [STAThread]
    static void Main()
    {
    if (mutex.WaitOne(TimeSpan.Zero, true))
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(fals e);
    Application.Run(new Form1());
    mutex.ReleaseMutex();
    }
    else
    {
    NativeMethods.PostMessage((IntPtr)NativeMethods.HW ND_BROADCAST,
    NativeMethods.WM_SHOWME,
    IntPtr.Zero,
    IntPtr.Zero);
    }
    }
    }



    خوب تنها یک کار دیگر باقی مانده است.
    اکنون باید به فرم اصلی برنامه خود مراجعه نمایید (در اینجا Form1 می باشد) و دو متد زیر را به آن اضافه نمایید.
     

    protected override void WndProc(ref Message m)
    {
    if (m.Msg == NativeMethods.WM_SHOWME)
    {

    ShowMe();
    }
    base.WndProc(ref m);
    }
    private void ShowMe()
    {

    if (WindowState == FormWindowState.Minimized)
    {
    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. #2
    VIP آواتار Sajjad.Aghapour
    تاریخ عضویت
    مهر 1386
    محل زندگی
    اهل کاشانم .. روزگارم بد نیست
    پست
    1,265

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    دوست عزیز دست شما درد نکنه.این مورد چندین بار در سایت بحث شده بود اما این مقاله هم کامل بود.....

    قصد من از گذاشتن این پست:
    منبع مقاله یادتون رفت !!.....
    Close your eyes, take a deep breath, click your heels three times, and say, "There's no better thing than Inversion of Control and Dependency Injection, generic specialization, the decorator pattern, chains of responsibilities, and extensible software."

  3. #3
    کاربر دائمی آواتار mohsen_f_b
    تاریخ عضویت
    مرداد 1385
    محل زندگی
    تهران
    سن
    32
    پست
    401

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    نقل قول نوشته شده توسط sajjadlove مشاهده تاپیک
    دوست عزیز دست شما درد نکنه.این مورد چندین بار در سایت بحث شده بود اما این مقاله هم کامل بود.....

    قصد من از گذاشتن این پست:
    منبع مقاله یادتون رفت !!.....
    منبع : http://www.30sharp.com/

  4. #4

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    با تشکر از مقاله ای که قرار دادین

    واسه من دو تا سوال مطرح شده
    1- علت تاکید جمله زیر رو نفهمیدم ! اگه میشه توضیح مختصری مبذول بفرمایید
    نقل قول نوشته شده توسط mohsen_f_b مشاهده تاپیک
    دقت کنید که فراموش نکنید که حتما Mutex را پس از خروج از برنامه ReleaseMutex کنید.
    2-اگه من بخواهم فقط 3 نسخه از برنامه من به صورت همزمان قابل اجرا باشه ، راه کار پیش نهادی شما چیه؟

  5. #5
    کاربر دائمی آواتار saied_genius
    تاریخ عضویت
    آبان 1386
    محل زندگی
    IRAN فعلاً ...
    پست
    595

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    سلام
    اين هم يک روش ديگر که من خودم استفاده مي کنم:

           static void Main()
    {
    if (!IsProcessOpen("نام برنامه اجرايي"))
    {
    Application.Run(new frmMainClient());
    }
    else
    {
    MessageBox.Show("برنامه در حال اجرا است");
    }
    }
    static bool IsProcessOpen(string name)
    {
    int counterProcess = 0;
    //
    foreach (Process clsProcess in Process.GetProcesses())
    {
    if (clsProcess.ProcessName.Contains(name))
    {
    counterProcess += 1;
    //
    if (counterProcess > 1)//براي چک کردن يک برنامه ----- قابل تغيير براي تعداد بيشتر

    {
    return true;
    }
    }
    }
    return false;
    }

    }

  6. #6

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

    نقل قول نوشته شده توسط saied_genius مشاهده تاپیک
    سلام
    اين هم يک روش ديگر که من خودم استفاده مي کنم:

           static void Main()
    {
    if (!IsProcessOpen("نام برنامه اجرايي"))
    {
    Application.Run(new frmMainClient());
    }
    else
    {
    MessageBox.Show("برنامه در حال اجرا است");
    }
    }
    static bool IsProcessOpen(string name)
    {
    int counterProcess = 0;
    //
    foreach (Process clsProcess in Process.GetProcesses())
    {
    if (clsProcess.ProcessName.Contains(name))
    {
    counterProcess += 1;
    //
    if (counterProcess > 1)//براي چک کردن يک برنامه ----- قابل تغيير براي تعداد بيشتر

    {
    return true;
    }
    }
    }
    return false;
    }

    }
    راه کاری که شما ارائه دادین stabile نیست!

    اگه کاربر ، برنامه رو اجرا کنه و در هنگامی که برنامه در حال اجرا است نام فایل اجرایی برنامه رو تغییر بده می تواند این الگوریتم رو دور بزنه!

    لطفا" راهکاری ارائه بدن که کمترین نقص رو داشته باشه

  7. #7
    کاربر دائمی
    تاریخ عضویت
    آبان 1386
    محل زندگی
    قم
    پست
    657

    نقل قول: جلوگیری از اجرای چندین نمونه از برنامه به صورت همزمان

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

    ///<summary>
    /// The main entry point for the application.
    ///</summary>
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(fals e);

    //use Mutex to prevent multi instances of the program
    System.Threading.Mutex mutex = null;
    bool owned = false;

    try
    {
    mutex = new System.Threading.Mutex(true, Assembly.GetExecutingAssembly().FullName, out owned);
    if (!owned)
    {
    Process current = Process.GetCurrentProcess();
    foreach (Process process in Process.GetProcessesByName(current.ProcessName))
    {
    if (process.Id != current.Id)
    {
    SetForegroundWindow(process.MainWindowHandle);
    break;
    }
    }

    Process.GetCurrentProcess().Kill();
    }
    }
    catch (Exception ex)
    {
    }
    finally
    {
    if (mutex != null && owned)
    mutex.ReleaseMutex();
    }

    Application.Run(new Form1());
    }
    }

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •