Article directory
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
System.Threading.Mutex mutex;
public App()
{
this.Startup += new StartupEventHandler(App_Startup);
}
void App_Startup(object sender, StartupEventArgs e)
{
bool ret;
mutex = new System.Threading.Mutex(true, "ElectronicNeedleTherapySystem", out ret);
if (!ret)
{
MessageBox.Show("已有一个程序实例运行");
Environment.Exit(0);
}
}
}
or
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
private static System.Threading.Mutex mutex;
protected override void OnStartup(StartupEventArgs e)
{
mutex = new System.Threading.Mutex(true, "OnlyRun_CRNS");
if (mutex.WaitOne(0, false))
{
base.OnStartup(e);
}
else
{
MessageBox.Show("程序已经在运行!", "提示");
this.Shutdown();
}
}
}
or
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (EnsureInstance())
{
return;
}
if (new LoginView().ShowDialog()==true)
{
new MainView().ShowDialog();
}
Application.Current.Shutdown();
}
/// 该函数设置由不同线程产生的窗口的显示状态
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分</param>
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
/// <summary>
/// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
/// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
/// </summary>
/// <param name="hWnd">将被激活并被调入前台的窗口句柄</param>
/// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private const int SW_SHOWNOMAL = 1;
private static void HandleRunningInstance(Process instance)
{
ShowWindowAsync(instance.MainWindowHandle, SW_SHOWNOMAL);//显示
SetForegroundWindow(instance.MainWindowHandle);//当到最前端
}
private static Process[] RuningInstance()
{
Process currentProcess = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);
return processes.Where(x => x.Id != currentProcess.Id).ToArray();
}
private static bool EnsureInstance()
{
var intance = RuningInstance();
var select = false;
if (intance != null && intance.Count() > 0)
{
var result = MessageBox.Show(string.Format(CultureInfo.CurrentCulture,
$"软件已经在后台运行{
intance.Count()}个实例!\r\n" +
$"路径:\r\n{
GetProcessPath(intance)}\r\n\n" +
"请选择:\n" +
"1.关闭后台程序重新运行\t[是]\n" +
"2.显示后台程序\t\t[否]\n" +
"3.保留后台程序并启动新程序\t[取消]\n"),
"LoginManagement", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
switch (result)
{
case MessageBoxResult.Yes:
KillProcess(intance);
break;
case MessageBoxResult.No:
case MessageBoxResult.None:
Array.ForEach(intance, x => HandleRunningInstance(x));
select = true;
break;
case MessageBoxResult.Cancel:
break;
default:
break;
}
}
return select;
}
private static string GetProcessPath(Process[] processes)
{
var sb = new StringBuilder();
for (int i = 0; i < processes.Count(); i++)
{
sb.Append($"{
i + 1}:{
processes[i].MainModule.FileName}\n");
}
return sb.ToString();
}
private static void KillProcess(Process[] processes)
{
foreach (var p in processes)
{
p.Kill();
if (!p.HasExited)
{
MessageBox.Show(string.Format(CultureInfo.CurrentCulture, "进程关闭失败!请手动确认进程已关闭"),
"LoginManagement", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}