在C#中显示另一个应用程序的WPF窗口

时间:2012-07-09 16:45:18

标签: c# wpf winapi process window

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

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

我该怎么做?

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

在我的App启动活动中,我这样做:

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

2 个答案:

答案 0 :(得分:6)

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

此时,您可以通知原始应用程序实例“显示”自身。这是a good article describing the entire process in detail(虽然使用Windows窗体)。

对于WPF应用程序,您需要将此逻辑放在应用程序的启动逻辑中,并在您希望显示的WPF窗口中放置add an HwndSourceHook to process the windows message

答案 1 :(得分: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