Winform防止程序重复运行
需求:1、点击“关闭”按钮时,程序最小化到托盘,并没有退出,这时再次运行程序,不会重复运行,而是显示已运行的程序;2、支持不同目录;3、支持修改名称。
代码(不支持修改名称,不支持不同目录):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tool;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices; namespace 计算器
{
static class Program
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 该函数设置由不同线程产生的窗口的显示状态。
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分。</param>
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零。</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindow(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_SHOWNORMAL = ; /// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Process processes = RunningInstance();
if (processes == null)
{
Application.Run(new Form1());
}
else
{
HandleRunningInstance(processes);
}
} /// <summary>
/// 获取正在运行的实例,没有运行的实例返回null;
/// </summary>
public 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;
} /// <summary>
/// 显示已运行的程序。
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr formHwnd = FindWindow(null, "计算器");
ShowWindow(formHwnd, SW_SHOWNORMAL); //显示
SetForegroundWindow(formHwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
代码(支持修改名称,支持不同目录):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tool;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices; namespace 计算器
{
static class Program
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 该函数设置由不同线程产生的窗口的显示状态。
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分。</param>
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零。</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindow(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_SHOWNORMAL = ; /// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Common.AutoRegister(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); bool createNew;
using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew))
{
if (createNew)
{
FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //进程ID写入文件
Application.Run(new Form1());
}
else
{
try
{
string strProcessId = FileOperator.GetValue("ProcessId"); //从文件中获取进程ID
int processId = Convert.ToInt32(strProcessId);
Process process = Process.GetProcessById(processId);
HandleRunningInstance(process);
}
catch
{
FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //进程ID写入文件
Application.Run(new Form1());
}
}
}
} /// <summary>
/// 显示已运行的程序。
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr formHwnd = FindWindow(null, "计算器");
ShowWindow(formHwnd, SW_SHOWNORMAL); //显示
SetForegroundWindow(formHwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
其实,IntPtr formHwnd = FindWindow(null, "计算器"); 这段代码是有BUG的,比如你打开一个名为“计算器”的文件夹,那么FindWindow找到的其实是这个文件夹,而不是计算器程序。我们可以在主窗体第一次显示的时候,记下窗口句柄,代码如下:
private void Form1_Shown(object sender, EventArgs e)
{
FileOperator.SetValue("hwnd", Process.GetCurrentProcess().MainWindowHandle.ToString());
}
然后,显示已运行的程序时,从文件中读取之前记录的窗口句柄,代码如下:
/// <summary>
/// 显示已运行的程序
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr hwnd = new IntPtr(Convert.ToInt32(FileOperator.GetValue("hwnd")));
ShowWindow(hwnd, SW_SHOWNORMAL); //显示
SetForegroundWindow(hwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
综上,再整理一下,就能得到完美的解决方案。
Winform防止程序重复运行的更多相关文章
- C# Winform防止一个程序重复运行
1: //在写一些服务型的软件的时候,你可能不希望一个操作系统里有两个副本在运行,这样也许会扰乱你的操作.这时,你就需要限制程序的副本.下面的这个方法,很简单的就可以实现上述功能. using Sys ...
- C# WINFORM判断程序是否运行,且只能运行一个实例(转)
判断程序是否已经运行,使程序只能运行一个实例有很多方法,下面记录两种, 方法1:线程互斥 static class Program { private static System.Threading. ...
- winform判断程序是否运行,且只能运行一个实例
前言 判断程序是否已经运行,使程序只能运行一个实例有很多方法,下面记录两种. 目前使用的是第一种方法. 方法1:线程互斥 static class Program { private static S ...
- C# .NET Winform等程序一运行就闪退 不同环境 换到其他电脑,例如XP之类的解决方法。
我现在写标题就跟写tag一样,方便大家索引. 有时候经常会把.NET写的程序拿到其他客户机,发现直接闪退,啥也不报错..那就很蛋疼,又不可能去装IDE来检测是吧,网上还有很多说啥看系统日志的,什么图标 ...
- [转]使用互斥对象让程序只运行一次(delphi)
使用互斥对象让程序只运行一次“怎么让我的程序在运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题.本文将比较详细的说明这一问题,并给出一个较为完善的解决方案. 尽管这已经不是一个新问题了,但这 ...
- C#检测应用程序重复启动----函数检测(可以在多用户登录情况下检测)
上文是在网上找的检测程序重复运行的类,但是感觉不是很好用,而且还使用了API,似乎完全没有必要,于是晚上自己写了一个函数,经过测试,在多用户下仍然可以检测到程序的多次运行.当然,如果程序改了名字还是可 ...
- [WinForm]C# .net防止一个程序(WinForm)重复运行的方法。
最近比较忙,邮件预警系统暂停了没时间去处理,临时处理:直接执行exe文件! 可是问题来了: 我点击了两次,原来几乎在同时执行这个进程,我在程序中有线程时间睡眠2秒一次等待队列,打开进程果然两个MAIL ...
- MONO 如何打包 .NET程序独立运行(winform篇)
.NET程序独立运行是指运行.NET的电脑上,不需要安装.NET框架. .NET程序集“独立运行”并非真正的独立,它是运行在mono运行时基础之上的.由于这个运行时可以独立存在,所以,我们不需要在目标 ...
- winform .net2.0的程序如何运行于.net 4.x
约束 最近有一个winform项目,要求: (1)程序能够运行在winxp, win7, win8, win10中 (2)安装尽可能简单,尽量不要安装.net framework.即使要安装也要尽可以 ...
随机推荐
- 【C语言学习】《C Primer Plus》第5章 运算符、表达式和语句
学习总结 1.有了一定的语言基础,运算符和表达式这些都大同小异,无外乎赋值运算符(=).算术运算符(+.-.*./.%.++.——)和其他的一下运算符(sizeof.(type)). 2.声明一个参数 ...
- Wix 安装部署教程(十二) -- 自动更新WXS文件
上一篇分享了一个QuickWIX,用来对比两个工程前后的差异,但是这样还是很繁琐,而且昨天发现有Bug,目录对比有问题.这次改变做法,完全让程序自动去更新WXS文件,然后再用CCNet去自动编译,这样 ...
- Sqlserver 如何获取每组中的第一条记录
在日常生活方面,我们经常需要记录一些操作,类似于日志的操作,最后的记录才是有效数据,而且可能它们属于不同的方面.功能下面,从数据库的术语来说,就是查找出每组中的一条数据. 例子 我们要从上面获得的有效 ...
- Windows 10 周年版尝鲜
早在今年的 Build 大会上,微软就开始宣传最新的 Windows 10 周年版更新,炫了不少特技,直到昨天(2016/8/2 PST)才正式放出,相关新闻可以参考这里,正式的版本为 Version ...
- 将网站添加到iPhone的主屏幕上
我之前有篇文章介绍过如何将网站固定到Windows的开始菜单,并可以自定义图标.颜色以及Windows推送通知,其实Apple也有类似的功能,通过在网页的head部分添加link标记,在Safari浏 ...
- 分离EF connectionString里的db连接串
创建EF模型后,自动生成的connectionString如下: <add name="TravelPPEntities" connectionString="me ...
- 关于python的最大递归层数详解
在阅读http://www.cnblogs.com/skabyy/p/3451780.html这篇文章的时候,实验yield的流式迭代素数的时候发现有个问题,故详细记录下来. 首先来看看python默 ...
- Atitit.会员卡(包括银行卡)api的设计
Atitit.会员卡(包括银行卡)api的设计 1. 银行卡的本质是一种商业机构会员卡1 2. 会员卡号结构组成1 2.1. ●前六位是:发行者标识代码 Issuer Identification N ...
- C#并行编程-线程同步原语
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- CKEditor与CKFinder整合 MVC3
今天偶然看到一篇关于 CKEditor与CKFinder整合文章,心想有一段时间没有使用这种东西了.于是乎自己动手亲自体验了一下,本以为简单但在东西编写的过程发现了很多没有遇见毛病. 所以记录一下自己 ...