这里微酷分享一下.Net技术(C#)开发WinForm应用程序只运行一个实例的方法。@VCOO

方法一:使用线程互斥变量,通过定义互斥变量来判断是否已运行实例。
[csharp]
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
bool RunOne;
System.Threading.Mutex run = new System.Threading.Mutex(true, "9a4822d4-ba21-44bc-b84a-ae1d67eedf0a", out RunOne);
if (RunOne)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
Application.EnableVisualStyles();
MessageBox.Show("只能运行一个实例。", "系统提示:");
}
}[/csharp]

方法二:在Main()方法开始时遍历所有进程,获取每个进程的程序集GUID和PID,若发现有跟自己GUID相同且PID不同的进程,就勒令自身退出。
[csharp]
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Guid ownGUID = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(GuidAttribute))).Value);
Guid proGUID;
int ownPID = Process.GetCurrentProcess().Id;
int proPID;

foreach (Process p in Process.GetProcesses())
{
try
{
proGUID = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.LoadFile(p.MainModule.FileName), typeof(GuidAttribute))).Value);
proPID = p.Id;
if (proGUID.Equals(ownGUID) && proPID != ownPID)
{
MessageBox.Show("程序已运行");
Environment.Exit(Environment.ExitCode);
}
}
catch
{
continue; //遇上进程访问异常就跳过该进程
}
}

//若未被Exit,正常启动
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}[/csharp]

方法三:全局原子法,创建程序前,先检查全局原子表中看是否存在特定原子A(创建时添加的), 存在时停止创建,说明该程序已运行了一个实例;不存在则运行程序并想全局原子表中添加特定原子A; 退出程序时要记得释放特定的原子A哦,不然要到关机才会释放。
[csharp]
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
public static extern UInt32 GlobalAddAtom(String lpString); //添加原子

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
public static extern UInt32 GlobalFindAtom(String lpString); //查找原子

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
public static extern UInt32 GlobalDeleteAtom(UInt32 nAtom); //删除原子

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
if (GlobalFindAtom("xinggang") == 20121212) //没找到原子"xinggang"
{
GlobalAddAtom("xinggang"); //添加原子"xinggang"
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("已经运行了一个实例了。");
}
}

//注意要在FormClosed事件中添加如下代码:

GlobalDeleteAtom(GlobalFindAtom("xinggang")); //删除原子"xinggang"
[/csharp]

方法四:按进程名查找,如果已经运行则激活。

[csharp]
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;//使用DllImport的必须。
using System.Diagnostics;//引入Process 类

namespace WindowsFormApp1
{
static class Program
{
private const int WS_SHOWNORMAL = 1;
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Process instance = GetRunningInstance();
if (instance == null)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frm_Main());//在这启动主窗体。
}
else
{
HandleRunningInstance(instance);
}
}

/// <summary>
/// 获取当前是否具有相同进程。
/// </summary>
/// <returns></returns>
public static Process GetRunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
//遍历正在有相同名字运行的例程
foreach (Process process in processes)
{
//忽略现有的例程
if (process.Id != current.Id)
//确保例程从EXE文件运行
if ( System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/" , "\\") == current.MainModule.FileName )
return process;
}
return null;
}

/// <summary>
/// 激活原有的进程。
/// </summary>
/// <param name="instance"></param>
public static void HandleRunningInstance(Process instance)
{
ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
SetForegroundWindow(instance.MainWindowHandle);
}
}
}
[/csharp]

发表评论

/ 快捷键:Ctrl+Enter
加载中……