停止WinForms应用程序第二次运行,如果是这样,关闭第一个示例[重复]

eiee3dmh  于 2023-11-21  发布在  其他
关注(0)|答案(1)|浏览(98)

此问题在此处已有答案

Activating the main form of a single instance application(3个答案)
17天前关闭。
截至17天前,社区正在审查是否重新讨论这个问题。
我正在用WinForms做一个项目,我想确保它不会同时运行两次。这是一个在后台安静工作的程序。我已经想出了如何检测是否有人试图再次打开它。
我使用这个函数来检测程序是否正在运行:

private bool IsAlreadyRuning()
{
    const string appName = "RocketAlert";
    bool createdNew;
    mutex = new Mutex(true, appName, out createdNew);

    if (!createdNew)
    {
        return true;
    }
    return false;
}

字符串
现在,我想让它关闭已经运行的程序,如果它检测到它已经运行。我如何才能实现这一点?
我试图对“NamedPipeClientStream”进行调整,但它在我的项目中的存在似乎导致了问题。程序无法启动或无法读取文件。

vi4fp9gy

vi4fp9gy1#

为了满足问题的第一个子句停止WinForms应用程序第二次运行,检测应用程序的可重入示例的一种传统方法是设置Mutex
随后调用静态入口点static void Main()的尝试将无法进入互斥块。如果目标是阻止新示例运行,那么根据我最初的回答,利用这个机会让正在运行的示例单独运行,并阻止新示例运行。
为了满足问题的第二个子句if it does,close the first instance,我们可以采取不同的方法。使用Program.cs的 * 原始无互斥体 * 版本,在注意从效果中接种自身之后,使主窗体类广播WM_USER消息。MainForm的其他窗口示例现在将自行关闭。

public partial class MainForm : Form
{
    SemaphoreSlim sslimNotMe = new SemaphoreSlim(0, 1);
    public MainForm() => InitializeComponent();
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        Text = "Creation Time " +  DateTime.Now.ToString(@"hh\:mm\:ss tt");
        if (!PostMessage((IntPtr)HWND_BROADCAST, WM_SWAP_FOR_NEW_INSTANCE, IntPtr.Zero, IntPtr.Zero))
        {
            MessageBox.Show("Failed to post message");
        }
    }
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SWAP_FOR_NEW_INSTANCE)
        {
            try
            {
                if (sslimNotMe.Wait(0))
                {
                    Close();
                }
            }
            finally
            {
                sslimNotMe.Release();
            }
        }
        base.WndProc(ref m);
    }

    public static int WM_SWAP_FOR_NEW_INSTANCE { get; } = RegisterWindowMessage("{FC0A54D8-F999-493A-B8D1-DF4E8FCF08E4}");

    #region Dll Imports
    private const int HWND_BROADCAST = 0xFFFF;
    [DllImport("user32")]
    private static extern int RegisterWindowMessage(string message);

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

    #endregion Dll Imports
}

字符串
上一个答案,使用Mutex来避免新示例(根据问题的第一部分)。

internal static class Program
{
    /// <summary>
    ///  The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        if(Mutex.WaitOne(TimeSpan.Zero, true))
        {
            try
            {
                ApplicationConfiguration.Initialize();
                Application.Run(new MainForm());
            }
            finally
            {
                Mutex.ReleaseMutex();
            }
        }
        else
        {
            MessageBox.Show(Form.ActiveForm, "The app is already running!");
        }
    }
    static Mutex Mutex = new Mutex(
        true,
        // Use Tools\Create Guid to generate an arbitrary identifier.
        "{FD4DF30D-C22A-499C-A814-EA2A21BDE585}"
    );
}

相关问题