C# winform 一台电脑运行一个程序控制

一个私有云从业者 2010-06-24 08:58:18
如题,描述:我做一个C# winform程序。打开时候是个登录窗口,若登录成功则进入主窗口。
现在,我想控制一台电脑只可以有一个这样的程序在运行。当用户点击运行程序时,
若这个程序已经运行,则把这个程序的主窗口显示出来。
若没有运行则,显示登录窗口。


我用以下程序实现:
//查看是否有该程序的进程存在,若存在,将其结束,但是根本进入不了主页面。
private void btLogin_Click(object sender, EventArgs e)
{
//string processName = "123";//进程名
//foreach (System.Diagnostics.Process thisproc in System.Diagnostics.Process.GetProcesses())
//{
// if (thisproc.ProcessName.Equals(processName ))
// {
// thisproc.Kill();
// }
//}
}
...全文
725 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunkai572 2010-06-24
  • 打赏
  • 举报
回复
学习。。。
gohappy2008 2010-06-24
  • 打赏
  • 举报
回复
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WinFormStudy
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
bool ret;
System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out ret);
if (ret)
{
System.Windows.Forms.Application.EnableVisualStyles(); //这两行实现 XP 可视风格
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.Run(new Form1());
// frmMain 为你程序的主窗体,如果是控制台程序不用这句
m.ReleaseMutex();
}
else
{
MessageBox.Show(null, "有一个和本程序相同的应用程序已经在运行,请不要同时运行多个本程序。\n\n这个程序即将退出。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
// 提示信息,可以删除。
Application.Exit();//退出程序
}
}
}
}
fangbuge 2010-06-24
  • 打赏
  • 举报
回复
防止程序运行多个实例的方法有多种,如:通过使用互斥量和进程名等.而我想要实现的是:在程序运行多个实例时激活的是第一个实例,使其获得焦点,并在前端显示.

主要用到两个API 函数:

ShowWindowAsync 该函数设置由不同线程产生的窗口的显示状态。
SetForegroundWindow 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。
代码如下:

static class Program
{
/// <summary>
/// 该函数设置由不同线程产生的窗口的显示状态。
/// </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 WS_SHOWNORMAL = 1;

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Process instance = RunningInstance();
if (instance == null)
{
Form1 frm = new Form1();
Application.Run(new Form1());
}
else
{
HandleRunningInstance(instance);
}

}
/// <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)
{
ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); //显示,可以注释掉
SetForegroundWindow(instance.MainWindowHandle); //放到前端
}
}
记着引用以下命名空间:
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/baihe_591/archive/2008/08/22/2811731.aspx
pg1987ll 2010-06-24
  • 打赏
  • 举报
回复
学习,接分。
兔子-顾问 2010-06-24
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 hzzasdf 的回复:]
引用 8 楼 wuyazhe 的回复:
任何事都没绝对,这个前提是winform。非winform,都没窗体。你前置啥。直接把当前进程结束掉不就行了。

赫赫,忘了说了,这个程序对于已经最小化了的窗体好像无效哦。
对于已经最小化了的程序,需要先调用API函数ShowWindow(window, SW_SHOWNORMAL);然后再调用SetForegroundWindow
[/Quote]
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wuyazhe 的回复:]
任何事都没绝对,这个前提是winform。非winform,都没窗体。你前置啥。直接把当前进程结束掉不就行了。
[/Quote]
赫赫,忘了说了,这个程序对于已经最小化了的窗体好像无效哦。
对于已经最小化了的程序,需要先调用API函数ShowWindow(window, SW_SHOWNORMAL);然后再调用SetForegroundWindow
wxm3630478 2010-06-24
  • 打赏
  • 举报
回复
参考:http://blog.csdn.net/zgke/archive/2009/07/29/4390545.aspx

但是这个有一点缺陷,如果添加一个托盘,然后窗体this.Visible = false,那么就找不到主窗体啦....我自己是用Socket解决的
zjy118 2010-06-24
  • 打赏
  • 举报
回复
判断程序的实例能否已经启动,无非是通过设立某个标识,让下次启动程序时知道该实例已经运行。嗯,可是在WIN32中每个进程都有自已独立的空间,那么如何处理呢,下面提供两种方案:

方案一,使用内核对象

因为内核对象是能够跨进程具有的,因而我们能够通过创建一个命名互斥体(Mutex)内核对象来判断,当用同一个名字的来创建Mutex时,CreateMutex会前往一个指向该互斥体的句柄,但是GetLastError会得到ERROR_ALREADY_EXISTS的返值。因而我们就能够判断程序已有一个实例在运行。下面是其中的关键代码



m_hmutex = ::CreateMutex( NULL,FALSE,appID);



if(m_hmutex == NULL) return FALSE; //



if( ::GetLastError() == ERROR_ALREADY_EXISTS ) //

{

return FALSE;

}

else

{

return TRUE;

}



方案二,使用共享数据段

背景学问:EXE和DLL文件映像由许多区组成如代码在.text段中,初始化数据在.data段中,未初始化数据在.bss段中。系统在加载EXE和DLL时,实际上是使用了内存映射,为了减少加载时间,同一EXE文件多个实例实际在系统中只有一份。但一般地如果其中某个实例对某个数据区进行写时,系统会使用Copy-On-Write机制将这个数据区在虚拟内存中复制一份出来,并映射到该实例原先的地址空间,也就实现了进程数据的独一性,而不会干扰其它进程。但是我们能够通过设置让系统关闭掉这个机制。哪么如何做呢?

在Visual Studio中你能够程序中加上以下几行:

#pragma comment(linker,"/SECTION:Share,RWS") //指示编译器Share是可读写和共享的,当然你也能够通过设置链接器选项间接加上 /SECTION:Share,RWS,不过我更喜欢这个,因而其他朋友就不必自已去设置这个选项了。

#pragma data_seg("Share") // 开始自已的数据段

int g_AppInit =0; //必需初始化,否则不会将编译器不会将其放入Share这个区

#pragma data_seg()



还有一种将某个变量置于特别数据段的方式

__declspec(allocate("Share")) int g_AppInit =0;

这种方式的好处是无论你初不初始化这个变量都将置于该Share段内

哪么如何判断呢能否启动了实例呢,很简单,看以下代码

g_AppInit ++ ;

if(g_AppInit >1)

{

AfxMessageBox("A instance are runed!");

return FALSE;
来源:www.va1314.com/bc

}



相关的问题:如何通知前一个实例

处理了重复启动的问题,为了获得更佳的用户体验,往往我们要使前一个实例激活,如何做呢?使用消息是一个不错的方法。首先你需要在启动程序时登记一个全局消息。



WM_APPACTIVE = ::RegisterWindowMessage(appID);



相同的appID字符串会给出相同的消息值,并且分是在0xC000- 0xFFFF区间中,然后当你发觉已启动程序实例时通知前一个实例:

DWORD dectype = BSM_APPLICATIONS; //仅向应用程序发送



BroadcastSystemMessage(BSF_POSTMESSAGE,

&dectype,

WM_APPACTIVE,

0,0);

前一个程序实例收到这个消息后,进行处理,能够前置窗口激活等等。
  • 打赏
  • 举报
回复
谢谢各位,我的问题解决。
有空加QQ 群:102738525 一起交流啊
zjy118 2010-06-24
  • 打赏
  • 举报
回复
http://bbs.eyuyan.com/read.php?tid=160751
兔子-顾问 2010-06-24
  • 打赏
  • 举报
回复
而且是自己写的,自己知道如何选择策略的。
兔子-顾问 2010-06-24
  • 打赏
  • 举报
回复
任何事都没绝对,这个前提是winform。非winform,都没窗体。你前置啥。直接把当前进程结束掉不就行了。
  • 打赏
  • 举报
回复
楼上的程序是有缺陷的,有些程序拿不到MainWindowHandle
兔子-顾问 2010-06-24
  • 打赏
  • 举报
回复
新建一个windows application,吧program.cs文件替换为以下内容即可。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication2
{
static class Program
{
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
public static extern int SetForegroundWindow(IntPtr hwnd);

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Process[] p = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
//防止程序启动多次,只有一个运行的实例
if (p.Length > 1)
{
//将之前启动的窗体显示出来。
SetForegroundWindow(p[1].MainWindowHandle);
return;//退出软件
}
//正常情况下的窗体显示
Application.Run(new Form1());
}
}
}
  • 打赏
  • 举报
回复
楼主几位高手说的都很有道理,我都试过了,但是还是不行啊。
谁能够提供详细的解决方案啊?????
Baesky 2010-06-24
  • 打赏
  • 举报
回复

//string processName = "123";//进程名
//foreach (System.Diagnostics.Process thisproc in System.Diagnostics.Process.GetProcesses())
//{
// if (thisproc.ProcessName.Equals(processName ))
// {
// thisproc.Kill();
// }
//}
你的程序启动时候,进程肯定有你这个程序的名字了(就是123是吧?)
所以你判断的时候,必然能第2部分红字找找到你第一行红字设的进程名子进而必然执行thisproc.kill
vrhero 2010-06-24
  • 打赏
  • 举报
回复
老问题,用互斥体Mutex类即可...搜索一下例子多得是...
  • 打赏
  • 举报
回复
在codeproject网站有篇很好的帖子谈这个问题:

实现单实例并能够激活最小化了的程序
cecilia2006 2010-06-24
  • 打赏
  • 举报
回复
//string processName = "123";//进程名
//foreach (System.Diagnostics.Process thisproc in System.Diagnostics.Process.GetProcesses())
//{
// if (thisproc.ProcessName.Equals(processName ))
// {
// thisproc.Kill();
这个过程应该放在程序加载前吧 不能用thisproc.Kill(); 加载前如果发现存在 则这个程序 就不要加载了

Program 类里


//foreach (System.Diagnostics.Process thisproc in System.Diagnostics.Process.GetProcesses())
//{
// if !(thisproc.ProcessName.Equals(processName ))
// {
Application.Run(new Form6());
// // }
//}
ghost281536992 2010-06-24
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 wtpmcheng 的回复:]
运行通过~~~


C# code

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{

Process instance = RunningInstance();……
[/Quote]
这个方法貌似以前用过,而且就算窗体最小化了也没问题。
加载更多回复(5)
辅助软件 aspx/asp代码生成器 语言规范 C# Language Specification 1.2(C#语言规范1.2).doc C# Language Specification 2.0(C#语言规范2.0).doc 源码教程 ASP.NET编程技术与交互式网页设计 asp.net亲密接触_带源码 C#学习 01_类.htm.txt 02_构造函数的执行序列.htm.txt 03_抽象类和接口.htm.txt 04_结构类型.htm.txt 05_类成员的定义.htm.txt 06_类成员的其他议题.htm.txt 07_接口的执行.htm.txt 08_集合.htm.txt 09_运算符重载.htm.txt 10_阴影和深度复制.htm.txt 11_事件基础.htm.txt 12_事件进阶.htm.txt 13_读写Txt文件.htm.txt 14_StatusBar控件.htm.txt 15_自定义控件.htm.txt 16_使用打开保存文件对话框.htm.txt 17_图形绘制基础.htm.txt 18_图形绘制进阶-线条、字体.htm.txt 19_图形绘制进阶-图像(双倍缓冲).htm.txt 20_Windows应用程序安装部署概念.htm.txt 21_使用文件基础.htm.txt 22_使用文件高级.htm.txt 23_串行化和并行化.htm.txt 技术资料 ACCESS数据库操作类.txt ASP.NET常用代码.txt asp.net常用函数表.txt Asp.net的身份验证.txt ASP导出Excel数据的四种方法.txt C#调用存储过程.txt CheckBox控件.txt datagrid排序_选择_分页.txt DataSet对象.txt DotNET WinForm FAQ 16个.txt excel打印.txt EXCEL导出.txt EXCEL中合并单元格.txt mail.txt NET在RichTextBox控件加入图片(类似QQ).txt send.txt SQL储存过程等的解密.txt VisualC#打造“浏览器”.txt vs2005常用快捷键.txt webcontrol和pagelet.txt win2003中配置msdtc.txt word导出.txt 保证应用程序只有一个实例运行.txt 编辑字段中的word文件.txt 编码标准.txt 播放声音.txt 捕捉DataGrid的双击事件(C#版本).txt 不显示窗口后台运行程序.txt 储存过程.txt 处理“进程性能计数器被禁用”的错误.txt 串口操作.txt 打开word文件.txt 打造“浏览器”.txt 带图标和自定义颜色的ListBox.txt 得到当前数据库中所有用户表信息.txt 读取、设置系统时间日期.txt 读写注册表.txt 对过程进行加密.txt 二进制数据保存.txt 二进制数据字段的更新.txt 分页及动态创建列的控件 .txt 改变Windows服务的启动顺序.txt 各进制之间的转换.txt 给图片添加版权信息.txt 关于拖放操作.txt 关于在WinForm里用HttpWebRequest获得某个页面,并填写页面的textbox及点击button的方法.txt 画带阴影效果的文字.txt 环境信息.txt 获得光标在多行textbox中的行与列的函数.txt 计算控件中文字所占的宽度.txt 加半透明图片水印.txt 将控件放到datagrid中以及修改列宽.txt 截取系统消息.txt 解决VS.NET使用中属性框不显示的问题.txt 里的InputBox.txt 模拟鼠标和键盘操作.txt 取CPU的序列号.txt 如何:在VisualC#.NET中建立一个平滑的进度条.txt 如何得到网卡号.txt 如何调用WindowsAPI的要点.txt 如何控制输入法.txt 如何利用GDI作图解决异或问题.txt 如何取硬件标志.txt 如何让应用程序只有一个实例运行.txt 如何如何插入照片到Excel.txt 如何识别键盘左右的shift,Ctrl或Alt键.txt 如何水晶按钮的程序生成.txt 如何为DataGrid添加下拉列表框.txt 如何用C#在Excel中生成图表?.txt 如何用程序实现键盘和鼠标的模拟?.txt 如何与资源管理器互动剪切、拷贝、粘贴文件.txt 深入理解C#编程中的组件-事件-委托.txt 生成透明的GIF图片 .txt 生成压缩图片时的2种方法.txt 使用C#返回系统特殊路径.txt 使用VisualC#.NET检查Windows版本.txt 使用Win32和其他库.txt 使用自己画的光标.txt 数据绑定.txt 水晶报表使用winform.txt 水印.txt 特殊文件夹路径.txt 同一解决方案中一个项目的xml注释在另一个项目中不能智能提示显示这些注释的解决方法.txt 图像读取.txt 无标题窗口的拖放.txt 下面的5行代码完成了从局域网中找出所有的机器.txt 显示DataGrid序号的一个适用的方法.txt 用C#快速往Excel写数据.txt 用C#来捕获屏幕.txt 用C#做ScreenSaver.txt 用imgscan.ocx来扫描图像.txt 用word填充表格.txt 用户登录组合控件.txt 在.NET中得到计算机硬件信息的一些功能.txt 在MapX中响应滚轮放大缩小地图.txt 在两个ASP.NET页面之间传递值.txt 在如何利用SharpZipLib进行文件的压缩和解压缩.txt 怎样打开关闭CDROM.txt 怎样检测网络中的电脑是否有安装SQL2000.txt 怎样写一个存储过程类来实现如何对存储过程的调用?.txt 直接拉入图片文件到程序窗口中打开.txt 指定Web服务器运行的不是ASP.NET1.1版.txt 字符串加密.txt 字幕显示屏幕保护.txt 自己动手用c#写控件.txt C#试题 简答题.txt 填空题.txt 问答题1.txt 问答题2.txt 选择题.txt 综合题.txt

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧