将参数传递给同一应用程序的另一个实例

时间:2016-05-26 13:45:12

标签: c# arguments pipe instance msmq

我的小应用程序出现严重问题;基本上它很容易理解:

我的软件在打开时就可以做到。

我想专注于打开另一个实例(我的意思是再次打开.exe),检查它是否已经打开。如果不是简单地启动应用程序,但如果它已经运行(AKA第二次或更多实例)"简单地"将输入参数( args字符串数组)传递给第一个实例,它将适当地处理它。

这是我的program.cs

static class Program
{
    static Mutex mutex = new Mutex(true, "{blabla}");

    [STAThread]
    static void Main(String[] args)
    {
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            //First Instance!

            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                CALL A MY STATIC METHOD, DO SOME THINGS

                Application.Run(new Form1());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        else
        {
            //Not-so-first instance!
            CALL A STATIC METHOD, 
            DO OTHER THINGS LIKE COMUNICATE WITH FIRST INSTANCE

            SIMPLY CLOSE.
        }
    }
}

这只会识别(使用互斥锁)它是否已经打开但是(当然)它无法与主实例进行任何通信。

我已经尝试过很多东西,但是我无法让它发挥作用。

我已经尝试了this但是我真的不明白(经过大量的时间浪费)如何把我的第一次"第一次"代码和"已经运行"代码。

也试过MSMQ,但我无法使其发挥作用。

有人可以帮帮我吗?它是一个基本的软件,做了一些非常基本的事情,但是我花了一天时间让它按照我想要的方式工作!

3 个答案:

答案 0 :(得分:1)

使用Mutex

    // Generate your GUID and put it here
    private const string ProgramRunningGuid = "BD2023EE-F7B3-47B8-8C76-32668196E4D3";
    private Mutex _mutex;

    private bool IsProgramRunning()
    {
        bool createdNew;
        // It returns a bool value determining if a Mutex that created is new
        // If the program is already running mutex wouldn't be new
        _mutex = new Mutex(true, ProgramRunningGuid, out createdNew);
        return !createdNew;
    }

在程序退出时,您需要释放互斥锁:

    _needlesRunningMutex.ReleaseMutex();

如果您想关注已经运行的应用程序实例,可以在此处使用工作解决方案检查我的答案:https://stackoverflow.com/a/35018042/3731444

如果您只需要共享一些bool参数来确定是否打开或关闭了某些内容,您可以为每个参数使用互斥锁。

如果您在启动时需要将参数传递给.exe,请检查以下问题:How to pass parameters to an exe?

如果您需要在正在运行的应用程序的两个实例之间进行持续通信,请继续使用MSMQ。如果有任何问题,我会尽力帮助你。

在此处查看如何使用MSMQ:https://github.com/IvanYurchenko/MSMQSample

答案 1 :(得分:0)

最简单的通信方式之一是将第二个实例的Windows消息发送到第一个实例。第二个实例将使用PostMessage发送消息,第一个实例将覆盖Form1的WndProc方法来处理消息。

这里有一个例子: Send message to a Windows process (not its main window)

该问题还有一个使用管道(和WCF)进行通信的答案。

有许多形式的进程间通信。您使用哪一个取决于您的需求,例如Windows消息不能携带大量信息,而管道可以非常高的速度传输数据。

<强>更新 一个简单的替代方案可能是IPCChannel。这允许您在第一个实例中创建可由第二个实例调用的对象。您可以在该对象上创建方法并将数据作为参数传递

答案 2 :(得分:0)

我通过文本文件传递参数(我确定您可以从VB.NET/伪代码进行翻译):

Private _uniqueEventName As String
Private _uniqueMutexName As String
Private _eventWaitHandle As EventWaitHandle
Private _mutex As Mutex

Private Sub ensureSingleInstance()
    _uniqueEventName = "{0ae64101-e630-4221-bf10-123fdddd5ab2}" + Assembly.GetEntryAssembly().GetName().Name
    _uniqueMutexName = "{03169a07-793b-48c6-8ceb-1232388cb69a}" + Assembly.GetEntryAssembly().GetName().Name

    Dim isOwned As Boolean
    _mutex = New Mutex(True, _uniqueMutexName, isOwned)
    _eventWaitHandle = New EventWaitHandle(False, EventResetMode.AutoReset, _uniqueEventName)

    GC.KeepAlive(_mutex)

    If isOwned Then
        Dim thread As Thread = New Thread(
                               Sub()
                                   While _eventWaitHandle.WaitOne()
                                       Application.Dispatcher.BeginInvoke(
                                           Sub()
                                               ' ****************************************************
                                               ' READ AND PROCESS THE ARGUMENTS FROM C:\MYAPPARGS.TXT
                                               ' ****************************************************

                                               If Not Application.MainWindow Is Nothing Then
                                                   _loggingDAL.Log("Activating main window")

                                                   If (Application.MainWindow.WindowState = WindowState.Minimized Or Application.MainWindow.Visibility = Visibility.Hidden) Then
                                                       Application.MainWindow.Show()
                                                       Application.MainWindow.WindowState = WindowState.Normal
                                                   End If

                                                   Application.MainWindow.Activate()
                                                   Dim topMost As Boolean = Application.MainWindow.Topmost
                                                   Application.MainWindow.Topmost = True
                                                   Application.MainWindow.Topmost = topMost
                                                   Application.MainWindow.Focus()
                                               End If
                                           End Sub)
                                   End While
                               End Sub)
        thread.IsBackground = True
        thread.Start()
    Else
        _loggingDAL.Log("There is already an instance running -> switching and quitting")

        ' ***************************************
        ' WRITE THE ARGUMENTS TO C:\MYAPPARGS.TXT
        ' ***************************************

        _eventWaitHandle.Set()
        Application.Shutdown()
    End If
End Sub