2

作为标题状态,我想制作一个单实例程序并在启动另一个实例时显示 MainWindow。我已经实现了显示只允许一个实例的消息。

public class MyApplication
{
static Mutex mutex = new Mutex(true, "FirstInstance");
    [STAThread]
    public static void Main(string[] args)
    {
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            App app = new App();
            app.InitializeComponent();
            app.Run();
        }
        else
        {
            MessageBox.Show("only one instance at a time");
        }
    }
}

这工作正常,但我想显示 MainWindow 而不是消息,所以我尝试了

static Application app;//change app to static
if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            app = new App();
            app.InitializeComponent();
            app.Run();
        }  
else
{
    app.MainWindow.WindowState = WindowState.Normal;
}

我得到“System.NullReferenceException:对象引用未设置为对象的实例”。似乎应用程序中的 MainWindow(它是静态的)为空,我不明白为什么。

所以我尝试了这篇文章http://sanity-free.org/143/csharp_dotnet_single_instance_application.html 但是 WndProc 方法在 WPF 中不存在。

如果您能帮助我,我将不胜感激。谢谢!

4

2 回答 2

3

I created a sample WPF app and only changed the App.xaml.cs file. If the single-instance window is already open, this code will find any process that matches the name of the current process, and if that process has a window, shows it:

public partial class App : Application
{
    // signals to restore the window to its normal state
    private const int SW_SHOWNORMAL = 1;

    // create the mutex
    private const string MUTEXNAME = "FirstInstance";
    private readonly Mutex _mutex = new Mutex(true, MUTEXNAME);

    public App()
    {
        if (!_mutex.WaitOne(TimeSpan.Zero))
        {
            ShowExistingWindow();
            Shutdown();
        }
    }

    [DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    // shows the window of the single-instance that is already open
    private void ShowExistingWindow()
    {
        var currentProcess = Process.GetCurrentProcess();
        var processes = Process.GetProcessesByName(currentProcess.ProcessName);
        foreach (var process in processes)
        {
            // the single-instance already open should have a MainWindowHandle
            if (process.MainWindowHandle != IntPtr.Zero)
            {
                // restores the window in case it was minimized
                ShowWindow(process.MainWindowHandle, SW_SHOWNORMAL);

                // brings the window to the foreground
                SetForegroundWindow(process.MainWindowHandle);

                return;
            }
        }
    }
}

FYI, this does not work in debug mode because .vshost becomes part of the process name. If you need it to work in debug mode, you need to iterate through all processes instead of calling Process.GetProcessesByName.

于 2013-07-22T15:56:39.570 回答
0

如果我没有误解你的问题,试试这样

[STAThread]
    public static void Main(string[] args)
    {
        Task task = new Task(() => { Thread.Sleep(200); MessageBox.Show("what a marvelous engineering"); });
        task.Start();
        //If you want application not to run untill task is complete then just use wait
        task.Wait();

            App app = new App();
            app.InitializeComponent();
            app.Run();
    }

但是我想知道您是否希望在 MainWindow 实例化之前完成您的 C# 工作,为什么不只是在 App app=new App() 之前执行其他工作并让代码按顺序运行。

于 2013-07-21T14:23:07.500 回答