什么是最好的(也许不是最好的 - 刚刚好)吗?在同一台机器通信的两个进程的方式,使用.NET

其实在应用这两个过程我的工作,甚至没有两个不同的程序;他们只是两个相同的EXE的实例。我想做一些像一个单身的应用程序,但有它每用户(指有多个用户的终端服务器或Citrix或App-V的服务器应该能够启动的应用程序自身的单拷贝)。如果另一个实例是由同一个用户运行,它应该只是委派任务已经运行的实例,然后退出。每个节目的用户只有一个实例应该运行。到目前为止,我已经做了(感谢StackOverflow的),可检测应用程序的实例是否已经在运行,使用互斥的部分。但我需要第二应用程序实例,以便能够将数据发送到所述第一应用程序实例。

我倾向于使用命名管道和WCF的NetNamedPipeBinding这一点,但如果你有更好的想法,我会很感激它。感谢:)

有帮助吗?

解决方案

我会去命名管道。

基本上,你需要每个用户的唯一终点。至于你的互斥,你可能会使用的用户名,找出命名管道使用的名称。这甚至可能会取代你的互斥体的使用:试图找出是否命名管道为这个特殊的已经存在,如果确实如此,这意味着你的第二个实例来运行

这是很难TCP端口映射到一个用户。

哦,对使用命名管道,实际上,我说:“远程处理命名管道”。

其他提示

命名管道通常是最好的,但也考虑MSMQ的火灾和忘记的场景,确保了长时间的消息传递。这真的取决于你的邮件大小,以及。因为你需要每个用户唯一的端口TCP会变得非常棘手。

IPC是我在过去的这个用过。它是supprisingly容易。 .Net远程的一个很好的选择,但不幸的是它是一个受限制的选项becasue你不能例如使用它的CF。

下面是我用来执行进程间通信类的副本,可以在与一起选择一个互斥体,如果你想使用它,但它不是必需的。只要“pMappedMemoryName”和“pNamedEventName”在这两个过程是相同的,它应该只是罚款。我试图使它作为事件驱动越好。

只需使用戳方法写入数据,和Peek方法来读取它,虽然我设计它时,新的数据可用来自动触发一个事件。通过这种方式,你可以简单地订阅IpcEvent事件,而不必担心昂贵的投票。

  public class IpcService {
    private IServiceContext mContext;
    const int maxLength = 1024;
    private Thread listenerThread;
    private readonly string mMappedMemoryName;
    private readonly string mNamedEventName;
    public event EventHandler<TextualEventArgs> IpcEvent;
    private readonly bool mPersistantListener;

    public IpcService(bool pPersistantListener)
      : this(pPersistantListener, "IpcData", "IpcSystemEvent") {
      ;
    }

    public IpcService(bool pPersistantListener, string pMappedMemoryName, string pNamedEventName) {
      mPersistantListener = pPersistantListener;
      mMappedMemoryName = pMappedMemoryName;
      mNamedEventName = pNamedEventName;
    }

    public void Init(IServiceContext pContext) {
      mContext = pContext;
      listenerThread = new Thread(new ThreadStart(listenUsingNamedEventsAndMemoryMappedFiles));
      listenerThread.IsBackground = !mPersistantListener;
      listenerThread.Start();
    }


    private void listenUsingNamedEventsAndMemoryMappedFiles() {
      IntPtr hWnd = EventsManagement.CreateEvent(true, false, mNamedEventName);
      while (listenerThread != null) {
        if (Event.WAITOBJECT == EventsManagement.WaitForSingleObject(hWnd, 1000)) {
          string data = Peek();
          EventsManagement.ResetEvent(hWnd);
          EventHandler<TextualEventArgs> handler = IpcEvent;
          if (handler != null) handler(this, new TextualEventArgs(data));
        }
      }
      EventsManagement.SetEvent(hWnd);
      Thread.Sleep(500);
      HandleManagement.CloseHandle(hWnd);
    }

    public void Poke(string format, params object[] args) {
      Poke(string.Format(format, args));
    }

    public void Poke(string somedata) {
      using (MemoryMappedFileStream fs = new MemoryMappedFileStream(mMappedMemoryName, maxLength, MemoryProtection.PageReadWrite)) {
        fs.MapViewToProcessMemory(0, maxLength);
        fs.Write(Encoding.ASCII.GetBytes(somedata + "\0"), 0, somedata.Length + 1);
      }
      IntPtr hWnd = EventsManagement.CreateEvent(true, false, mNamedEventName);
      EventsManagement.SetEvent(hWnd);
      Thread.Sleep(500);
      HandleManagement.CloseHandle(hWnd);
    }

    public string Peek() {
      byte[] buffer;
      using (MemoryMappedFileStream fs = new MemoryMappedFileStream(mMappedMemoryName, maxLength, MemoryProtection.PageReadWrite)) {
        fs.MapViewToProcessMemory(0, maxLength);
        buffer = new byte[maxLength];
        fs.Read(buffer, 0, buffer.Length);
      }
      string readdata = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
      return readdata.Substring(0, readdata.IndexOf('\0'));
    }

    private bool mDisposed = false;

    public void Dispose() {
      if (!mDisposed) {
        mDisposed = true;
        if (listenerThread != null) {
          listenerThread.Abort();
          listenerThread = null;
        }
      }
    }

    ~IpcService() {
      Dispose();
    }

  }

我希望这有助于。

.NET远程处理也可能是方便的。它的快速和容易实现。

阅读更多的MSDN

您可以通过“本地\”的前缀名称设置一个互斥的,以“会话本地”的范围;阅读 MSDN 了解。这样,您就可以限制每个终端会话的流程实例(好吧,这不正是你问)。

的SendMessage / PostMessage的和GETMESSAGE是API的我喜欢这个

的SendMessage:结果 http://pinvoke.net/default.aspx/user32.SendMessage

PostMessage的:结果 http://pinvoke.net/default.aspx/user32.PostMessage

的GetMessage:结果 http://pinvoke.net/default.aspx/user32.GetMessage

另一种方法是使用好老DDE(动态数据交换): http://www.codeplex.com/ndde

DDE建立在窗口消息,但是一个抽象层在它上面。

(是的,我很喜欢我的朋友WIN32-API))

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top