代码改变世界

关于使用Xenocode PostBuild加壳的程序无法实现只允许运行一个实例的问题

2010-11-03 18:45  何朝阳  阅读(829)  评论(0)    收藏  举报

  今天下午突然发现,我打包安装后的浏览器程序,点击外部链接后,不会打开或是激活浏览器(直接双击图标可以运行多个实例,点击外部链接的时候,如果存在实例则激活浏览器窗口并打开链接,否则运行一个新的实例),而在程序调试的时候却没有这个问题,始终找不到原因,一直处于茫然状态,最后无意之中发现任务管理器中有两个浏览器进程(图1),并且内存使用相差很大,但是调试的时候只有一个进程,那么这应该是加壳后引起的问题(这里不讨论加壳的动机目的),凭直觉,内存占用少的这个进程就是Xenocode PostBuild加的一个外壳的进程。

图1 两个浏览器进程

  通过下面的代码,没有运行浏览器实例,但是返回的却不是null,而是上面图1中“6648”这个进程,却不能打开浏览器,这让我更加肯定是由于加壳引起的问题,返回的process和current肯定有不同的地方,关键是怎么把他们区分开来,过滤掉这个加壳的进程,先后试了很多方法,比如判断它们的启动时间,这虽然可以实现,但是不稳定,最后灵机一动,加壳后的进程的主模块加载模块所需的内存量肯定要比本身(current)的大,通过这个就可以过滤掉加壳的进程,并且如果存在多个实例的话,也可以区分开来,比判断启动时间的方法要好得多,最终修改代码,加壳后再次运行,一切正常!

#region 获取正在运行的实例,没有运行的实例返回null。
1 #region 获取正在运行的实例,没有运行的实例返回null。
2 /// <summary>
3 /// 获取正在运行的实例,没有运行的实例返回null。
4 /// </summary>
5 public static Process RunningInstance()
6 {
7 Process current = Process.GetCurrentProcess();
8 Process[] processes = Process.GetProcessesByName(current.ProcessName);
9 foreach (Process process in processes)
10 {
11 if (process.Id != current.Id)
12 {
13 if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
14 {
15 return process;
16 }
17 }
18 }
19 return null;
20 }
21 #endregion

修改后的代码:

获取正在运行的实例,没有运行的实例返回null。
1 #region 获取正在运行的实例,没有运行的实例返回null。
2 /// <summary>
3 /// 获取正在运行的实例,没有运行的实例返回null。
4 /// </summary>
5 public static Process RunningInstance()
6 {
7 Process current = Process.GetCurrentProcess();
8 Process[] processes = Process.GetProcessesByName(current.ProcessName);
9 foreach (Process process in processes)
10 {
11 //判断加载模块所需的内存量,过滤加壳的进程。
12 if (process.Id != current.Id && process.MainModule.ModuleMemorySize <= current.MainModule.ModuleMemorySize)
13 {
14 if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
15 {
16 return process;
17 }
18 }
19 }
20 return null;
21 }
22 #endregion

  由于水平有限,以上只是我的个人理解,还请各位大侠高手多多指教,感激不尽!