51Halcon机器视觉

 找回密码
 会员注册

QQ登录

只需一步,快速开始

扫一扫,微信登录

查看: 103|回复: 0
收起左侧

[资料] 让C#程序只运行一个实例,显示已经运行的界面

[复制链接]
  • TA的每日心情
    开心
    2020-11-7 10:15
  • 签到天数: 93 天

    连续签到: 1 天

    [LV.6]常住居民II

    29

    主题

    126

    帖子

    4210

    积分

    Rank: 6Rank: 6

    积分
    4210
    Princess 发表于 2020-11-3 15:47:06 | 显示全部楼层 |阅读模式

    51Halcon诚邀您的加入,专注于机器视觉开发与应用技术,我们一直都在努力!

    您需要 登录 才可以下载或查看,没有帐号?会员注册

    x
    本帖最后由 Princess 于 2020-11-3 15:49 编辑

    前提:一般操作硬件类型的软件,都需要独占硬件,所以这个时候对软件有一个要求就是只能运行一个实例,那么用户如果没有注意到程序已经运行再次去点击呢?如果没有做过防护那么很容易出现各种初始化异常问题,所以这个时候我们会考虑通过加入互斥体来解决该问题:
    1. bool bFlag;
    2. Mutex mutex = new Mutex(true, "_Demo1_", out bFlag);
    3. if (!bFlag)
    4. {
    5.       //检测到程序已经运行,一般情况下是弹窗提示不能重复运行
    6.       return;
    7. }
    8. mutex.ReleaseMutex();;
    复制代码


    这个是最早的雏形,当然这个问题也解决了,但是却不是很友好!
    那么有没有更好的一种方式呢?有的,我们可以迭代进程看看能否找到对应名称的进程,如果找到再将它打开并且显示,是不是就友好多了。

    那么我们需要在Progress.cs添加以下内容:
    命名空间引用:
    1. using System.Diagnostics;
    2. using System.Reflection;
    3. using System.Runtime.InteropServices;
    复制代码

    Main函数内部改造:
    1. Process instance = RunningInstance();
    2. if (null != instance)                  
    3. {
    4.         HandleRunningInstance(instance);
    5. }
    6. else
    7. {
    8.         Application.EnableVisualStyles();
    9.         Application.SetCompatibleTextRenderingDefault(false);
    10.         Application.Run(new Form1());
    11. }
    复制代码

    这句代码的意思就是如果找到了进程就直接打开运行中的实例,否则正常开启。

    下面是上面实现的核心函数,添加在Main函数下面即可。
    1. static Process RunningInstance()
    2.         {
    3.             Process current = Process.GetCurrentProcess();
    4.             Process[] processes = Process.GetProcessesByName(current.ProcessName);
    5.             foreach (Process process in processes)
    6.             {
    7.                 if (process.Id != current.Id)
    8.                 {
    9.                     if (Assembly.GetExecutingAssembly().Location.Replace("/ ", "\\ ") == current.MainModule.FileName)
    10.                     {
    11.                         return process;
    12.                     }
    13.                 }
    14.             }
    15.             return null;//第一次运行,返回null
    16.         }

    17.         public static void HandleRunningInstance(Process instance)
    18.         {
    19.             ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); //置窗口为正常状态
    20.             SetForegroundWindow(instance.MainWindowHandle);
    21.         }

    22.         #region 调用系统api

    23.         [DllImport("User32.dll ")]

    24.         private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

    25.         [DllImport("User32.dll ")]

    26.         private static extern bool SetForegroundWindow(IntPtr hWnd);

    27.         private const int WS_SHOWNORMAL = 1;

    28.         #endregion
    复制代码


    这里要注意,不要调试测试,因为current.ProcessName在调试下的进程是带了虚拟机标识的,比如Demo1.vshost这样的名称,实际运行是没有的。
    所以直接编译生成文件,到生成的目录下运行exe两次就可以看到效果。

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

    您需要登录后才可以回帖 会员登录 | 会员注册

    本版积分规则

    建议您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流浏览器浏览本网站

    51Halcon会员技术交流会员技术交流 | 51Halcon官方客服咨询官方客服咨询 | Halcon切换助手使用反馈切换助手使用

    申请友链| 小黑屋| 手机版| Archiver| 有问题需要咨询站长?|  

    CopyRight © 2015-2020 51Halcon机器视觉. Version X3.4.

    粤ICP备15095995号-2 粤公网安备44030602000670号

    快速回复 返回顶部 返回列表