如何在WinForms应用程序的另一个流程实例中调用方法?

我正在使用一个使用Mutex的应用程序来确保它是系统上运行的应用程序的唯一实例。

当另一个应用程序实例尝试启动时,我想要一个方法在原始实例中运行。

我可以从应用程序的另一个实例调用我的应用程序中的特定方法吗?

我发现了一些使用RegisterWindowMessage / PostMessage Win32 API的示例,通过将消息发送到HWND_BROADCAST,但我无法让它们工作,我在其他地方读过使用HWND_BROADCAST可能很危险。

有没有更好的方法来执行此操作,而不涉及需要在特权模式下运行的应用程序?

我之前已经对此进行过研究 – 您可以使用内存映射文件,在本文中演示http://www.codeproject.com/KB/cs/singleinstanceapplication.aspx ,或者您可以做我做过的事情(简单的方法)并利用vb.netfunction(特别是,允许​​您创建单实例应用程序并在当前运行的实例中调用方法,该方法传递命令行参数[因此您可以使用它来调用应用程序中的方法]) 。 我知道在C#中使用VB类听起来有点差,但它是最抽象和简单的方法。 链接到相关文章 – http://www.codeproject.com/KB/cs/CSSIApp.aspx,http://msdn.microsoft.com/en-us/magazine/cc163741.aspx的最后一部分

这是我写的一个小帮手。

要使用它:

var pipeListener = new NamedPipeListener(); // instantiate an instance pipeListener.MessageReceived += (sender, e) => MessageBox.Show(e.Message); // when a message is received, show a messagebox with the message pipeListener.Error += (sender, e) => MessageBox.Show("Error ({0}): {1}", e.ErrorType, e.Exception.Message); // oh noes! pipeListener.Start(); // when you're ready, start listening 

从另一个过程:

 NamedPipeListener.SendMessage("Howdy howdy howdy"); 

请注意,它使用PipeListener的全名作为管道的默认名称。 如果您需要更加谨慎,请使用带有管道名称的构造函数重载。

这是class级:

 using System; using System.IO.Pipes; using System.Runtime.Serialization.Formatters.Binary; namespace FunWithNamedPipes { /// Contains event data for  events. ///  public class NamedPipeListenerMessageReceivedEventArgs : EventArgs { /// Initializes an instance of  with the specified . /// The message passed by the event. public NamedPipeListenerMessageReceivedEventArgs(TMessage message) { this.Message = message; } /// Gets the message passed by the event. public TMessage Message { get; private set; } } /// Contains event data for  events. public class NamedPipeListenerErrorEventArgs : EventArgs { /// Initializes an instance of  with the specified  and . /// A  describing the part of the listener process where the error was caught. /// The  that was thrown. public NamedPipeListenerErrorEventArgs(NamedPipeListenerErrorType errorType, Exception ex) { this.ErrorType = errorType; this.Exception = ex; } /// Gets a  describing the part of the listener process where the error was caught. public NamedPipeListenerErrorType ErrorType { get; private set; } /// Gets the  that was caught. public Exception Exception { get; private set; } } /// Represents a method that will handle an event where a message is received via named pipes. /// The type of message that will be received. /// The source of the event. /// The event data passed by the event, which includes the message that was received. public delegate void NamedPipeMessageReceivedHandler(Object sender, NamedPipeListenerMessageReceivedEventArgs e); /// Represents a method that will handle an event that is fired when an exception is caught. /// The source of the event. /// The event data passed by the event, included the error type and exception that was caught. public delegate void NamedPipeMessageErrorHandler(Object sender, NamedPipeListenerErrorEventArgs e); /// Includes different types of errors that describe where in the listening process an exception was caught. public enum NamedPipeListenerErrorType : byte { /// Indicates that an exception was caught while calling . BeginWaitForConnection = 1, /// Indicates that an exception was caught while calling . EndWaitForConnection = 2, /// Indicates that an exception was caught while deserializing a message received from the named pipe. DeserializeMessage = 3, /// Indicates that an exception was caught while closing or disposing a used named pipe. CloseAndDisposePipe = 4, /// Indicates that an exception was caught while invoking the  event. NotifyMessageReceived = 5 } /// A helper class for sending and receiving messages using named pipes. /// The type of message that will be sent or received. public class NamedPipeListener : IDisposable { /// Occurs when a message is received. public event NamedPipeMessageReceivedHandler MessageReceived; /// Occurs when an exception is caught. public event NamedPipeMessageErrorHandler Error; static readonly String DEFAULT_PIPENAME = typeof(NamedPipeListener).FullName; static readonly BinaryFormatter formatter = new BinaryFormatter(); NamedPipeServerStream pipeServer; /// Initializes a new instance of  using the specified . /// The name of the named pipe that will be used to listen on. public NamedPipeListener(String pipeName) { this.PipeName = pipeName; } /// Initializes a new instance of  using the default pipe name. /// The default pipe name is the full name of the type of the instance. public NamedPipeListener() : this(DEFAULT_PIPENAME) { } /// The name of the named pipe that will be used to listen on. public String PipeName { get; private set; } /// Starts listening on the named pipe specified for the instance. internal void Start() { if (pipeServer == null) pipeServer = new NamedPipeServerStream(DEFAULT_PIPENAME, PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); try { pipeServer.BeginWaitForConnection(new AsyncCallback(PipeConnectionCallback), null); } catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.BeginWaitForConnection, ex); } } private void PipeConnectionCallback(IAsyncResult result) { try { pipeServer.EndWaitForConnection(result); } catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.EndWaitForConnection, ex); return; } TMessage message; try { message = (TMessage)formatter.Deserialize(pipeServer); } catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.DeserializeMessage, ex); return; } try { this.OnMessageReceived(new NamedPipeListenerMessageReceivedEventArgs(message)); } catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.NotifyMessageReceived, ex); return; } if (this.End()) { this.Start(); } } internal Boolean End() { try { pipeServer.Close(); pipeServer.Dispose(); pipeServer = null; return true; } catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.CloseAndDisposePipe, ex); return false; } } private void OnMessageReceived(TMessage message) { this.OnMessageReceived(new NamedPipeListenerMessageReceivedEventArgs(message)); } protected virtual void OnMessageReceived(NamedPipeListenerMessageReceivedEventArgs e) { if (this.MessageReceived != null) { this.MessageReceived(this, e); } } private void OnError(NamedPipeListenerErrorType errorType, Exception ex) { this.OnError(new NamedPipeListenerErrorEventArgs(errorType, ex)); } protected virtual void OnError(NamedPipeListenerErrorEventArgs e) { if (this.Error != null) { this.Error(this, e); } } void IDisposable.Dispose() { if(pipeServer != null) { try { pipeServer.Disconnect(); } catch { } try { pipeServer.Close(); } catch { } try { pipeServer.Dispose(); } catch { } } } /// Sends the specified  to the default named pipe for the message. /// The message to send. public static void SendMessage(TMessage message) { NamedPipeListener.SendMessage(DEFAULT_PIPENAME, message); } /// Sends the specified  to the specified named pipe. /// The name of the named pipe the message will be sent to. /// The message to send. public static void SendMessage(String pipeName, TMessage message) { using (var pipeClient = new NamedPipeClientStream(".", DEFAULT_PIPENAME, PipeDirection.Out, PipeOptions.None)) { pipeClient.Connect(); formatter.Serialize(pipeClient, message); pipeClient.Flush(); pipeClient.WaitForPipeDrain(); pipeClient.Close(); } } } }