Как я могу применить один экземпляр моего приложения? - PullRequest
4 голосов
/ 13 января 2012

Как я могу обеспечить один экземпляр моего приложения и установить на него фокус при попытке открыть второй экземпляр?

Я пробовал:

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));
    }
}

Это не фокусировка приложения.Как я могу это исправить?

Ответы [ 5 ]

6 голосов
/ 14 января 2012

Вместо этого вы можете использовать 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 голосов
/ 14 января 2012

Похоже, вы передаете Text в качестве параметра для вашего FocusWindow метода, но при выполнении проверки Contains. Готов поспорить, что текст - это только частичный заголовок окна, поэтому FindWindow не работает. Попробуйте передать полный текст дескриптора окна, например:

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

        if (proc != null)
        {
            FocusWindow(p.MainWindowTitle);
            Application.Exit();
        }
1 голос
/ 14 января 2012

Неправильно выполнять эту проверку загрузки формы. Вы должны использовать Mutex, чтобы убедиться, что запущен только один экземпляр приложения. См. эту статью для примера того, как это сделать, а также для установки фокуса на существующий экземпляр.

1 голос
/ 14 января 2012

Возможно, это вызвано тем же названием окон, поэтому FindWindow получает фактический дескриптор окна, попробуйте использовать функцию EnumWindows вместо FindWindow.

0 голосов
/ 14 января 2012

Поместите этот код в файл App.xaml.cs:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...