3

我有一个名为 app1 的 WPF 应用程序,它有一个名为 window1 的窗口。当用户单击 的关闭按钮时window1,应用程序不会关闭,但 window1 会隐藏 ( this.hide())。

我想检查应用程序的另一个实例在启动时是否已经在运行;如果是这样,我想显示已经运行的实例并终止新的实例。

我怎样才能做到这一点?

我知道如何检查进程以及如何关闭当前应用程序,但我不知道如何显示另一个正在运行的 WPF 进程的窗口...

在我的应用程序启动事件中,我这样做:

private void Application_Startup(object sender, StartupEventArgs e)
{
    if(Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
    {
        Application.Current.Shutdown(0);
    }
}  
4

2 回答 2

6

一个典型的方法是使用互斥锁。这允许您防止启动第二个实例(或者更确切地说,在应用程序的第二个实例中检测它)。

此时,您可以通知原始应用程序实例“显示”自己。这是一篇很好的文章,详细描述了整个过程(尽管使用 Windows 窗体)。

对于 WPF 应用程序,您需要将此逻辑放入应用程序的启动逻辑中,并添加一个 HwndSourceHook 来处理您想要显示的 WPF 窗口中的 windows 消息。

于 2012-07-09T16:50:11.470 回答
2

我找到了如何做这项工作!

我的问题通过“Reed Copsey”帮助和 Windows SendMessage API 解决了。为了做这件事,我在 window1.xaml.cs 文件中编写了这些代码:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Interop;


namespace app1
{
    public partial class window1: Window
    {
        public window1()
        {
            InitializeComponent();            
        }
        private void window1_Loaded(object sender, RoutedEventArgs e)
        {
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hwnd, msg, wParam, lParam);
            if (m.Msg == WM_COPYDATA)
            {
                // Get the COPYDATASTRUCT struct from lParam.
                COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

                // If the size matches
                if (cds.cbData == Marshal.SizeOf(typeof(MyStruct)))
                {
                    // Marshal the data from the unmanaged memory block to a 
                    // MyStruct managed struct.
                    MyStruct myStruct = (MyStruct)Marshal.PtrToStructure(cds.lpData,
                        typeof(MyStruct));

                    // Display the MyStruct data members.
                    if (myStruct.Message == "Show Up")
                    {
                        this.Show();
                    }
                }
            }
            return IntPtr.Zero;
        }

        internal const int WM_COPYDATA = 0x004A;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct MyStruct
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string Message;
        }
        [StructLayout(LayoutKind.Sequential)]
        internal struct COPYDATASTRUCT
        {
            public IntPtr dwData;       // Specifies data to be passed
            public int cbData;          // Specifies the data size in bytes
            public IntPtr lpData;       // Pointer to data to be passed
        }


    }
}


我在 App.xaml.cs 中编写了这些代码:


using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
using System.Runtime.InteropServices;
using System.Security;

namespace app1
{    
    public partial class App : Application
    {       
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct MyStruct
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string Message;
        }



        internal const int WM_COPYDATA = 0x004A;
        [StructLayout(LayoutKind.Sequential)]
        internal struct COPYDATASTRUCT
        {
            public IntPtr dwData;       // Specifies data to be passed
            public int cbData;          // Specifies the data size in bytes
            public IntPtr lpData;       // Pointer to data to be passed
        }
        [SuppressUnmanagedCodeSecurity]
        internal class NativeMethod
        {            
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
                IntPtr wParam, ref COPYDATASTRUCT lParam);


            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {            
            if (System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
            {
                IntPtr hTargetWnd = NativeMethod.FindWindow(null, "window1");
                if (hTargetWnd == IntPtr.Zero)
                {                    
                    return;
                }
                MyStruct myStruct;
                myStruct.Message = "Show Up";
                int myStructSize = Marshal.SizeOf(myStruct);
                IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize);
                try
                {
                    Marshal.StructureToPtr(myStruct, pMyStruct, true);

                    COPYDATASTRUCT cds = new COPYDATASTRUCT();
                    cds.cbData = myStructSize;
                    cds.lpData = pMyStruct;
                    NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, new IntPtr() , ref cds);

                    int result = Marshal.GetLastWin32Error();
                    if (result != 0)
                    {                       
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(pMyStruct);
                }
                Application.Current.Shutdown(0);
            }            
        }  

    }
}

就是这样。:D

于 2012-07-09T17:47:53.050 回答