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

C# 如果应用程序的实例已在运行,请在已运行的实例中调用方法,c#,winforms,ipc,C#,Winforms,Ipc,我有一个应用程序,它由一个系统图标和它的上下文菜单组成。在program.cs代码中,我使用互斥来检查程序实例是否已在运行,然后再启动一个新实例。当前,如果一个实例已经在运行,那么新实例就在那里退出。相反,当用户尝试启动应用程序的新实例时,我希望它触发正在运行的实例中notifyIcon的上下文菜单。有办法做到这一点吗?有没有一种好方法可以在已经运行的进程中调用一个方法并告诉它打开菜单 我发现了一篇有趣的文章,它指的是文章。它们都有一些非常有前途的代码,关于如何基本上做我想要的事情。然而,他们的

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

我发现了一篇有趣的文章,它指的是文章。它们都有一些非常有前途的代码,关于如何基本上做我想要的事情。然而,他们的代码覆盖了WndProc方法,对此我知之甚少。当我使用他们的代码时,我得到了一个错误“找不到合适的方法来覆盖”,我收集到这个错误是因为我的notifyIcon和上下文菜单的主代码没有实际的形式,并且从我对WndProc的有限理解来看,WndProc是一个实际形式的方法

我是否正确理解他们的解决方案和错误?如果没有,请解释,我很高兴学习。如果我理解,那么有没有一种方法可以让我只触发notifyIcon的上下文菜单,而不需要实际的表单

注意:为了记录,my program.cs遵循提供的第二个链接中的格式

如前所述,my 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);
            }
        }
    }
}
最后,PCMLNotifyIcon主要基于guide,因此它只是一个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

'上下文菜单.PCMLnotifyIcon.WndProc(参考 System.Windows.Forms.Message:“”未找到可重写的合适方法


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

查看本文:

下面是另一个您可能会发现有用的示例:


编辑:作为一种奖励,您可以删除互斥对象,以便测试命名管道的存在性

我不喜欢改变这种模式,但是为什么您不选择使用类似管道的东西呢?这样做会容易得多,伊姆霍。转到手头的主要问题:在
ShowMe()之后
,放置一个
返回值
。像这样:

protected override void WndProc(ref Message m)
{
    if (m.Msg == NativeMethods.WM_SHOWME)
    {
        ShowMe();
        return;  // <-- right here!
    }
    base.WndProc(ref m);
}
受保护的覆盖无效WndProc(参考消息m)
{
if(m.Msg==NativeMethods.WM_SHOWME)
{
ShowMe();

return;//选择IPC。“我发现了错误”-请发布代码。请参阅“因为我的notifyIcon和上下文菜单主代码没有实际形式”-您使用的是
NotifyIcon
而不是嵌入在
表单中的
吗?我确实是这样。我使用的是这里详述的方法。原因是程序启动时不需要表单。只需要NotifyIcon及其菜单。我用代码更新了问题以显示。正如我在原始问题中提到的,代码是vi从第二个链接算起,问题似乎是我没有实际的形式。所以我假设这意味着我需要找到一种完全不同的方式来实现这一点?啊,是的。NET远程处理。我同意作为一种直接的通信选择(即使是本地计算机)它已经被弃用了。尽管它在沙盒插件系统中与child
AppDomain
s进行通信时仍然很有用,但我离题了:)顺便说一下“IPC”只是指一个程序与另一个程序对话的功能。它实际上并不是指任何特定的传输、技术或协议。NET Remoting是一个IPC,但它不是IPC。“我不确定MSMQ是从哪里输入的”-哦,不,那是我的错。我看到了“而不是窗口消息”MSMQ想。我现在知道OP是通过Windows消息泵发布消息的。对不起,伙计们,我也可以更具体地描述IPC,这就是我所指的:是的,微软把很多人和“IPC”混淆了名称。它们的意思是命名管道。Lowry在他的文章中提到了这一点。他说:“我仍然保留互斥体……管道很好,只是在不写一些(可能很多?)的情况下确保唯一性还不够好。”关于脚手架代码…谢谢你的建议,但我不确定这会有什么帮助。不过,我尝试了一下,但我仍然遇到了WndProc不是ApplicationContext的方法的问题,而ApplicationContext正是我的类的来源。我想只有当你有一个实际的形式时,这个方法才可用。除非我误解了我在这儿等你。
protected override void WndProc(ref Message m)
{
    if (m.Msg == NativeMethods.WM_SHOWME)
    {
        ShowMe();
        return;  // <-- right here!
    }
    base.WndProc(ref m);
}