我的小应用程序出现严重问题;基本上它很容易理解:
我的软件在打开时就可以做到。
我想专注于打开另一个实例(我的意思是再次打开.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,但我无法使其发挥作用。
有人可以帮帮我吗?它是一个基本的软件,做了一些非常基本的事情,但是我花了一天时间让它按照我想要的方式工作!
答案 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