解决C# WINFORM程序只允许运行一个实例的几种方法详解

摘要:
已命名的互斥体是系统范围的。=current.Id)//忽略当前进程{//确认相同进程的程序运行位置是否一样.if{//Returntheotherprocessinstance.returnprocess;}}}//Nootherinstancewasfound,returnnull.returnnull;}2,把Main()函数改为如下代码:staticvoidMain(){if{Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault;Application.Run;}else{MessageBox.Show("已经运行了一个实例了。C#实现如下:1.申明WinAPI函数接口[System.Runtime.InteropServices.DllImport]publicstaticexternUInt32GlobalAddAtom;//添加原子[System.Runtime.InteropServices.DllImport]publicstaticexternUInt32GlobalFindAtom;//查找原子[System.Runtime.InteropServices.DllImport]publicstaticexternUInt32GlobalDeleteAtom;//删除原子2.修改Main()函数如下:staticvoidMain(){if//没找到原子"jiaao_test"{GlobalAddAtom;//添加原子"jiaao_test"Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault;Application.Run;}else{MessageBox.Show("已经运行了一个实例了。

要实现程序的互斥,通常有下面几种方式,下面用 C# 语言来实现:

方法一:
使用线程互斥变量. 通过定义互斥变量来判断是否已运行实例.
把program.cs文件里的Main()函数改为如下代码:

using System;

using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace NetTools

{

static class Program

{

[DllImport("user32.dll")]

private static extern bool FlashWindow(IntPtr hWnd, bool bInvert);

[DllImport("user32.dll")]

private static extern bool FlashWindowEx(int pfwi);

/// <summary>

/// 应用程序的主入口点。

/// </summary>

[STAThread]

static void Main()

{

bool runone;

System.Threading.Mutex run = new System.Threading.Mutex(true, "single_test", out runone);

if (runone)

{

run.ReleaseMutex();

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

FrmRemote frm = new FrmRemote();

int hdc = frm.Handle.ToInt32(); // write to ...

Application.Run(frm);

IntPtr a = new IntPtr(hdc);

}

else

{

MessageBox.Show("已经运行了一个实例了。");

//IntPtr hdc = new IntPtr(1312810); // read from...

//bool flash = FlashWindow(hdc, true);

}

}

}

}

说明:程序中通过语句 System.Threading.Mutex run = new System.Threading.Mutex(true, "single_test", out runone);来创建一个互斥体变量run,其中"single_test"为互斥体名,在此方法返回时,如果创建了局部互斥体或指定的命名系统互斥体,则布尔值runone为true;如果指定的命名系统互斥体已存在,则为 false。已命名的互斥体是系统范围的。

方法二:采用判断进程的方式,我们在运行程序前,查找进程中是否有同名的进程,同时运行位置也相同程,如是没有运行该程序,如果有就就不运行.在C#中应用System.Diagnostics名字空间中的Process类来实现,主要代码如下:
1,在program.cs文件中添加函数如下:

public static System.Diagnostics.Process RunningInstance()

{

System.Diagnostics.Process current = System.Diagnostics.Process.GetCurrentProcess();

System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();

foreach (System.Diagnostics.Process process in processes) //查找相同名称的进程

{

if (process.Id != current.Id) //忽略当前进程

{ //确认相同进程的程序运行位置是否一样.

if (System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", @"/") == current.MainModule.FileName)

{ //Return the other process instance.

return process;

}

}

} //No other instance was found, return null.

return null;

}

2,把Main ()函数改为如下代码:

static void Main()

{

if (RunningInstance() == null)

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new Form1());

}

else

{

MessageBox.Show("已经运行了一个实例了。");

}

}

方法三:全局原子法,创建程序前,先检查全局原子表中看是否存在特定原子A(创建时添加的),存在时停止创建,说明该程序已运行了一个实例;不存在则运行程序并想全局原子表中添加特定原子A;退出程序时要记得释放特定的原子A哦,不然要到关机才会释放。C#实现如下:
1.申明WinAPI函数接口

[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); //删除原子

2.修改Main()函数如下:

static void Main()

{

if (GlobalFindAtom("jiaao_test") == 77856768) //没找到原子"jiaao_test"

{

GlobalAddAtom("jiaao_test"); //添加原子"jiaao_test"

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new Form1());

}

else

{

MessageBox.Show("已经运行了一个实例了。");

}

}

3.FormClosed事件中添加如下代码:
GlobalDeleteAtom(GlobalFindAtom("jiaao_test"));//删除原子"jiaao_test"

方法四:通过进程判断是否启动:

static class Program

{

/// <summary>

/// 应用程序的主入口点。

/// </summary>

[STAThread]

static void Main()

{

//获取当前进程的ID

int pId = Process.GetCurrentProcess().Id;

bool isRun = false;

foreach (Process p in Process.GetProcessesByName("CallMaster"))

{

//取得当前程序的进程,进行比较

if (Common.GetPath().ToLower() == p.MainModule.FileName.ToLower())

{

if (pId != p.Id)

{

isRun = true;

break;

}

}

}

if (isRun==true)

{

Application.Exit();

return;

}

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new frmMain());

}

}

利用放射获取当前应用程序的全路径:

public static string GetPath()

{

return System.Reflection.Assembly.GetExecutingAssembly().Location;

}

方法五:通过线程互斥判断是否启动:

static class Program

{

private static System.Threading.Mutex mutex;

/// <summary>

/// 应用程序的主入口点。

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

mutex = new System.Threading.Mutex(true, "OnlyRun");

if (mutex.WaitOne(0, false))

{

Application.Run(new MainForm());

}

else

{

MessageBox.Show("程序已经在运行!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

Application.Exit();

}

}

}

另附:c#中怎样判断一个程序是否正在运行?

if (System.Diagnostics.Process.GetProcessesByName("程序进程中的名称").ToList().Count > 0)

{

//存在

}

else

{

//不存在

}

免责声明:文章转载自《解决C# WINFORM程序只允许运行一个实例的几种方法详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于JVisualVM的可视化监控mapping 详解1(mapping type)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#--Winform--图标控件Chart详解

以下是学习笔记: 学习内容:https://www.bilibili.com/video/BV1rp4y1s76g?p=2   一,图表的基本介绍: 1,下图说明了构成图表的关键要素  2,图表元素描述: 3,图标的坐标系 【1】计算机屏幕坐标系  【2】Chart控件的坐标系  【3】图标图片和图表区域  4,图表的文本元素   二,图表的应...

【DevExpress】4、在WinForm里用反射模拟Web里面的超链接功能

这几个月一直在用DevExpress做公司的一个工具,布局模仿DevExpress控件包里面的一个示例(如上图),用Dev的朋友们应该对这个很熟悉吧#^_^#,从里面学到了许多东西,控件的基本使用,以及一些好的设计理念,哈哈,也不知道算不算理念,反正对我自己挺有帮助的,这里就总结了下,对自己是个巩固,如果有不恰当的地方,请大家不要吝惜手中的砖头。 布局...

解决winform中mdi子窗体加载时显示最大化最小化按钮的方法

场景:在mid加载子窗体的时候如果指定WindowState为Maximized,加载完成后主窗体会显示最大化、最小化、关闭的按钮图标。 解决方法: 1.更改主窗体FormMain的属性。制定MainMenuStrip的属性为menuStrip1控件。menuStrip1控件就是主窗体上的菜单栏。 2.在menuStrip1控件的ItemAdded事件中添...

Winform传统DataGridView和DevExpress控件的GridControl两者表头全选功能的实现

在开发一个个人项目的时候,有客户反映默认GridView多选操作不是很方便和理想,想在列表的左边增加一列可以勾选,并且最好支持列表头部全选的操作,否则数据多的时候一个个勾选要到天荒地老。 基于以上需求,找了不少例子进行比较,并对代码进行测试改进,终于完成了以上的功能了, 并且由于我本身做了多套界面的处理,因此,基于传统的DataGridView全选操作不能...

WinForm界面布局空间WeifenLuo.WinformUI.Docking

最近在学习Sharpdevelop的过程中,看到了使用的很好的winform页面布局控件,感觉非常的不错。实现效果如下所示:  这里我就简单的下一下他的实现步骤,当中我也看考了其他人的博客。  1) 创建一个windows Form的应用程序 2) 添加引用:WeifenLuo.WinFormsUI.Docking他是一个DLL文件,可以自行从网络上下载...

C# winform 登陆成功打开主form,同时关闭登陆form

设置 Application.Run(new Form1());其中form1为主窗口,然后在form1的load方法里面这样写: 代码 private void Form1_Load(object sender, EventArgs e)         {             Form f2 = new Form2();            ...