8

次のコードは、アプリケーションのインスタンスを 1 つだけ実行できるようにする単純なシングルトンを実装しています。ただし、別のインスタンスが開始された場合は、そのインスタンスのコマンドライン引数を取得し、それを最初のインスタンスに渡してから、2 番目のインスタンスを終了できる必要があります。

アプリケーションの最初のインスタンスを取得しようとすると、問題が発生します。そのインスタンスのメイン フォームのハンドルを見つけたら、それをControl.FromHandle()メソッドに渡しMainFormます。代わりに、戻り値は常にnullです。(Control.FromChildHandle()同じ結果が得られます。)

したがって、私の質問は単純です: 私は何を間違っていますか? そして、これは.NETでも可能ですか?

public class MainForm : Form
{
[DllImport("user32")]
extern static int ShowWindowAsync(IntPtr hWnd, int nCmdShow);

[DllImport("user32")]
extern static bool SetForegroundWindow(IntPtr hWnd);

private Mutex singletonMutex;

private void MainForm_Load(object sender, EventArgs e)
{
  bool wasCreated;
  singletonMutex = new Mutex(false, Application.ProductName + "Mutex", out wasCreated);

  // returns false for every instance except the first
  if (!wasCreated)
  {
    Process thisProcess = Process.GetCurrentProcess();
    Process[] peerProcesses = Process.GetProcessesByName(thisProcess.ProcessName.Replace(".vshost", string.Empty));

    foreach (Process currentProcess in peerProcesses)
    {
      if (currentProcess.Handle != thisProcess.Handle)
      {
        ShowWindowAsync(currentProcess.MainWindowHandle, 1); // SW_NORMAL
        SetForegroundWindow(currentProcess.MainWindowHandle);

        // always returns null !!!
        MainForm runningForm = (MainForm) Control.FromHandle(currentProcess.MainWindowHandle);

        if (runningForm != null)
        {
          runningForm.Arguments = this.Arguments;
          runningForm.ProcessArguments();
        }

        break;
      }
    }

    Application.Exit();

    return;
  }
}
4

6 に答える 6

4

単一インスタンス アプリは、.NET フレームワークによって十分にサポートされています。必要なことを正確に行う例については、このスレッドを確認してください。

于 2009-02-24T16:15:11.490 に答える
3

Control.FromHandle は、探しているコントロールが別のプロセス (したがって別のアプリドメイン) にあるため、機能しません。

既に WindowHandle を持っていますが、その使用は Win32 API に限定されています。WinForms からは何も機能しません。

(WM_) メッセージを送信できますが、データを取得するのは困難です。

オプション

  1. 一時ファイルで低レベルのものを使用します。

  2. リモート処理 (WCF) を使用する

于 2009-02-24T14:00:41.593 に答える
3

以下を試してください

var form = (Form)(Control.FromHandle(myHandle));

編集

質問を読み直して、別のプロセスでハンドルを見ていることに気付きました。別のプロセスのハンドルを現在のプロセスの Form インスタンスに変換する方法はありません。私のソリューションは、同じプロセス内のハンドルに対してのみ機能します。

Form インスタンスを把握する唯一の方法は、Remoting を使用することです。しかし、それはあなたが探しているものではないように見える両方のプロセスの部分での協力を必要とします.

于 2009-02-24T13:53:13.797 に答える
2

シングルトン アプリケーションを実際に実装しようとしています。インターネットにはいくつかの例があります (申し訳ありませんが、実際に自分で試したことはありません)。

http://www.codeproject.com/KB/cs/SingletonApplication.aspx

http://www.nathanm.com/csharp-wpf-singleton-application/

于 2009-02-24T14:10:13.147 に答える
0

別のプロセスのコードを直接呼び出すことはできません。何らかの形式のプロセス間通信を使用する必要があります

同じコンピューター上の同じユーザーによって開始されたプロセス間でのみ通信する場合は、ウィンドウ メッセージを使用できます (WinAPI PostMessage を使用し、WndProc をオーバーライドします)。

于 2009-02-24T14:25:35.310 に答える