能运行c#语言软件,基于.Net平台应用程序唯一运行实例C#代码实现-.NET教程,C#语言...

作者:郑佐

时间:2006-7-2

概述

本文是针对《基于.net平台应用程序唯一运行实例实现》的补充,文章给出功能实现代码,其中singleinstance类实现只允许一个实例运行,program为测试主程序入口。在代码中标识说明文字。完整代码下载。

主要代码

singleinstance.cs文件,

using system;

using system.io;

using system.diagnostics;

using system.threading;

using system.reflection;

using system.runtime.interopservices;

/*————————————————

郑佐 2006-07-01  http://blog.csdn.net/zhzuo

————————————————–*/

namespace zhengzuo.csharpcode

{

///

/// 只启动一个应用程序实例控制类

///

public static class singleinstance

{

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);

//标志文件名称

private static string runflagfullname = null;

//声明同步基元

private static mutex mutex = null;

///

/// static constructor

///

static singleinstance()

{

}

#region api实现

///

/// 获取应用程序进程实例,如果没有匹配进程,返回null

///

/// 返回当前process实例

public static process getrunninginstance()

{

process currentprocess = process.getcurrentprocess();//获取当前进程

//获取当前运行程序完全限定名

string currentfilename = currentprocess.mainmodule.filename;

//获取进程名为processname的process数组。

process[] processes = process.getprocessesbyname(currentprocess.processname);

//遍历有相同进程名称正在运行的进程

foreach (process process in processes)

{

if (process.mainmodule.filename == currentfilename)

{

if (process.id != currentprocess.id)//根据进程id排除当前进程

return process;//返回已运行的进程实例

}

}

return null;

}

///

/// 获取应用程序句柄,设置应用程序前台运行,并返回bool值

///

public static bool handlerunninginstance(process instance)

{

//确保窗口没有被最小化或最大化

showwindowasync(instance.mainwindowhandle, ws_shownormal);

//设置真实例程为foreground window

return setforegroundwindow(instance.mainwindowhandle);

}

///

/// 获取窗口句柄,设置应用程序前台运行,并返回bool值,重载方法

///

///

public static bool handlerunninginstance()

{

process p = getrunninginstance();

if (p != null)

{

handlerunninginstance(p);

return true;

}

return false;

}

#endregion

#region mutex实现

///

/// 创建应用程序进程mutex

///

/// 返回创建结果,true表示创建成功,false创建失败。

public static bool createmutex()

{

return createmutex(assembly.getentryassembly().fullname);

}

///

/// 创建应用程序进程mutex

///

/// mutex名称

/// 返回创建结果,true表示创建成功,false创建失败。

public static bool createmutex(string name)

{

bool result = false;

mutex = new mutex(true, name, out result);

return result;

}

///

/// 释放mutex

///

public static void releasemutex()

{

if (mutex != null)

{

mutex.close();

}

}

#endregion

#region 设置标志实现

///

/// 初始化程序运行标志,如果设置成功,返回true,已经设置返回false,设置失败将抛出异常

///

/// 返回设置结果

public static bool initrunflag()

{

if (file.exists(runflag))

{

return false;

}

using (filestream fs = new filestream(runflag, filemode.create))

{

}

return true;

}

///

/// 释放初始化程序运行标志,如果释放失败将抛出异常

///

public static void disposerunflag()

{

if (file.exists(runflag))

{

file.delete(runflag);

}

}

///

/// 获取或设置程序运行标志,必须符合windows文件命名规范

/// 这里实现生成临时文件为依据,如果修改成设置注册表,那就不需要符合文件命名规范。

///

public static string runflag

{

get

{

if(runflagfullname == null)

{

string assemblyfullname = assembly.getentryassembly().fullname;

//commonapplicationdata://”c:\\documents and settings\\all users\\application data”

string path = environment.getfolderpath(environment.specialfolder.commonapplicationdata);

//”c:\\program files\\common files”

//string path = environment.getfolderpath(environment.specialfolder.commonprogramfiles);

runflagfullname = path.combine(path, assemblyfullname);

}

return runflagfullname;

}

set

{

runflagfullname = value;

}

}

#endregion

}

}

program.cs文件,

using system;

using system.windows.forms;

using system.diagnostics;

using zhengzuo.csharpcode;

/*————————————————

郑佐 2006-07-01  http://blog.csdn.net/zhzuo

————————————————–*/

namespace zhengzuo.test.wingui

{

static class program

{

[stathread]

static void main(string[] args)

{

if (args.length == 0) //没有传送参数

{

process p = singleinstance.getrunninginstance();

if (p != null) //已经有应用程序副本执行

{

singleinstance.handlerunninginstance(p);

}

else //启动第一个应用程序

{

runapplication();

}

}

else //有多个参数

{

switch (args[0].tolower())

{

case “-api”:

if (singleinstance.handlerunninginstance() == false)

{

runapplication();

}

break;

case “-mutex”:

if (args.length >= 2) //参数中传入互斥体名称

{

if ( singleinstance.createmutex(args[1]) )

{

runapplication();

singleinstance.releasemutex();

}

else

{

//调用singleinstance.handlerunninginstance()方法显示到前台。

messagebox.show(“程序已经运行!”);

}

}

else

{

if (singleinstance.createmutex())

{

runapplication();

singleinstance.releasemutex();

}

else

{

//调用singleinstance.handlerunninginstance()方法显示到前台。

messagebox.show(“程序已经运行!”);

}

}

break;

case “-flag”://使用该方式需要在程序退出时调用

if (args.length >= 2) //参数中传入运行标志文件名称

{

singleinstance.runflag = args[1];

}

try

{

if (singleinstance.initrunflag())

{

runapplication();

singleinstance.disposerunflag();

}

else

{

//调用singleinstance.handlerunninginstance()方法显示到前台。

messagebox.show(“程序已经运行!”);

}

}

catch (exception ex)

{

messagebox.show(ex.tostring());

}

break;

default:

messagebox.show(“应用程序参数设置失败。”);

break;

}

}

}

//启动应用程序

static void runapplication()

{

application.enablevisualstyles();

application.run(new mainform());

}

}

}

功能测试

功能测试类别包括下面五类,

1.本地系统同一应用程序目录;

2.本地系统同一应用程序修改运行文件名称使两次运行名称不同;

3.本地系统两次运行程序目录不同,不修改文件名称;

4.本地系统不同会话用户登录启动应用程序;

5.远程计算机程序访问启动应用程序(一个程序在远程另一个在本地)。

运行cmd命令行,

第一种调用方式:

windowsapplication1.exe

或 windowsapplication1.exe –api

第二种调用方式:

windowsapplication1.exe –mutex

或windowsapplication1.exe –mutex {f140ae26-626c-42f8-bd49-45025742205e}

第三种调用方式:

windowsapplication1.exe –flag

或windowsapplication1.exe –flag c:\blog.csdn.net.zhzuo

测试结果,

匹配/互斥/标志

1同一目录

2修改名称

3不同目录

4不同用户

5远程访问

1同一目录

o/o/o

2修改名称

x/o/o

3不同目录

x/o/o

4不同用户

#/x/o

5远程访问

x/o/o

备注:o – 表示成功,x – 表示失败,# – 程序第二个运行没有反应

针对远程访问的测试,需要在系统管理工具的.net framework 2.0 configuration中进行设置授权该局域网路径允许访问,否则会抛出system.security.securityexception异常。

根据测试结果可见三种实现方式适用范围不同,理想的实现是结合他们的优点进行多点判断。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值