我有一个名为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);
}
}
答案 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