从应用程序运行一个实例

发布于 2024-07-21 05:18:25 字数 177 浏览 3 评论 0原文

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

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

提前致谢

I have a windows application (C#) and i need to configure it to run one instance from the application at the time , It means that one user clicked the .exe file and the application is run and the user didn't close the first instance of the application that is being run and need to run a next instance so it should appear the first instance and not opening new one.

can any one help me how to do that?

thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

幻想少年梦 2024-07-28 05:18:26

我找到了这个代码,它是工作!

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

I found this code, it's work!

 /// <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;
                }
            }
        }
初见终念 2024-07-28 05:18:25

我经常通过检查其他同名进程来解决这个问题。 这样做的优点/缺点是您(或用户)可以通过重命名 exe 来“退出”检查。 如果您不希望这样,您可以使用返回的 Process 对象。

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

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

I often solve this by checking for other processes with the same name. The advantage/disadvantage with this is that you (or the user) can "step aside" from the check by renaming the exe. If you do not want that you could probably use the Process-object that is returned.

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

It depends on your need, I think it's handy to bypass the check witout recompiling (it's a server process, which sometimes is run as a service).

薄情伤 2024-07-28 05:18:25

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

这是文章中的相关部分:

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");
    }
}

The VB.Net team has already implemented a solution. You will need to take a dependency on Microsoft.VisualBasic.dll, but if that doesn't bother you, then this is a good solution IMHO.
See the end of the following article: Single-Instance Apps

Here's the relevant parts from the article:

1) Add a reference to Microsoft.VisualBasic.dll
2) Add the following class to your project.

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());
    }
}

Open Program.cs and add the following using statement:

using Microsoft.VisualBasic.ApplicationServices;

Change the class to the following:

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");
    }
}
仙女山的月亮 2024-07-28 05:18:25

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

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

您可以从项目 -> 执行此操作 属性-> “应用程序”选项卡

来源

Edit : After the question was amended to include c#. My answer works only for vb.net application

select the Make single instance application check box to prevent users from running multiple instances of your application. The default setting for this check box is cleared, allowing multiple instances of the application to be run.

You can do this from Project -> Properties -> Application tab

Source

十二 2024-07-28 05:18:25

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

基本上我们尝试打开一个文件进行独占读取。 如果失败(因为另一个实例已经完成了此操作),我们会收到异常并可以退出应用程序。

        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();
        }

We had exactly the same problem. We tried the process approach, but this fails, if the user has no right to read information about other processes, i.e. non-admins. So we implemented the solution below.

Basically we try to open a file for exclusive reading. If this fails (because anohter instance has already done this), we get an exception and can quit the app.

        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();
        }
迷迭香的记忆 2024-07-28 05:18:25

假设您使用的是 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());
        }

Assuming you are using 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());
        }
舞袖。长 2024-07-28 05:18:25

对于这种情况,我将使用 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);
    }
}

I'd use a Mutex for this scenario. Alternatively, a Semaphore would also work (but a Mutex seems more apt).

Here's my example (from a WPF application, but the same principles should apply to other project types):

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文