最近写C#窗体程序,希望运行程序时,第二次点击该程序(使其运行)只激活第一次运行的窗体,而不是重新创建新的窗体实例。一下子想到了在Program.Cs类中使用单实例的设计模式,然后得到警告“在设置窗体可视之前不允许创建窗体实例”,放弃掉这种想法,进行另一种尝试(使用Mutex或者Semaphore)来进行控制。 尝试一:参考资料为VB的代码,基本上是直接转译下语言 创建一个信号灯就可以了 using System.Runtime.InteropServices;
Private Declare Function ReleaseSemaphore Lib "kernel32" (ByVal hSemaphore As Long, ByVal lReleaseCount As Long, lpPreviousCount As Long) As Long
Private Declare Function CreateSemaphore Lib "kernel32" Alias "CreateSemaphoreA" (lpSemaphoreAttributes As SECURITY_ATTRIBUTES, ByVal lInitialCount As Long, ByVal lMaximumCount As Long, ByVal lpName As String) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Type SECURITY_ATTRIBUTES nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Dim Semaphore As String, Sema As Long, Security As SECURITY_ATTRIBUTES
Dim PrevSemaphore As Long, Turn As Long
Security.bInheritHandle = True '默认的安全值
Security.lpSecurityDescriptor = 0
Security.nLength = Len(Security)
Sema = CreateSemaphore(Security, 1, 1, Semaphore) '申请一个权限,并立即返回
Turn = WaitForSingleObject(Sema, 0) '如果不是正常返回,则表示没有申请到资源的使用权限
If Turn <> 0 Then MsgBox "管理系统已经运行!", vbOKOnly + vbCritical, "提示"
End
End If
End Sub
public class SECURITY_ATTRIBUTES
{
public int nLength, lpSecurityDescriptor, bInheritHandle;
//public string lpSecurityDescriptor;
//public bool bInheritHandle;
}
{
[DllImport("kernel32.dll")] //CharSet=CharSet.Auto|Ansi
private static extern bool ReleaseSemaphore(int hSemaphore, int lReleaseCount, int lpPreviousCount);
private static extern IntPtr CreateSemaphore(SECURITY_ATTRIBUTES lpSemaphoreAttributes, int lInitialCount,int lMaximumCount,string lpName);
private static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
private static extern IntPtr OpenSemaphore(int dwDesiredAccess,bool bInheritHandle,string lpName);
private int PrevSemaphore, Turn;
private SECURITY_ATTRIBUTES Security;
private IntPtr Sema;
{
InitializeComponent();
Security = new SECURITY_ATTRIBUTES();
}
{
Security.bInheritHandle = 1; //等价于Security.bInheritHandle =True;
Security.lpSecurityDescriptor = 0 ;
Security.nLength = 12; //值为3*32/8
Sema = CreateSemaphore(Security, 1, 1, Semaphore); //申请一个权限,并立即返回
Turn = WaitForSingleObject(Sema, 0); //如果不是正常返回,则表示没有申请到资源的使用权限
if(Turn!=0)
{
MessageBox.Show("管理系统已经运行!","提示",MessageBoxButtons.OK);
//OpenSemaphore(SEMAPHORE_ALL_ACCESS
this.Close();
}
}
}
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
namespace WinFormStudy
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Process instance = RunningInstance();
if (instance == null)
{
//没有实例在运行
Application.Run(new Form1());
}
else
{
//已经有一个实例在运行
HandleRunningInstance(instance);
}
}
#region 确保程序只运行一个实例
private static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
//遍历与当前进程名称相同的进程列表
foreach (Process process in processes)
{
//如果实例已经存在则忽略当前进程
if (process.Id != current.Id)
{
//保证要打开的进程同已经存在的进程来自同一文件路径
if (Assembly.GetExecutingAssembly().Location.Replace("/", "//") == current.MainModule.FileName)
{
//返回已经存在的进程
return process;
}
}
}
return null;
}
private static void HandleRunningInstance(Process instance)
{
MessageBox.Show("已经在运行!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
ShowWindowAsync(instance.MainWindowHandle, 1); //调用api函数,正常显示窗口
SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(System.IntPtr hWnd);
#endregion
}
}
联系客服