2012-01-13 14 views
4

アプリケーションのインスタンスを1つ確保し、2つ目のインスタンスを開くときにフォーカスを設定するにはどうすればよいですか? アプリケーションのインスタンスを1つだけ強制実行するにはどうすればよいですか?

は、私が試した:これは、アプリケーションを集中されていない

public partial class Form1 : Form { 

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)] 
    public static extern 
    IntPtr FindWindow(String lpClassName, String lpWindowName); 

    [DllImport("USER32.DLL")] 
    public static extern 
    Boolean SetForegroundWindow(IntPtr hWnd); 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     bool isRunning = Process.GetProcesses() 
           .Where(p => p.MainWindowTitle.Contains(Text)) 
           .Count() > 1; 

     if (isRunning) 
     { 
      FocusWindow(Text); 
      Application.Exit(); 
     } 
    } 

    public static void FocusWindow(string title) 
    { 
     SetForegroundWindow(FindWindow(null, title)); 
    } 
} 

。これをどうすれば解決できますか?

+0

ていますか? – Tigran

+0

フォームを起動する前にProgram.csをチェックインするのは意味がありませんか? 'count> 0'でプロセス名のインスタンスを確認してください。 –

+1

[C#でのシングルインスタンスアプリケーション](http://blogs.msdn.com/b/tyler_whitney/archive/2005/11/28/497604.aspx) – LarsTech

答えて

6

代わりにMutexを使用すると、信頼性の低い方法でウィンドウを検索することを避けることができます(メインフォームの名前を変更するか、代わりに別のフォームを開くことを想像してください)。

bool createdNew; 
Mutex m = new Mutex(true, "SomeNameHere", out createdNew); 

if (!createdNew) 
{ 
    // Application already running. Call it and ask to show it's form. 
    IpcClientChannel clientChannel = new IpcClientChannel(); 
    ChannelServices.RegisterChannel(clientChannel, true); 

    RemotingConfiguration.RegisterWellKnownClientType(typeof(ExchangeBase), "ipc://SomeNameHere/YourAppBase"); 

    ExchangeBase Exchange = new ExchangeBase(); 
    Exchange.ShowForm(); 
} 
else 
{ 
    IpcServerChannel serverChannel = new IpcServerChannel("SomeNameHere"); 
    ChannelServices.RegisterChannel(serverChannel, true); 
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(ExchangeBase), "YourAppBase", WellKnownObjectMode.SingleCall); 

    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 

    MainForm = new FormMain(); 
    if (!MainForm.StopLoading) 
    { 
     Application.Run(MainForm); 

     // Keep the mutex reference alive until the termination of the program. 
     GC.KeepAlive(m); 
    } 
} 
2

TextをパラメータとしてFocusWindowメソッドに渡しているようですが、Containsのチェックを行っている間に表示されます。私はテキストが部分的なウィンドウのタイトルにすぎないので、FindWindowが失敗することになるでしょう。以下のようなウィンドウのフルテキストではなく、ハンドル渡して試してみてください:それはおそらく窓の同じタイトルによって引き起こされるので、FindWindowを実際のウィンドウハンドルを取得しています

var proc = Process.GetProcesses() 
        .Where(p => p.MainWindowTitle.Contains(Text)) 
        .FirstOrDefault(); 

     if (proc != null) 
     { 
      FocusWindow(p.MainWindowTitle); 
      Application.Exit(); 
     } 
1

フォームの読み込み時にこのチェックを行うのが間違っています。アプリケーションのインスタンスが1つだけ実行されていることを確認するには、Mutexを使用する必要があります。それを行う方法と既存のインスタンスにフォーカスを設定する方法の例については、this articleを参照してください。

0

置きますApp.xaml.csファイルでこのコード:あなたはFindWindowを、有効なHWNDを返すことを確認してください

using System.Runtime.InteropServices; 

#region SetWindowPos Definitions 
[DllImport("user32.dll")] 
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, 
    int X, int Y, int cx, int cy, uint uFlags); 

static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); 
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); 
static readonly IntPtr HWND_TOP = new IntPtr(0); 
static readonly IntPtr HWND_BOTTOM = new IntPtr(1); 

const UInt32 SWP_NOSIZE = 0x0001; 
const UInt32 SWP_NOMOVE = 0x0002; 
const UInt32 SWP_NOZORDER = 0x0004; 
const UInt32 SWP_NOREDRAW = 0x0008; 
const UInt32 SWP_NOACTIVATE = 0x0010; 
const UInt32 SWP_FRAMECHANGED = 0x0020; 
const UInt32 SWP_SHOWWINDOW = 0x0040; 
const UInt32 SWP_HIDEWINDOW = 0x0080; 
const UInt32 SWP_NOCOPYBITS = 0x0100; 
const UInt32 SWP_NOOWNERZORDER = 0x0200; 
const UInt32 SWP_NOSENDCHANGING = 0x0400; 
#endregion 
#region OnStartup 
protected override void OnStartup(StartupEventArgs e) 
{ 
    // Only allow one instance of the application 
    Process thisProc = Process.GetCurrentProcess(); 
    Process[] processes = Process.GetProcessesByName(thisProc.ProcessName); 
    if (processes.Length > 1) 
    { 
     Application.Current.Shutdown(); 

     SetWindowPos(processes[1].MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, 
      SWP_NOSIZE | SWP_NOMOVE); 
     SetWindowPos(processes[1].MainWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, 
      SWP_NOSIZE | SWP_NOMOVE); 
    } 
    else 
    { 
     base.OnStartup(e); 
    } 
} 
#endregion 
関連する問題