如果应用程序的实例已在运行,请在已运行的实例中调用方法

时间:2016-02-18 00:16:33

标签: c# winforms ipc

我有一个由系统托盘notifyIcon及其上下文菜单组成的应用程序。在program.cs代码中,我使用Mutex来检查程序的实例是否已经在运行之前开始运行。目前,如果一个人已经在运行,那么新实例就会在那里退出。相反,当用户尝试启动应用程序的新实例时,我希望它在正在运行的实例中触发notifyIcon的上下文菜单。有没有办法做到这一点?有没有一种方法可以在已经运行的进程中调用方法并告诉它打开菜单?

我找到了this有趣的文章,它引用了this文章。两者都有一些非常有前途的代码,基本上如何做我想要的。但是,他们的代码会覆盖WndProc方法,我对此几乎一无所知。当我使用他们的代码时,我得到了“没有找到合适的方法来覆盖”的错误,我收集的是因为我的notifyIcon和上下文菜单的主要代码,没有实际的形式,并且来自我对{{3}的有限理解,WndProc是一种实际形式的方法。

我了解他们的解决方案以及我得到的错误吗?如果没有,请解释,我很高兴学习。如果我理解,那么有没有办法让我只需触发notifyIcon的上下文菜单而不必拥有实际的表单?

注意:对于记录,我的program.cs遵循所提供的第二个链接中的一个格式。

如上所述,我的program.cs几乎与第二个链接中的program.cs相同,但这里只是要明确:

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

namespace Context_Menu
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>

        static Mutex mutex = new Mutex(true, "{41264ee37e7688d64250ffb50dc681d2}");

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            if (mutex.WaitOne(TimeSpan.Zero, true))
            {
                Application.Run(new PCMLnotifyIcon());
                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类也与链接中的类相同,如下所示:

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

最后,PCMLNotifyIcon主要基于here指南,因此只是一个没有附带表格的notifyIcon。下面是一个片段,显示我从第二个链接中删除代码的位置:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace Context_Menu
{
    class PCMLnotifyIcon : ApplicationContext
    {  
        private NotifyIcon niIcon;
        private ContextMenuStrip cmsMenu;
        private ToolStripMenuItem tsmiUpdate;
        private ToolStripSeparator tssOne;
        private ToolStripMenuItem tsmiQuickAdd;
        private ToolStripSeparator tssTwo;
        private ToolStripSeparator tssThree;
        private ToolStripMenuItem tsmiSettings;
        private ToolStripMenuItem tsmiAbout;
        private ToolStripMenuItem tsmiFeedback;
        private ToolStripMenuItem tsmiExit;

        public PCMLnotifyIcon()
        {
            InitializeComponent();
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == NativeMethods.WM_SHOWME)
            {
                ShowMe();
            }
            base.WndProc(ref m);
        }

如上所述,我怀疑是由于缺少表格而给出的错误:错误1

  

“Context_Menu.PCMLnotifyIcon.WndProc(参照   System.Windows.Forms.Message)':找不到合适的方法来覆盖

2 个答案:

答案 0 :(得分:1)

我会提供一些代码,但我不确定你要完成什么。相反,我会看看我是否可以指出你正确的方向:)我在一个非常相似的例子中使用了一个IPC频道取得了巨大的成功。但是,似乎已经弃用了WCF。虽然它看起来并不太糟糕。您可以使用命名管道代替TCP,它应该非常高效。我认为你会发现这比窗口消息更可靠,窗口消息充其量只是笨重。您可以轻松地本地传递相当大而复杂的有效负载。

查看此文章:https://gorillacoding.wordpress.com/2013/02/03/using-wcf-for-inter-process-communication/

以下是另一个有用的示例:http://adndevblog.typepad.com/cloud_and_mobile/2013/12/inter-process-communication-using-wcf.html

编辑:作为奖励,您可以放弃互斥锁,转而选择是否存在命名管道

答案 1 :(得分:0)

我讨厌翻转这个范例,但你为什么不选择使用管道之类的东西?本来可以更容易做,恕我直言。继续讨论主要问题:在ShowMe();之后,添加return。像这样:

protected override void WndProc(ref Message m)
{
    if (m.Msg == NativeMethods.WM_SHOWME)
    {
        ShowMe();
        return;  // <-- right here!
    }
    base.WndProc(ref m);
}

HTH!