从应用程序运行一个实例

时间:2009-05-25 09:51:49

标签: c# semaphore

我有一个Windows应用程序(C#),我需要将其配置为当时从应用程序运行一个实例,这意味着一个用户单击.exe文件并运行应用程序并且用户没有关闭正在运行的应用程序的第一个实例,需要运行下一个实例,因此它应该显示为第一个实例而不是打开新实例。

任何人都可以帮我怎么做?

提前致谢

7 个答案:

答案 0 :(得分:10)

我经常通过检查具有相同名称的其他进程来解决此问题。这样做的优点/缺点是你(或用户)可以通过重命名exe来“退出”检查。如果你不希望你可以使用返回的Process-object。

  string procName = Process.GetCurrentProcess().ProcessName;
  if (Process.GetProcessesByName(procName).Length == 1)
  {
      ...code here...
  }

这取决于你的需要,我认为在重新编译时绕过检查是很方便的(它是一个服务器进程,有时作为服务运行)。

答案 1 :(得分:4)

VB.Net团队已经实施了一个解决方案。您将需要依赖Microsoft.VisualBasic.dll,但如果这不打扰你,那么这是一个很好的解决方案恕我直言。 请参阅以下文章的结尾:Single-Instance Apps

以下是文章中的相关部分:

1)添加对Microsoft.VisualBasic.dll的引用 2)将以下类添加到项目中。

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
    private SingleInstanceApplication()
    {
        base.IsSingleInstance = true;
    }

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
    {
        SingleInstanceApplication app = new SingleInstanceApplication();
        app.MainForm = f;
        app.StartupNextInstance += startupHandler;
        app.Run(Environment.GetCommandLineArgs());
    }
}

打开Program.cs并添加以下using语句:

using Microsoft.VisualBasic.ApplicationServices;

将课程更改为以下内容:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler);
    }

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
    {
        MessageBox.Show("New instance");
    }
}

答案 2 :(得分:1)

编辑:修改问题后包含c#。我的回答仅适用于vb.net应用程序

选中制作单实例应用程序复选框,以防止用户运行应用程序的多个实例。清除此复选框的默认设置,允许运行多个应用程序实例。

您可以从Project - &gt;执行此操作属性 - &gt;应用程序选项卡

Source

答案 3 :(得分:1)

我们遇到了完全相同的问题。我们尝试了流程方法,但如果用户无权读取有关其他流程的信息,即非管理员,则会失败。所以我们实施了以下解决方案。

基本上我们尝试打开一个独家阅读文件。如果失败(因为anohter实例已经这样做了),我们得到一个异常并且可以退出应用程序。

        bool haveLock = false;
        try
        {
            lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None);
            haveLock = true;
        }
        catch(Exception)
        {
            System.Console.WriteLine("Failed to acquire lock. ");
        }
        if(!haveLock)
        {
            Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already");
            diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20);
            diag.ShowDialog();
            Application.Exit();
        }

答案 4 :(得分:0)

假设您正在使用C#

        static Mutex mx;
        const string singleInstance = @"MU.Mutex";
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                System.Threading.Mutex.OpenExisting(singleInstance);
                MessageBox.Show("already exist instance");
                return;
            }
            catch(WaitHandleCannotBeOpenedException)
            {
                mx = new System.Threading.Mutex(true, singleInstance);

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

答案 5 :(得分:0)

我在此方案中使用Mutex。或者,Semaphore也可以使用(但Mutex似乎更合适。)

这是我的示例(来自WPF应用程序,但相同的原则应适用于其他项目类型):

public partial class App : Application
{
    const string AppId = "MY APP ID FOR THE MUTEX";
    static Mutex mutex = new Mutex(false, AppId);
    static bool mutexAccessed = false;

    protected override void OnStartup(StartupEventArgs e)
    {
        try
        {
            if (mutex.WaitOne(0))
                mutexAccessed = true;
        }
        catch (AbandonedMutexException)
        {
            //handle the rare case of an abandoned mutex
            //in the case of my app this isn't a problem, and I can just continue
            mutexAccessed = true;
        }

        if (mutexAccessed)
            base.OnStartup(e);
        else
            Shutdown();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        if (mutexAccessed)
            mutex?.ReleaseMutex();

        mutex?.Dispose();
        mutex = null;
        base.OnExit(e);
    }
}

答案 6 :(得分:0)

我找到了这个code,它起作用了!

 /// <summary>
        /// The main entry point for the application.
        /// Limit an app.to one instance
        /// </summary>
        [STAThread]
        static void Main()
        {
            //Mutex to make sure that your application isn't already running.
            Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName");
            try
            {
                if (mutex.WaitOne(0, false))
                {
                    // Run the application
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    MessageBox.Show("An instance of the application is already running.",
                        "An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            finally
            {
                if (mutex != null)
                {
                    mutex.Close();
                    mutex = null;
                }
            }
        }