214 lines
6.4 KiB
C#
214 lines
6.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Runtime.Remoting.Channels;
|
|
using System.Runtime.Remoting.Channels.Ipc;
|
|
using System.Threading;
|
|
using JD.Kernel.StaticHelpers;
|
|
|
|
namespace JD.TeaBoxAddinSystem.Bootstrap
|
|
{
|
|
/// <summary>
|
|
/// This class is used to check whether there already exists other instances of the application running,
|
|
/// and to communicate with the "main" instance.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This class assumes that this library is in the same directory as the entry exe.
|
|
/// </remarks>
|
|
public sealed class ApplicationInstanceManager : MarshalByRefObject, IDisposable
|
|
{
|
|
#region Delegates
|
|
|
|
/// <summary>
|
|
/// Delegate for method that can receive a string array.
|
|
/// </summary>
|
|
/// <param name="args"></param>
|
|
public delegate object ReceiveDelegate(string[] args);
|
|
|
|
#endregion
|
|
|
|
#region Variables
|
|
|
|
private const string ServiceName = "Remoting";
|
|
|
|
private readonly string m_uniqueIdentifier;
|
|
private readonly IpcChannel m_ipcChannel;
|
|
private readonly Mutex m_mutex = null;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// </summary>
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")]
|
|
public ApplicationInstanceManager(string uniqueIdentifier)
|
|
{
|
|
Throw.IfEmpty(uniqueIdentifier, "uniqueIdentifier");
|
|
|
|
m_uniqueIdentifier = uniqueIdentifier;
|
|
|
|
/*LogService.LogMessage("Trying to lock '" + UniqueIdentifier + "' mutex.", MessageImportance.Debug);
|
|
m_mutex = new Mutex(false, UniqueIdentifier);
|
|
|
|
if (m_mutex.WaitOne(1, true))
|
|
{
|
|
// We locked it, we are the first instance.
|
|
m_ipcChannel = new IpcChannel(UniqueIdentifier);
|
|
ChannelServices.RegisterChannel(m_ipcChannel, false);
|
|
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ApplicationInstanceManager), ServiceName, WellKnownObjectMode.SingleCall);
|
|
}
|
|
else
|
|
{
|
|
// Not the first instance.
|
|
m_mutex.Close();
|
|
m_mutex = null;
|
|
}*/
|
|
|
|
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
|
|
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
|
|
|
|
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
|
|
|
|
IDictionary props = new Hashtable();
|
|
props["portName"] = UniqueIdentifier + "<" + Process.GetCurrentProcess().Id + ">";
|
|
|
|
m_ipcChannel = new IpcChannel(props, clientProv, serverProv);
|
|
ChannelServices.RegisterChannel(m_ipcChannel, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// DO NOT USE THIS CONSTRUCTOR.
|
|
/// </summary>
|
|
public ApplicationInstanceManager()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finalizer.
|
|
/// </summary>
|
|
~ApplicationInstanceManager()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes this object.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (m_mutex != null)
|
|
{
|
|
m_mutex.Close();
|
|
}
|
|
|
|
if (m_ipcChannel != null)
|
|
{
|
|
ChannelServices.UnregisterChannel(m_ipcChannel);
|
|
m_ipcChannel.StopListening(null);
|
|
}
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Unique Identifier.
|
|
/// </summary>
|
|
public string UniqueIdentifier
|
|
{
|
|
get
|
|
{
|
|
return m_uniqueIdentifier;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Sends a string array to the "main" instance.
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
public object Send(string[] s)
|
|
{
|
|
return Send(UniqueIdentifier, s);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends a string array to the "main" instance of the application specified by <paramref name="uniqueIdentifier"/>.
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
/// <param name="uniqueIdentifier"></param>
|
|
public static object Send(string uniqueIdentifier, string[] s)
|
|
{
|
|
string completeUrl = "ipc://" + uniqueIdentifier + "/" + ServiceName;
|
|
|
|
try
|
|
{
|
|
ApplicationInstanceManager mainInstance = Activator.GetObject(typeof(ApplicationInstanceManager), completeUrl) as ApplicationInstanceManager;
|
|
return mainInstance.OnReceived(s);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogService.LogService.LogError("Error while sending string array to main instance: {0}", e);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
internal static object LocalSend(string[] args)
|
|
{
|
|
return OnReceivedInternal(args);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if there is already an instance running with the given <paramref name="uniqueIdentifier"/>.
|
|
/// </summary>
|
|
public static bool IsInstanceRunning(string uniqueIdentifier)
|
|
{
|
|
Mutex mutex = new Mutex(false, uniqueIdentifier);
|
|
bool result = !mutex.WaitOne(1, true);
|
|
mutex.Close();
|
|
return result;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// Fired when a string array is received from other temporary instances.
|
|
/// </summary>
|
|
public static event ReceiveDelegate Received;
|
|
|
|
private static object OnReceivedInternal(string[] s)
|
|
{
|
|
if (Received != null)
|
|
{
|
|
return Received(s);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Triggers the <see cref="Received"/> event.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Method needs to be public to be called remotely.
|
|
/// </remarks>
|
|
/// <param name="s">String array</param>
|
|
/// <returns></returns>
|
|
public object OnReceived(string[] s)
|
|
{
|
|
return OnReceivedInternal(s);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|