2009-07-31 5 views
1

私はWinFormsアプリケーションを持っています。すでに&を実行しているインスタンスがある場合、別のインスタンスを起動しようとすると、Application.Run()を呼び出す前にMutexをチェックして停止します。その部分はうまく動作します。私がしたいのは、新しいプロセスを強制終了する前に、アプリケーションの新しいインスタンス(文字列形式のデータとともに)を既存のインスタンスに渡すことです。管理対象アプリのあるインスタンスから別のインスタンスにメッセージを送信するにはどうすればよいですか?

私はPostMessageを呼び出そうとしましたが、実行中のアプリケーションでメッセージを受け取りましたが、lparamで渡した文字列は失敗しています(はい、私は良い文字列を渡していることを確認しました〜から始まる)。どうすればこれを最もうまくできますか?私のフォーム内の別の場所

static class Program 
{ 
    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    public static extern bool PostMessage(int hhwnd, uint msg, IntPtr wparam, IntPtr lParam); 

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern uint RegisterWindowMessage(string lpString); 

    private const int HWND_BROADCAST = 0xffff; 
    static uint _wmJLPC = unchecked((uint)-1); 

    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     _wmJLPC = RegisterWindowMessage("JumpListProjectClicked"); 
     if (_wmJLPC == 0) 
     { 
      throw new Exception(string.Format("Error registering window message: \"{0}\"", Marshal.GetLastWin32Error().ToString())); 
     } 

     bool onlyInstance = false; 
     Mutex mutex = new Mutex(true, "b73fd756-ac15-49c4-8a9a-45e1c2488599_ProjectTracker", out onlyInstance); 

     if (!onlyInstance) { 
      ProcessArguments(); 
      return; 
     } 

     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new MainForm()); 

     GC.KeepAlive(mutex); 
    } 

    internal static void ProcessArguments() 
    { 
     if (Environment.GetCommandLineArgs().Length > 1) 
     { 
      IntPtr param = Marshal.StringToHGlobalAuto(Environment.GetCommandLineArgs()[1]); 
      PostMessage(HWND_BROADCAST, _wmJLPC, IntPtr.Zero, param); 
     } 
    } 
} 

、...

protected override void WndProc(ref Message m) 
{ 
    try 
    { 
     if (m.Msg == _wmJLPC) 
     { 
      // always returns an empty string 
      string param = Marshal.PtrToStringAnsi(m.LParam); 

      // UI code omitted 
     } 
    } 
    catch (Exception ex) 
    { 
     HandleException(ex); 
    } 

    base.WndProc(ref m); 
} 

答えて

3

グレッグ、

StringToHGlobalAutoによって作成された管理対象外のポインタがそれを作成したプロセス空間でのみ有効ですを取得します。それが参照するメモリは、他のプロセスからアクセスすることはできません。

あるアプリケーションから別のアプリケーションにデータを渡すには、WM_COPYDATAメッセージとともにSendMessage()を使用します。

スコット

0

は再びあなたのコードを確認してください。 StringToHGlobalAutoを使用して文字列を作成しています(Unicodeで終わる可能性が高い)。次に、Unicodeを使用していないPtrToStringAnsiを呼び出しています。

このソリューションが機能しない場合は、いくつかのオプションがあります。

使い慣れた方法の1つは、すばやく簡単なので、必要な内容のよく知られたファイルを作成することです。IPC(InterProcess Communication)名前付きイベントでそのファイルの使用をロックし、別の名前付きイベントを設定してファイルが変更されたことを「所有者」アプリに伝えます。 「所有者」はイベントを時々チェックしたり、ワーカースレッドを起動して監視します。

また、IPCには多くの味があります。これらのアイデアがうまく機能しない場合は、見てください。

0

最近では、クロスプロセス通信を行うための方がはるかに単純で現代的な方法があります。特に、WCFをチェックしてください。

私は学習曲線の十分なビットがあることを認めますが。一度それを理解すれば、それは本当にとても簡単です。プログラムですべてを行うこともできるので、構成の混乱を心配する必要はありません。

0

ここには簡単な方法があります。私は、コードを実行していないが、あなたはアイデア

class Program 
{ 
    static Thread listenThread; 
    static void Main(string[] args) 
    { 
     try 
     { 
      using (Mutex mutex = new Mutex(true, "my mutex")) 
      { 
       listenThread = new Thread(Listen); 
       listenThread.IsBackground = true; 
       listenThread.Start(); 
      } 
     } 
     catch (ApplicationException) 
     { 
      using (Mutex mutex = Mutex.OpenExisting("my mutex")) 
      { 
       mutex.WaitOne(); 
       try 
       { 
        using (NamedPipeClientStream client = new NamedPipeClientStream("some pipe")) 
        { 
         using (StreamWriter writer = new StreamWriter(client)) 
         { 
          writer.WriteLine("SomeMessage"); 
         } 
        } 
       } 
       finally 
       { 
        mutex.ReleaseMutex(); 
       } 
      } 
     } 
    } 
    static void Listen() 
    { 
     using (NamedPipeServerStream server = new NamedPipeServerStream("some pipe")) 
     { 
      using (StreamReader reader = new StreamReader(server)) 
      { 
       for (; ;) 
       { 
        server.WaitForConnection(); 
        string message = reader.ReadLine(); 
        //Dispatch the message, probably onto the thread your form 
        // was contructed on with Form.BeginInvoke 

       } 
      } 
     } 
    } 
関連する問題