c# - একটি একক দৃষ্টান্ত WPF অ্যাপ্লিকেশন তৈরি করার সঠিক উপায় কি?




.net mutex (20)

সি # এবং ডাব্লুপিএফ ব্যবহার করে .NET ( উইন্ডোজ ফরম বা কনসোলের পরিবর্তে), কোনও অ্যাপ্লিকেশন তৈরি করার সঠিক উপায় যা শুধুমাত্র একটি উদাহরণ হিসাবে চালানো যেতে পারে?

আমি জানি যে এটি একটি mutex নামে কিছু পৌরাণিক জিনিস নিয়ে কিছু করার আছে, কদাচিৎ আমি এমন কাউকে খুঁজে পেতে পারি যা থামাতে বিরক্ত এবং এগুলির মধ্যে কোনটি ব্যাখ্যা করে।

কোডটি ইতিমধ্যে চলমান ইনস্ট্যান্সকে জানাতে হবে যে ব্যবহারকারীটি দ্বিতীয়টি শুরু করার চেষ্টা করেছিল এবং কোনও বিদ্যমান থাকলেও কোনও কমান্ড-লাইন আর্গুমেন্ট পাস করতে পারে।


Mutex এবং IPC স্টাফগুলি ব্যবহার করে এমন একটি নতুন এবং চলমান ইনস্ট্যান্সে কোনও কমান্ড লাইন আর্গুমেন্ট পাস করে, এটি blogs.microsoft.co.il/blogs/arik/archive/2010/05/28/…


আচ্ছা, আমার কাছে একটি ডিসপোজেবল ক্লাস রয়েছে যা বেশিরভাগ ক্ষেত্রেই সহজেই কাজ করে:

এটি ভালো ব্যবহার করুন:

static void Main()
{
    using (SingleInstanceMutex sim = new SingleInstanceMutex())
    {
        if (sim.IsOtherInstanceRunning)
        {
            Application.Exit();
        }

        // Initialize program here.
    }
}

এটা এখানে:

/// <summary>
/// Represents a <see cref="SingleInstanceMutex"/> class.
/// </summary>
public partial class SingleInstanceMutex : IDisposable
{
    #region Fields

    /// <summary>
    /// Indicator whether another instance of this application is running or not.
    /// </summary>
    private bool isNoOtherInstanceRunning;

    /// <summary>
    /// The <see cref="Mutex"/> used to ask for other instances of this application.
    /// </summary>
    private Mutex singleInstanceMutex = null;

    /// <summary>
    /// An indicator whether this object is beeing actively disposed or not.
    /// </summary>
    private bool disposed;

    #endregion

    #region Constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="SingleInstanceMutex"/> class.
    /// </summary>
    public SingleInstanceMutex()
    {
        this.singleInstanceMutex = new Mutex(true, Assembly.GetCallingAssembly().FullName, out this.isNoOtherInstanceRunning);
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets an indicator whether another instance of the application is running or not.
    /// </summary>
    public bool IsOtherInstanceRunning
    {
        get
        {
            return !this.isNoOtherInstanceRunning;
        }
    }

    #endregion

    #region Methods

    /// <summary>
    /// Closes the <see cref="SingleInstanceMutex"/>.
    /// </summary>
    public void Close()
    {
        this.ThrowIfDisposed();
        this.singleInstanceMutex.Close();
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            /* Release unmanaged ressources */

            if (disposing)
            {
                /* Release managed ressources */
                this.Close();
            }

            this.disposed = true;
        }
    }

    /// <summary>
    /// Throws an exception if something is tried to be done with an already disposed object.
    /// </summary>
    /// <remarks>
    /// All public methods of the class must first call this.
    /// </remarks>
    public void ThrowIfDisposed()
    {
        if (this.disposed)
        {
            throw new ObjectDisposedException(this.GetType().Name);
        }
    }

    #endregion
}

এই কোড প্রধান পদ্ধতিতে যেতে হবে। WPF এ প্রধান পদ্ধতি সম্পর্কে আরও তথ্যের জন্য here দেখুন।

[DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

private const int SW_SHOWMAXIMIZED = 3;

static void Main() 
{
    Process currentProcess = Process.GetCurrentProcess();
    var runningProcess = (from process in Process.GetProcesses()
                          where
                            process.Id != currentProcess.Id &&
                            process.ProcessName.Equals(
                              currentProcess.ProcessName,
                              StringComparison.Ordinal)
                          select process).FirstOrDefault();
    if (runningProcess != null)
    {
        ShowWindow(runningProcess.MainWindowHandle, SW_SHOWMAXIMIZED);
       return; 
    }
}

পদ্ধতি 2

static void Main()
{
    string procName = Process.GetCurrentProcess().ProcessName;
    // get the list of all processes by that name

    Process[] processes=Process.GetProcessesByName(procName);

    if (processes.Length > 1)
    {
        MessageBox.Show(procName + " already running");  
        return;
    } 
    else
    {
        // Application.Run(...);
    }
}

দ্রষ্টব্য: উপরের পদ্ধতিগুলি আপনার প্রক্রিয়া / অ্যাপ্লিকেশনটির একটি অনন্য নাম অনুমান করে। যেহেতু এটি কোন বিদ্যমান প্রসেসর খুঁজে পেতে প্রক্রিয়া নাম ব্যবহার করে। সুতরাং, যদি আপনার অ্যাপ্লিকেশনটির একটি সাধারণ নাম (অর্থাত: নোটপ্যাড) থাকে তবে উপরের পদ্ধতিটি কাজ করবে না।


এখানে Mutex সমাধান সম্পর্কিত একটি খুব ভাল article । নিবন্ধটি বর্ণিত পদ্ধতির দুটি কারণের জন্য উপকারী।

প্রথম, এটি মাইক্রোসফ্ট উপর নির্ভরতা প্রয়োজন হয় না। ভিসুয়াল বেসিক সমাবেশ। যদি আমার প্রকল্পের ইতিমধ্যেই সেই সমাবেশে নির্ভরশীলতা থাকে তবে আমি সম্ভবত গৃহীত উত্তরগুলিতে দেখানো পদ্ধতিটি ব্যবহার করার পক্ষে সমর্থন দেব। কিন্তু যেহেতু, আমি মাইক্রোসফ্ট ব্যবহার করি না। ভিসুয়াল বেসিক সমাবেশ, এবং আমি বরং আমার প্রকল্পের অপ্রয়োজনীয় নির্ভরতা যোগ করব না।

দ্বিতীয়ত, নিবন্ধটি দেখায় যে ব্যবহারকারী যখন অন্য দৃষ্টান্ত শুরু করার চেষ্টা করে তখন অ্যাপ্লিকেশনটির বিদ্যমান উদাহরণটি ফোরামটিতে আনতে হবে। এটি একটি খুব চমৎকার স্পর্শ যা এখানে বর্ণনা করা অন্যান্য Mutex সমাধানগুলি ঠিকানা দেয় না।

হালনাগাদ

8/1/2014 পর্যন্ত, আমি উপরের নিবন্ধটি এখনো সক্রিয় ছিলাম, তবে ব্লগটি কিছুক্ষণের মধ্যে আপডেট করা হয়নি। যে আমাকে উদ্বেগ করে যে অবশেষে এটি অদৃশ্য হতে পারে, এবং এটি সঙ্গে, সমর্থিত সমাধান। আমি এখানে বংশবৃত্তির জন্য নিবন্ধের বিষয়বস্তু পুনরুত্পাদন করছি। স্যানিটি ফ্রি কোডিংয়ে ব্লগ মালিকের কাছে এই শব্দগুলি সম্পূর্ণরূপে অন্তর্গত।

আজ আমি কিছু কোড পুনরায় refactor চেয়েছিলেন যা আমার অ্যাপ্লিকেশন নিষিদ্ধ নিজেই একাধিক দৃষ্টান্ত থেকে চলমান।

পূর্বে আমি System.Diagnostics.Process এর প্রক্রিয়া তালিকাতে আমার myapp.exe এর একটি উদাহরণ সন্ধান করতে ব্যবহার করেছিলাম। যদিও এটি কাজ করে, এটি অত্যধিক ওভারহেড এনে দেয় এবং আমি কিছু ক্লিনার চেয়েছিলেন।

আমি এই জন্য একটি mutex ব্যবহার করতে পারে যে জানি (কিন্তু আগে এটা করা না) আমি আমার কোড কাটা এবং আমার জীবন সহজ করা আউট সেট আউট।

আমার আবেদন ক্লাসের ক্লাসে আমি একটি স্ট্যাটিক নামক Mutex তৈরি Mutex :

static class Program
{
    static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
    [STAThread]
    ...
}

একটি নামযুক্ত mutex থাকার ফলে আমরা একাধিক থ্রেড এবং প্রসেস জুড়ে সিঙ্ক্রোনাইজেশন স্ট্যাক করতে পারবেন যা আমি যা খুঁজছি তা কেবল জাদু।

Mutex.WaitOne একটি ওভারলোড আছে যা আমাদের অপেক্ষা করার জন্য সময় নির্দিষ্ট করে। যেহেতু আমরা প্রকৃতপক্ষে আমাদের কোডটি সিঙ্ক্রোনাইজ করতে চাই না (এটি বর্তমানে ব্যবহারে রয়েছে কিনা তা যাচাই করুন) আমরা দুটি প্যারামিটারের সাথে ওভারলোড ব্যবহার করি: Mutex.WaitOne (টাইমসপ্যান সময়সীমা, বুল প্রস্থানকেনটেক্সট) । যদি এটি প্রবেশ করতে সক্ষম হয় তবে এক ফেরত আসার অপেক্ষা করুন এবং যদি এটি না হয় তবে মিথ্যা। এই ক্ষেত্রে, আমরা সব অপেক্ষা করতে চান না; যদি আমাদের mutex ব্যবহার করা হয়, এটি এড়িয়ে যান এবং সরান, তাই আমরা টাইমস্প্যান.জিরো (0 মিলিসেকেন্ড অপেক্ষা করুন) এ পাস করি, এবং exitContext টি সত্য সেট করুন যাতে আমরা এটিতে লকটি অ্যাকচয়ের চেষ্টা করার আগে আমরা সিঙ্ক্রোনাইজেশান প্রেক্ষাপটে প্রস্থান করতে পারি। এই ব্যবহার করে, আমরা আমাদের অ্যাপ্লিকেশন মোড়ানো। এই মত কিছু ভিতরে রুন কোড:

static class Program
{
    static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
    [STAThread]
    static void Main() {
        if(mutex.WaitOne(TimeSpan.Zero, true)) {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            mutex.ReleaseMutex();
        } else {
            MessageBox.Show("only one instance at a time");
        }
    }
}

সুতরাং, যদি আমাদের অ্যাপ্লিকেশন চলমান হয়, তাহলে WaitOne মিথ্যা ফেরত দেবে, এবং আমরা একটি বার্তা বাক্স পাবেন।

একটি বার্তা বাক্স দেখানোর পরিবর্তে, আমি আমার চলমান দৃষ্টান্তটি অবহিত করার জন্য একটি ছোট Win32 ব্যবহার করতে পছন্দ করেছিলাম যে কেউ ভুলে গেছেন যে এটি ইতিমধ্যে চলছে (সমস্ত অন্যান্য উইন্ডোগুলির শীর্ষে নিজেকে আনয়ন করে)। এটি অর্জন করার জন্য আমি প্রতিটি উইন্ডোতে একটি কাস্টম বার্তা সম্প্রচার করার জন্য PostMessage ব্যবহার PostMessage (কাস্টম বার্তাটি আমার চলমান অ্যাপ্লিকেশন দ্বারা RegisterWindowMessage উইণ্ডো মেসেজের সাথে RegisterWindowMessage ছিল, যার মানে কেবল আমার অ্যাপ্লিকেশনটি কী তা জানে) তবে আমার দ্বিতীয় উদাহরণটি বের হয়। চলমান অ্যাপ্লিকেশন ইনস্ট্যান্স যে বিজ্ঞপ্তি পাবেন এবং এটি প্রক্রিয়া। এটি করার জন্য, আমি আমার মূল ফর্ম WndProc এবং আমার কাস্টম বিজ্ঞপ্তির জন্য শোনা। যখন আমি সেই বিজ্ঞপ্তিটি পেয়েছি তখন আমি উপরের টপিকে আনতে ফর্মটির শীর্ষতম সম্পত্তিটি সত্যতে সেট করেছি।

এখানে আমি শেষ পর্যন্ত কি হল:

  • Program.cs
static class Program
{
    static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
    [STAThread]
    static void Main() {
        if(mutex.WaitOne(TimeSpan.Zero, true)) {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            mutex.ReleaseMutex();
        } else {
            // send our Win32 message to make the currently running instance
            // jump on top of all the other windows
            NativeMethods.PostMessage(
                (IntPtr)NativeMethods.HWND_BROADCAST,
                NativeMethods.WM_SHOWME,
                IntPtr.Zero,
                IntPtr.Zero);
        }
    }
}
  • NativeMethods.cs
// this class just wraps some Win32 stuff that we're going to use
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);
}
  • Form1.cs (সামনের দিকে আংশিক)
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    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;
    }
}

এমএসডিএন আসলে C # এবং VB উভয়ের জন্য একটি নমুনা অ্যাপ্লিকেশন আছে যা ঠিক করতে: http://msdn.microsoft.com/en-us/library/ms771662(v=VS.90).aspx

একক দৃষ্টান্ত সনাক্তকরণের জন্য সবচেয়ে সাধারণ এবং বিশ্বস্ত কৌশল মাইক্রোসফ্ট। নেট ফ্রেমওয়ার্ক রিমোটিং অবকাঠামো (সিস্টেম। রিমোটিং) ব্যবহার করা। মাইক্রোসফ্ট। নেট ফ্রেমওয়ার্ক (সংস্করণ 2.0) এর মধ্যে একটি টাইপ, উইন্ডোফফর্ম অ্যাপ্লিকেশনबेस রয়েছে, যা প্রয়োজনীয় রিমোটিং কার্যকারিতাকে সিদ্ধ করে। একটি WPF অ্যাপ্লিকেশন এ এই প্রকারটি অন্তর্ভুক্ত করার জন্য, একটি প্রকারটি থেকে এটি অর্জন করতে হবে এবং অ্যাপ্লিকেশন স্ট্যাটিক এন্ট্রি পয়েন্ট পদ্ধতি, মুখ্য এবং WPF অ্যাপ্লিকেশনের অ্যাপ্লিকেশন প্রকারের মধ্যে শিম হিসাবে ব্যবহার করা উচিত। শিমটি যখন কোনও অ্যাপ্লিকেশনটি প্রথম চালু হয় তখন সনাক্ত হয় এবং পরবর্তী লঞ্চগুলির প্রয়াস করা হয় এবং লঞ্চগুলি কীভাবে প্রক্রিয়া করবেন তা নির্ধারণ করতে WPF অ্যাপ্লিকেশন প্রকারকে নিয়ন্ত্রণ করে।

  • সি # মানুষের জন্য কেবল একটি গভীর শ্বাস নিতে এবং সম্পূর্ণ ভুলে যাওয়া 'আমি ভিসুয়ালাসাসিক DLL অন্তর্ভুক্ত করতে চাই না'। this কারণে এবং স্কট হানসেলম্যান কী বলছেন এবং এই বিষয়টিটি যে সমস্যাটির সবচেয়ে পরিষ্কার সমাধান এবং এটি এমনভাবে ডিজাইন করা হয়েছে যারা আপনার চেয়ে ফ্রেমওয়ার্ক সম্পর্কে অনেক কিছু জানেন।
  • একটি ব্যবহারযোগ্যতা দৃষ্টিকোণ থেকে আপনার ব্যবহারকারী একটি অ্যাপ্লিকেশন লোড হচ্ছে এবং এটি ইতিমধ্যে খোলা হয় এবং আপনি তাদের একটি ত্রুটি বার্তা প্রদান করছেন যেমন 'Another instance of the app is running. Bye' 'Another instance of the app is running. Bye' তারপর তারা খুব খুশি ব্যবহারকারী হতে হবে না। আপনি কেবলমাত্র একটি GUI অ্যাপ্লিকেশনে অবশ্যই এটি প্রয়োগ করুন এবং প্রদত্ত আর্গুমেন্টগুলিতে পাস করুন - অথবা যদি কমান্ড লাইনের প্যারামিটারগুলির কোন অর্থ না থাকে তবে আপনাকে অবশ্যই এমন অ্যাপ্লিকেশনটি পপ করতে হবে যা কমিয়ে আনা যেতে পারে।

কাঠামোটি ইতিমধ্যেই এর জন্য সমর্থন করেছে - এটি ঠিক যে কিছু বোকা Microsoft.VisualBasic ডায়াল করা হয়েছে। ভিসুয়ালবাজিক ​​এবং এটি Microsoft.VisualBasic ঢোকানো হয়নি। Microsoft.ApplicationUtils বা এরকম কিছু। এটা পেতে - বা প্রতিফলক খুলুন।

টিপ: আপনি যদি এই পদ্ধতিটি ঠিক যেমনটি ব্যবহার করেন, এবং আপনার কাছে ইতোমধ্যে সংস্থার সাথে App.xaml রয়েছে তবে আপনিও এটিকে দেখতে চান।


কোড article যা চিহ্নিত উত্তরটির রেফারেন্সটি একটি দুর্দান্ত শুরু।

যাইহোক, আমি দেখেছি এটি খুব ভাল ক্ষেত্রে পরিচালনা করে না যখন ইতিমধ্যে উপস্থিত থাকা একটি মোডাল ডায়লগ খোলা থাকে, সে কথোপকথনটি পরিচালিত একটি (যেমন কোনও বক্সের মতো অন্য ফর্মের মতো), বা কোনও পরিচালিত নয় (যেমন এমনকি স্ট্যান্ডার্ড নেট ব্যবহার করেও OpenFileDialog)। আসল কোড দিয়ে, মূল ফর্মটি সক্রিয় করা হয় তবে মোডালটি অযৌক্তিক থাকে, যা অদ্ভুত দেখাচ্ছে, প্লাস ব্যবহারকারীকে অ্যাপ্লিকেশানটি ব্যবহার করার জন্য এটিতে ক্লিক করতে হবে।

সুতরাং, আমি WinForms এবং WPF অ্যাপ্লিকেশনের জন্য এটি সম্পূর্ণরূপে স্বয়ংক্রিয়ভাবে পরিচালনা করতে একটি সিঙ্গলইনস্ট্যান্স ইউটিলিটি ক্লাস তৈরি করেছি।

Winforms :

1) প্রোগ্রাম শ্রেণীবদ্ধ এই মত পরিবর্তন করুন:

static class Program
{
    public static readonly SingleInstance Singleton = new SingleInstance(typeof(Program).FullName);

    [STAThread]
    static void Main(string[] args)
    {
        // NOTE: if this always return false, close & restart Visual Studio
        // this is probably due to the vshost.exe thing
        Singleton.RunFirstInstance(() =>
        {
            SingleInstanceMain(args);
        });
    }

    public static void SingleInstanceMain(string[] args)
    {
        // standard code that was in Main now goes here
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

2) এই মত প্রধান উইন্ডো ক্লাস সংশোধন করুন:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
        // if needed, the singleton will restore this window
        Program.Singleton.OnWndProc(this, m, true);

        // TODO: handle specific messages here if needed
        base.WndProc(ref m);
    }
}

WPF:

1) এপ্লিকেশনটি এপ্লিকেশনটি সংশোধন করুন (এবং মুখ্য পদ্ধতিটি পুনরায় সংজ্ঞায়িত করতে আপনি পৃষ্ঠায় এটির বিল্ড অ্যাকশন সেট করেছেন তা নিশ্চিত করুন):

public partial class App : Application
{
    public static readonly SingleInstance Singleton = new SingleInstance(typeof(App).FullName);

    [STAThread]
    public static void Main(string[] args)
    {
        // NOTE: if this always return false, close & restart Visual Studio
        // this is probably due to the vshost.exe thing
        Singleton.RunFirstInstance(() =>
        {
            SingleInstanceMain(args);
        });
    }

    public static void SingleInstanceMain(string[] args)
    {
        // standard code that was in Main now goes here
        App app = new App();
        app.InitializeComponent();
        app.Run();
    }
}

2) এই মত প্রধান উইন্ডো ক্লাস সংশোধন করুন:

public partial class MainWindow : Window
{
    private HwndSource _source;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        _source = (HwndSource)PresentationSource.FromVisual(this);
        _source.AddHook(HwndSourceHook);
    }

    protected virtual IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        // if needed, the singleton will restore this window
        App.Singleton.OnWndProc(hwnd, msg, wParam, lParam, true, true);

        // TODO: handle other specific message
        return IntPtr.Zero;
    }

এবং এখানে ইউটিলিটি ক্লাস হয়:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;

namespace SingleInstanceUtilities
{
    public sealed class SingleInstance
    {
        private const int HWND_BROADCAST = 0xFFFF;

        [DllImport("user32.dll")]
        private static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        private static extern int RegisterWindowMessage(string message);

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        public SingleInstance(string uniqueName)
        {
            if (uniqueName == null)
                throw new ArgumentNullException("uniqueName");

            Mutex = new Mutex(true, uniqueName);
            Message = RegisterWindowMessage("WM_" + uniqueName);
        }

        public Mutex Mutex { get; private set; }
        public int Message { get; private set; }

        public void RunFirstInstance(Action action)
        {
            RunFirstInstance(action, IntPtr.Zero, IntPtr.Zero);
        }

        // NOTE: if this always return false, close & restart Visual Studio
        // this is probably due to the vshost.exe thing
        public void RunFirstInstance(Action action, IntPtr wParam, IntPtr lParam)
        {
            if (action == null)
                throw new ArgumentNullException("action");

            if (WaitForMutext(wParam, lParam))
            {
                try
                {
                    action();
                }
                finally
                {
                    ReleaseMutex();
                }
            }
        }

        public static void ActivateWindow(IntPtr hwnd)
        {
            if (hwnd == IntPtr.Zero)
                return;

            FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(hwnd));
        }

        public void OnWndProc(IntPtr hwnd, int m, IntPtr wParam, IntPtr lParam, bool restorePlacement, bool activate)
        {
            if (m == Message)
            {
                if (restorePlacement)
                {
                    WindowPlacement placement = WindowPlacement.GetPlacement(hwnd, false);
                    if (placement.IsValid && placement.IsMinimized)
                    {
                        const int SW_SHOWNORMAL = 1;
                        placement.ShowCmd = SW_SHOWNORMAL;
                        placement.SetPlacement(hwnd);
                    }
                }

                if (activate)
                {
                    SetForegroundWindow(hwnd);
                    FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(hwnd));
                }
            }
        }

#if WINFORMS // define this for Winforms apps
        public void OnWndProc(System.Windows.Forms.Form form, int m, IntPtr wParam, IntPtr lParam, bool activate)
        {
            if (form == null)
                throw new ArgumentNullException("form");

            if (m == Message)
            {
                if (activate)
                {
                    if (form.WindowState == System.Windows.Forms.FormWindowState.Minimized)
                    {
                        form.WindowState = System.Windows.Forms.FormWindowState.Normal;
                    }

                    form.Activate();
                    FormUtilities.ActivateWindow(FormUtilities.GetModalWindow(form.Handle));
                }
            }
        }

        public void OnWndProc(System.Windows.Forms.Form form, System.Windows.Forms.Message m, bool activate)
        {
            if (form == null)
                throw new ArgumentNullException("form");

            OnWndProc(form, m.Msg, m.WParam, m.LParam, activate);
        }
#endif

        public void ReleaseMutex()
        {
            Mutex.ReleaseMutex();
        }

        public bool WaitForMutext(bool force, IntPtr wParam, IntPtr lParam)
        {
            bool b = PrivateWaitForMutext(force);
            if (!b)
            {
                PostMessage((IntPtr)HWND_BROADCAST, Message, wParam, lParam);
            }
            return b;
        }

        public bool WaitForMutext(IntPtr wParam, IntPtr lParam)
        {
            return WaitForMutext(false, wParam, lParam);
        }

        private bool PrivateWaitForMutext(bool force)
        {
            if (force)
                return true;

            try
            {
                return Mutex.WaitOne(TimeSpan.Zero, true);
            }
            catch (AbandonedMutexException)
            {
                return true;
            }
        }
    }

    // NOTE: don't add any field or public get/set property, as this must exactly map to Windows' WINDOWPLACEMENT structure
    [StructLayout(LayoutKind.Sequential)]
    public struct WindowPlacement
    {
        public int Length { get; set; }
        public int Flags { get; set; }
        public int ShowCmd { get; set; }
        public int MinPositionX { get; set; }
        public int MinPositionY { get; set; }
        public int MaxPositionX { get; set; }
        public int MaxPositionY { get; set; }
        public int NormalPositionLeft { get; set; }
        public int NormalPositionTop { get; set; }
        public int NormalPositionRight { get; set; }
        public int NormalPositionBottom { get; set; }

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool SetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);

        private const int SW_SHOWMINIMIZED = 2;

        public bool IsMinimized
        {
            get
            {
                return ShowCmd == SW_SHOWMINIMIZED;
            }
        }

        public bool IsValid
        {
            get
            {
                return Length == Marshal.SizeOf(typeof(WindowPlacement));
            }
        }

        public void SetPlacement(IntPtr windowHandle)
        {
            SetWindowPlacement(windowHandle, ref this);
        }

        public static WindowPlacement GetPlacement(IntPtr windowHandle, bool throwOnError)
        {
            WindowPlacement placement = new WindowPlacement();
            if (windowHandle == IntPtr.Zero)
                return placement;

            placement.Length = Marshal.SizeOf(typeof(WindowPlacement));
            if (!GetWindowPlacement(windowHandle, ref placement))
            {
                if (throwOnError)
                    throw new Win32Exception(Marshal.GetLastWin32Error());

                return new WindowPlacement();
            }
            return placement;
        }
    }

    public static class FormUtilities
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr SetActiveWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        private delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool EnumThreadWindows(int dwThreadId, EnumChildrenCallback lpEnumFunc, IntPtr lParam);

        private class ModalWindowUtil
        {
            private const int GW_OWNER = 4;
            private int _maxOwnershipLevel;
            private IntPtr _maxOwnershipHandle;

            private bool EnumChildren(IntPtr hwnd, IntPtr lParam)
            {
                int level = 1;
                if (IsWindowVisible(hwnd) && IsOwned(lParam, hwnd, ref level))
                {
                    if (level > _maxOwnershipLevel)
                    {
                        _maxOwnershipHandle = hwnd;
                        _maxOwnershipLevel = level;
                    }
                }
                return true;
            }

            private static bool IsOwned(IntPtr owner, IntPtr hwnd, ref int level)
            {
                IntPtr o = GetWindow(hwnd, GW_OWNER);
                if (o == IntPtr.Zero)
                    return false;

                if (o == owner)
                    return true;

                level++;
                return IsOwned(owner, o, ref level);
            }

            public static void ActivateWindow(IntPtr hwnd)
            {
                if (hwnd != IntPtr.Zero)
                {
                    SetActiveWindow(hwnd);
                }
            }

            public static IntPtr GetModalWindow(IntPtr owner)
            {
                ModalWindowUtil util = new ModalWindowUtil();
                EnumThreadWindows(GetCurrentThreadId(), util.EnumChildren, owner);
                return util._maxOwnershipHandle; // may be IntPtr.Zero
            }
        }

        public static void ActivateWindow(IntPtr hwnd)
        {
            ModalWindowUtil.ActivateWindow(hwnd);
        }

        public static IntPtr GetModalWindow(IntPtr owner)
        {
            return ModalWindowUtil.GetModalWindow(owner);
        }
    }
}

2017-01-25 আপডেট করুন। কয়েকটি জিনিস চেষ্টা করার পরে, আমি ভিসুয়ালবাসিক.dll এর সাথে যেতে সিদ্ধান্ত নিলাম এটি সহজ এবং ভাল কাজ করে (অন্তত আমার জন্য)। আমি রেফারেন্স হিসাবে আমার পূর্ববর্তী উত্তর দেওয়া যাক ...

ঠিক যেমন রেফারেন্স, এইভাবে আমি কীভাবে আর্গুমেন্ট পাস না করেই কাজ করেছি (যা আমি এটার কোনো কারণ খুঁজে পাচ্ছি না ... আমি একটি আর্গুমেন্ট দিয়ে একটি একক অ্যাপ্লিকেশন যা এক উদাহরণ থেকে অন্য একটিকে অতিক্রম করতে হবে)। ফাইল অ্যাসোসিয়েশন প্রয়োজন হলে, একটি অ্যাপ্লিকেশন (প্রতিটি ব্যবহারকারীর মান প্রত্যাশা) প্রতিটি ডক জন্য instanciated করা উচিত। যদি আপনি বিদ্যমান অ্যাপ্লিকেশন এ args পাস করতে হবে, আমি মনে করি আমি VB DL ব্যবহার করা হবে।

Args (শুধুমাত্র একক ইনস্ট্যান্স অ্যাপ্লিকেশন) প্রেরণ করা হচ্ছে না, আমি একটি নতুন উইন্ডো বার্তা নিবন্ধন করতে পছন্দ করি না এবং ম্যাট ডেভিস সমাধানতে সংজ্ঞায়িত বার্তা লুপকে ওভাররাইড করি না। যদিও এটি একটি ভিজ্যুয়ালবাসিক ডিল যোগ করার জন্য একটি বড় চুক্তি নয়, তবে আমি একক ইনস্ট্যান্স অ্যাপ্লিকেশন করতে কেবল একটি নতুন রেফারেন্স যুক্ত করতে পছন্দ করি না। এছাড়াও, আমি অ্যাপ্লিকেশন থেকে শাটডাউন কল করার পরিবর্তে মেনের সাথে একটি নতুন বর্গকে তাত্ক্ষণিকভাবে পছন্দ করি। স্টার্টআপ ওভাররাইড যত তাড়াতাড়ি সম্ভব প্রস্থান করতে ভুলবেন।

আশা করি যে কেউ এটা পছন্দ করবে ... বা সামান্য বিট অনুপ্রাণিত করবে :-)

প্রকল্প স্টার্টআপ ক্লাসটি 'SingleInstanceApp' হিসাবে সেট করা উচিত।

public class SingleInstanceApp
{
    [STAThread]
    public static void Main(string[] args)
    {
        Mutex _mutexSingleInstance = new Mutex(true, "MonitorMeSingleInstance");

        if (_mutexSingleInstance.WaitOne(TimeSpan.Zero, true))
        {
            try
            {
                var app = new App();
                app.InitializeComponent();
                app.Run();

            }
            finally
            {
                _mutexSingleInstance.ReleaseMutex();
                _mutexSingleInstance.Close();
            }
        }
        else
        {
            MessageBox.Show("One instance is already running.");

            var processes = Process.GetProcessesByName(Assembly.GetEntryAssembly().GetName().Name);
            {
                if (processes.Length > 1)
                {
                    foreach (var process in processes)
                    {
                        if (process.Id != Process.GetCurrentProcess().Id)
                        {
                            WindowHelper.SetForegroundWindow(process.MainWindowHandle);
                        }
                    }
                }
            }
        }
    }
}

WindowHelper:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;

namespace HQ.Util.Unmanaged
{
    public class WindowHelper
    {
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

Mutex সমাধান ব্যবহার করুন:

using System;
using System.Windows.Forms;
using System.Threading;

namespace OneAndOnlyOne
{
static class Program
{
    static String _mutexID = " // generate guid"
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Boolean _isNotRunning;
        using (Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning))
        {
            if (_isNotRunning)
            {
                Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("An instance is already running.");
                return;
            }
        }
    }
}
}

এখানে একটি লাইটওয়েট সমাধান ব্যবহার করা যা অ্যাপ্লিকেশানটিকে কাস্টম উইন্ডোজ বার্তাগুলি বা অন্ধকার অনুসন্ধান প্রক্রিয়ার নামগুলি ব্যতীত কোনও পূর্ববর্তী উইন্ডোতে ইতিমধ্যে বিদ্যমান উইন্ডো আনতে দেয়।

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);

static readonly string guid = "<Application Guid>";

static void Main()
{
    Mutex mutex = null;
    if (!CreateMutex(out mutex))
        return;

    // Application startup code.

    Environment.SetEnvironmentVariable(guid, null, EnvironmentVariableTarget.User);
}

static bool CreateMutex(out Mutex mutex)
{
    bool createdNew = false;
    mutex = new Mutex(false, guid, out createdNew);

    if (createdNew)
    {
        Process process = Process.GetCurrentProcess();
        string value = process.Id.ToString();

        Environment.SetEnvironmentVariable(guid, value, EnvironmentVariableTarget.User);
    }
    else
    {
        string value = Environment.GetEnvironmentVariable(guid, EnvironmentVariableTarget.User);
        Process process = null;
        int processId = -1;

        if (int.TryParse(value, out processId))
            process = Process.GetProcessById(processId);

        if (process == null || !SetForegroundWindow(process.MainWindowHandle))
            MessageBox.Show("Unable to start application. An instance of this application is already running.");
    }

    return createdNew;
}

সম্পাদনা: আপনি mutex সংরক্ষণ এবং আরম্ভ করতে পারেন এবং নতুনভাবে স্ট্যাটিক্যালি তৈরি করতে পারেন, তবে আপনি এটি সম্পন্ন হয়ে গেলে মু्यूटক্সটিকে স্পষ্টভাবে নিষ্পত্তি / মুক্ত করতে হবে। ব্যক্তিগতভাবে, আমি mutex স্থানীয় রাখা পছন্দ করি কারণ এটি মুখ্য শেষের শেষে পৌঁছাতে থাকলেও অ্যাপ্লিকেশান বন্ধ হয়ে গেলে স্বয়ংক্রিয়ভাবে নিষ্পত্তি করা হবে।


এখানে একটি সমাধান:

Protected Overrides Sub OnStartup(e As StartupEventArgs)
    Const appName As String = "TestApp"
    Dim createdNew As Boolean
    _mutex = New Mutex(True, appName, createdNew)
    If Not createdNew Then
        'app is already running! Exiting the application
        MessageBox.Show("Application is already running.")
        Application.Current.Shutdown()
    End If
    MyBase.OnStartup(e)
End Sub

এটি হ্যান্ডেল করার একটি দুর্দান্ত উপায় রয়েছে বলে মনে হচ্ছে:

blogs.microsoft.co.il/blogs/arik/archive/2010/05/28/…

এটি এমন একটি ক্লাস সরবরাহ করে যা আপনি সমস্ত মু्यूटক্স এবং মেসেজিং ক্রাফ পরিচালনা করতে পারেন যেখানে এটি আপনার বাস্তবায়নকে সহজতর করে যেখানে এটি কেবল তুচ্ছ।


যদিও Mutex ব্যবহার করে না, সহজ উত্তর:

System.Diagnostics;    
...
string thisprocessname = Process.GetCurrentProcess().ProcessName;

if (Process.GetProcesses().Count(p => p.ProcessName == thisprocessname) > 1)
                return;

ভিতরে এটি রাখুন Program.Main()
উদাহরণ :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

namespace Sample
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            //simple add Diagnostics namespace, and these 3 lines below 
            string thisprocessname = Process.GetCurrentProcess().ProcessName;
            if (Process.GetProcesses().Count(p => p.ProcessName == thisprocessname) > 1)
                return;

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Sample());
        }
    }
}

আপনি স্ট্যাটেন্ট যোগ MessageBox.Showকরতে ifএবং "অ্যাপ্লিকেশন ইতিমধ্যে চলমান" রাখতে পারেন।
এই কেউ সহায়ক হতে পারে।


আপনি CodeFluent রানটাইম ব্যবহার করতে পারেন যা সরঞ্জামগুলির বিনামূল্যে সেট। এটি একটি একক ইনস্ট্যান্স অ্যাপ্লিকেশন বাস্তবায়নের জন্য একটি SingleInstance ক্লাস সরবরাহ করে।


আপনি একটি একক-ইনস্ট্যান্স অ্যাপ্লিকেশন বাস্তবায়ন করতে (অথবা কমপক্ষে কোডের জন্য নয়) একটি নামযুক্ত mutex ব্যবহার করা উচিত নয়। ক্ষতিকারক কোডটি সহজেই আপনার গাধাকে ( পরিষেবা অস্বীকার করা ) করতে পারে ...


আমি এখানে একটি সংক্ষিপ্ত সমাধান খুঁজে পাচ্ছি না sooo আমি আশা করি কেউ এই পছন্দ করবে:

আপডেট 2018-09-20

(বিটিউ। কোডটি আপনার মধ্যে "প্রোগ্রাম.cs" রাখুন )

    using System.Diagnostics;

    static void Main()
    {
        Process ThisProcess = Process.GetCurrentProcess();
        Process[] AllProcesses = Process.GetProcessesByName(ThisProcess.ProcessName);
        if (AllProcesses.Length > 1)
        {
            //Don't put a MessageBox in here because the user could spam this MessageBox.
            return;
        }

// ঐচ্ছিক কোড। যদি কেউ চায় না যে কেউ চালনা করে তবে আপনি একটি ভিন্ন নামের সাথে ".exe" আছেন:

        string exeName = AppDomain.CurrentDomain.FriendlyName;
        if (exeName != "the name of you're executable.exe") // If u try that in debug mode, don't forget that u don't use ur normal .exe. Debug uses the .vshost.exe.
        {// You can add here a MassageBox if you want. To point users that the name got changed and maybe what the name should be or something like that^^ 
            MessageBox.Show("The executable name should be \"the name of you're executable.exe\"", 
            "Wrong executable name", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        //Following Code is default code:
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }

আমি সহজ সমাধান খুঁজে পেয়েছিলাম, ডেল রাগান এর অনুরূপ, কিন্তু সামান্য সংশোধন করা হয়েছে। এটি আপনার প্রয়োজনীয় সবকিছু এবং স্ট্যান্ডার্ড মাইক্রোসফ্ট উইন্ডোজফর্ম অ্যাপ্লিকেশন বেস ক্লাসের উপর ভিত্তি করে।

প্রথমত, আপনি SingleInstanceController ক্লাসটি তৈরি করেন, যা আপনি অন্য সমস্ত একক-ইনস্ট্যান্স অ্যাপ্লিকেশানগুলিতে ব্যবহার করতে পারেন, যা উইন্ডোজ ফর্মগুলি ব্যবহার করে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;


namespace SingleInstanceController_NET
{
    public class SingleInstanceController
    : WindowsFormsApplicationBase
    {
        public delegate Form CreateMainForm();
        public delegate void StartNextInstanceDelegate(Form mainWindow);
        CreateMainForm formCreation;
        StartNextInstanceDelegate onStartNextInstance;
        public SingleInstanceController(CreateMainForm formCreation, StartNextInstanceDelegate onStartNextInstance)
        {
            // Set whether the application is single instance
            this.formCreation = formCreation;
            this.onStartNextInstance = onStartNextInstance;
            this.IsSingleInstance = true;

            this.StartupNextInstance += new StartupNextInstanceEventHandler(this_StartupNextInstance);                      
        }

        void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e)
        {
            if (onStartNextInstance != null)
            {
                onStartNextInstance(this.MainForm); // This code will be executed when the user tries to start the running program again,
                                                    // for example, by clicking on the exe file.
            }                                       // This code can determine how to re-activate the existing main window of the running application.
        }

        protected override void OnCreateMainForm()
        {
            // Instantiate your main application form
            this.MainForm = formCreation();
        }

        public void Run()
        {
            string[] commandLine = new string[0];
            base.Run(commandLine);
        }
    }
}

তারপরে আপনি নিম্নরূপ আপনার প্রোগ্রামে এটি ব্যবহার করতে পারেন:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using SingleInstanceController_NET;

namespace SingleInstance
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static Form CreateForm()
        {
            return new Form1(); // Form1 is used for the main window.
        }

        static void OnStartNextInstance(Form mainWindow) // When the user tries to restart the application again,
                                                         // the main window is activated again.
        {
            mainWindow.WindowState = FormWindowState.Maximized;
        }
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);            
            SingleInstanceController controller = new SingleInstanceController(CreateForm, OnStartNextInstance);
            controller.Run();         
        }
    }
}

প্রোগ্রাম এবং একক ইনস্ট্যান্স কন্ট্রোলার_এনইটি সমাধান উভয় মাইক্রোসফ্ট রেফারেন্স করা উচিত। ভিসুয়াল বেসিক। ব্যবহারকারী চলমান প্রোগ্রামটি পুনরায় চালু করার চেষ্টা করলে স্বাভাবিক উইন্ডো হিসাবে চলমান অ্যাপ্লিকেশনটি পুনরায় সক্রিয় করতে চাইলে, SingleInstanceController এর দ্বিতীয় প্যারামিটারটি নিল হতে পারে। প্রদত্ত উদাহরণে, উইন্ডোটি সর্বাধিক করা হয়।


নামযুক্ত-ম্যুটক্স ভিত্তিক পন্থাগুলি ক্রস-প্ল্যাটফর্ম নয় কারণ নামকরণ করা মৌটসগুলি মোনোতে বিশ্বব্যাপী নয়। প্রক্রিয়া-পরিমাপ-ভিত্তিক পন্থাগুলিতে কোনও সিঙ্ক্রোনাইজেশন নেই এবং এর ফলে ভুল আচরণ হতে পারে (উদাহরণস্বরূপ একাধিক প্রসেস একই সময়ে শুরু হতে পারে যা সমস্ত সময়ের উপর নির্ভর করে আত্মসমর্পণ করতে পারে)। Windowing- সিস্টেম ভিত্তিক পন্থা একটি কনসোল অ্যাপ্লিকেশন এ পছন্দসই নয়। ডিভিনের উত্তরের উপরে নির্মিত এই সমাধানটি এই সব সমস্যার সমাধান করে:

using System;
using System.IO;

namespace TestCs
{
    public class Program
    {
        // The app id must be unique. Generate a new guid for your application. 
        public static string AppId = "01234567-89ab-cdef-0123-456789abcdef";

        // The stream is stored globally to ensure that it won't be disposed before the application terminates.
        public static FileStream UniqueInstanceStream;

        public static int Main(string[] args)
        {
            EnsureUniqueInstance();

            // Your code here.

            return 0;
        }

        private static void EnsureUniqueInstance()
        {
            // Note: If you want the check to be per-user, use Environment.SpecialFolder.ApplicationData instead.
            string lockDir = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
                "UniqueInstanceApps");
            string lockPath = Path.Combine(lockDir, $"{AppId}.unique");

            Directory.CreateDirectory(lockDir);

            try
            {
                // Create the file with exclusive write access. If this fails, then another process is executing.
                UniqueInstanceStream = File.Open(lockPath, FileMode.Create, FileAccess.Write, FileShare.None);

                // Although only the line above should be sufficient, when debugging with a vshost on Visual Studio
                // (that acts as a proxy), the IO exception isn't passed to the application before a Write is executed.
                UniqueInstanceStream.Write(new byte[] { 0 }, 0, 1);
                UniqueInstanceStream.Flush();
            }
            catch
            {
                throw new Exception("Another instance of the application is already running.");
            }
        }
    }
}

নিম্নলিখিত কোডটি আমার ডাব্লুসিএফ নামক পাইপ সমাধান একটি একক-ইনস্ট্যান্স অ্যাপ্লিকেশন নিবন্ধন। এটি চমৎকার কারণ এটি একটি ইভেন্টও উত্থাপন করে যখন অন্য উদাহরণটি শুরু করার প্রচেষ্টা করে এবং অন্য দৃষ্টান্তের কমান্ড লাইন পায়।

এটি WPF এর দিকে পরিচালিত কারণ এটি System.Windows.StartupEventHandlerক্লাস ব্যবহার করে তবে এটি সহজেই সংশোধন করা যেতে পারে।

এই কোড PresentationFramework, এবং একটি রেফারেন্স প্রয়োজন System.ServiceModel

ব্যবহার:

class Program
{
    static void Main()
    {
        var applicationId = new Guid("b54f7b0d-87f9-4df9-9686-4d8fd76066dc");

        if (SingleInstanceManager.VerifySingleInstance(applicationId))
        {
            SingleInstanceManager.OtherInstanceStarted += OnOtherInstanceStarted;

            // Start the application
        }
    }

    static void OnOtherInstanceStarted(object sender, StartupEventArgs e)
    {
        // Do something in response to another instance starting up.
    }
}

সোর্স কোড:

/// <summary>
/// A class to use for single-instance applications.
/// </summary>
public static class SingleInstanceManager
{
  /// <summary>
  /// Raised when another instance attempts to start up.
  /// </summary>
  public static event StartupEventHandler OtherInstanceStarted;

  /// <summary>
  /// Checks to see if this instance is the first instance running on this machine.  If it is not, this method will
  /// send the main instance this instance's startup information.
  /// </summary>
  /// <param name="guid">The application's unique identifier.</param>
  /// <returns>True if this instance is the main instance.</returns>
  public static bool VerifySingleInstace(Guid guid)
  {
    if (!AttemptPublishService(guid))
    {
      NotifyMainInstance(guid);

      return false;
    }

    return true;
  }

  /// <summary>
  /// Attempts to publish the service.
  /// </summary>
  /// <param name="guid">The application's unique identifier.</param>
  /// <returns>True if the service was published successfully.</returns>
  private static bool AttemptPublishService(Guid guid)
  {
    try
    {
      ServiceHost serviceHost = new ServiceHost(typeof(SingleInstance));
      NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
      serviceHost.AddServiceEndpoint(typeof(ISingleInstance), binding, CreateAddress(guid));
      serviceHost.Open();

      return true;
    }
    catch
    {
      return false;
    }
  }

  /// <summary>
  /// Notifies the main instance that this instance is attempting to start up.
  /// </summary>
  /// <param name="guid">The application's unique identifier.</param>
  private static void NotifyMainInstance(Guid guid)
  {
    NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
    EndpointAddress remoteAddress = new EndpointAddress(CreateAddress(guid));
    using (ChannelFactory<ISingleInstance> factory = new ChannelFactory<ISingleInstance>(binding, remoteAddress))
    {
      ISingleInstance singleInstance = factory.CreateChannel();
      singleInstance.NotifyMainInstance(Environment.GetCommandLineArgs());
    }
  }

  /// <summary>
  /// Creates an address to publish/contact the service at based on a globally unique identifier.
  /// </summary>
  /// <param name="guid">The identifier for the application.</param>
  /// <returns>The address to publish/contact the service.</returns>
  private static string CreateAddress(Guid guid)
  {
    return string.Format(CultureInfo.CurrentCulture, "net.pipe://localhost/{0}", guid);
  }

  /// <summary>
  /// The interface that describes the single instance service.
  /// </summary>
  [ServiceContract]
  private interface ISingleInstance
  {
    /// <summary>
    /// Notifies the main instance that another instance of the application attempted to start.
    /// </summary>
    /// <param name="args">The other instance's command-line arguments.</param>
    [OperationContract]
    void NotifyMainInstance(string[] args);
  }

  /// <summary>
  /// The implementation of the single instance service interface.
  /// </summary>
  private class SingleInstance : ISingleInstance
  {
    /// <summary>
    /// Notifies the main instance that another instance of the application attempted to start.
    /// </summary>
    /// <param name="args">The other instance's command-line arguments.</param>
    public void NotifyMainInstance(string[] args)
    {
      if (OtherInstanceStarted != null)
      {
        Type type = typeof(StartupEventArgs);
        ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
        StartupEventArgs e = (StartupEventArgs)constructor.Invoke(null);
        FieldInfo argsField = type.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic);
        Debug.Assert(argsField != null);
        argsField.SetValue(e, args);

        OtherInstanceStarted(null, e);
      }
    }
  }
}

শুধু কিছু চিন্তাভাবনা: কিছু ক্ষেত্রেই যখন কোনও অ্যাপ্লিকেশনটির কেবল একটি উদাহরণ প্রয়োজন তখন "লঙ্গ" হয় না কারন কেউ আপনাকে বিশ্বাস করবে। ডেটাবেস অ্যাপ্লিকেশন, ইত্যাদি পরিধি আরো কঠিন হলে একক ব্যবহারকারীকে ডেটাবেস অ্যাক্সেস করার জন্য অ্যাপ্লিকেশনের একাধিক দৃষ্টান্তের অনুমতি দেয় (আপনি জানেন, সমস্ত রেকর্ড যা আপডেট করে ব্যবহারকারীর অ্যাপ্লিকেশনের একাধিক ক্ষেত্রে খোলা থাকে মেশিন, ইত্যাদি)। প্রথমত, "সংঘর্ষের নামটির জন্য, মানুষের পঠনযোগ্য নাম ব্যবহার করবেন না - পরিবর্তে একটি GUID ব্যবহার করুন অথবা এমনকি GUID + মানুষের পঠনযোগ্য নামটি আরও ভালো করুন। নাম সংঘর্ষের সম্ভাবনাগুলি কেবল রাডার বন্ধ করে দেওয়া হয়েছে এবং মু्यूटক্স যত্ন নিচ্ছে না যেহেতু কেউ নির্দেশ করেছে, একটি ডস আক্রমণ আঘাত করবে, কিন্তু যদি দূষিত ব্যক্তিটি mutex নামটি পেতে এবং তাদের অ্যাপ্লিকেশানে এটি অন্তর্ভুক্ত করার সমস্যাটি চলে গেছে,আপনি যাইহোক একটি টার্গেট অনেক বেশি এবং শুধুমাত্র একটি mutex নাম fiddle তুলনায় নিজেকে রক্ষা করার জন্য আরো অনেক কিছু করতে হবে। এছাড়াও, যদি কেউ একটি নতুন সংস্করণ ব্যবহার করে: নতুন Mutex (সত্য, "কিছু GUID প্লাস নাম", এআইএসফারস্টইনস্টেন্স আউট), আপনার কাছে ইতিমধ্যেই আপনার নির্দেশক আছে যে ম্যুটক্স প্রথম উদাহরণ।


সাধারণত যখনই আমরা .exe চালাও, প্রতিবার এটি নিজস্ব ঠিকানা স্থান, সংস্থান এবং আরও কিছু সহ একটি পৃথক উইন্ডোজ প্রক্রিয়া তৈরি করে। কিন্তু আমরা এই মানদণ্ড চাই না কারণ এটি আমাদেরকে একক প্রক্রিয়া তৈরি করতে বাধা দেবে। সিঙ্গেল ইনস্ট্যান্স অ্যাপ্লিকেশনগুলি C # এ Mutex ব্যবহার করে তৈরি করা যেতে পারে যা এই নিবন্ধে আলোচনা করা হয়েছে

তাছাড়া আমরা যদি আবেদনটি শীর্ষে আনতে চাই তবে আমরা এটি ব্যবহার করতে পারি

 [DllImport("user32")]
 static extern IntPtr SetForegroundWindow(IntPtr hWnd);




mutex