zoukankan      html  css  js  c++  java
  • [Winform]只允许运行一个exe,如果已运行则将窗口置前

    摘要

    接着介绍项目中用到的一些方法,在winform中,打好包,有时并不允许运行多个客户端,要保证只有一个客户端运行。如果已经运行了,则弹出已运行的窗口,使其展示。

    方法

    判断是否有相同的进程

       /// <summary>  
            /// 获取当前是否具有相同进程。  
            /// </summary>  
            /// <returns></returns>  
            public static Process GetRunningInstance()
            {
                Process current = Process.GetCurrentProcess();
                Process[] processes = Process.GetProcessesByName(current.ProcessName);
                //遍历正在有相同名字运行的例程     
                foreach (Process process in processes)
                {
                    //忽略现有的例程     
                    if (process.Id != current.Id)
                        //确保例程从EXE文件运行   
                        if (System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", "\") == current.MainModule.FileName)
                            return process;
                }
                return null;
            }

    在Main函数中,进行判断

            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                try
                {
             
                
                    Process instance = GetRunningInstance();
                    Application.SetCompatibleTextRenderingDefault(false);
                    if (instance == null)
                    {
                        Run();
                    }
                    else
                    {
                        ShowWindowAsync(instance.MainWindowHandle, SW_SHOWNOACTIVATE);  //调用api函数,正常显示窗口
                        SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端
                    }
                }
                catch (Exception ex)
                {
                    LogInfoData.WriteLog(new LogInfo { Message = ex.Message, Op = "start_app_err" });
                    MessageBox.Show("系统启动出现异常,请重新启动");
                }
            }

    windows API

         private const int SW_HIDE = 0;
            private const int SW_NORMAL = 1;
            private const int SW_MAXIMIZE = 3;
            private const int SW_SHOWNOACTIVATE = 4;
            private const int SW_SHOW = 5;
            private const int SW_MINIMIZE = 6;
            private const int SW_RESTORE = 9;
            private const int SW_SHOWDEFAULT = 10;
            [DllImport("User32.dll")]
            private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
            [DllImport("User32.dll")]
            private static extern bool SetForegroundWindow(System.IntPtr hWnd);

    在使用SetForegroundWindow需要注意以下几点:

    The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

    • The process is the foreground process.
    • The process was started by the foreground process.
    • The process received the last input event.
    • There is no foreground process.
    • The process is being debugged.
    • The foreground process is not a Modern Application or the Start Screen.
    • The foreground is not locked (see LockSetForegroundWindow).
    • The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
    • No menus are active.

    An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.

    A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindowfunction. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.

    The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.

    地址:https://msdn.microsoft.com/en-us/library/ms633539(v=VS.85).aspx

    这个进程是前台进程。
    这个进程是由前台进程的开始。
    进程中收到的最后一个输入事件。
    没有前台进程。
    前台进程正在被调试。
    前置不被锁定(见LockSetForegroundWindow)。
    前置锁定超时已过期(看到SPI_GETFOREGROUNDLOCKTIMEOUTSystemParametersInfo

    需要满足上面一条即可,比如如果这个进程是后台进程,则不会起作用。可以在windows任务管理器中,查看是否在窗口最小化的时候,变成了后台进程。比如,常用的Hide方法,会是窗口变为后台进程,而窗口最下话操作,则不会改变进程状态,扔是前台进程。

     this.WindowState = FormWindowState.Minimized;
  • 相关阅读:
    使用OPATCH_DEBUG环境变量调试Opatch工具
    ORACLE or Oracle?
    Precheck while you are applying oneoff patch
    SHMALL, SHMMAX and SGA sizing
    解决UDE31623错误一例
    Postgre SQL 9.1 beta:开源世界的礼物
    How does SGA/PGA allocate on AMM?
    /dev/shm Filled Up With Files In Format JOXSHM_EXT_xxx_SID_xxx
    解决ORA27103:internal error错误一例
    headfirst java ( 第 10 章 )
  • 原文地址:https://www.cnblogs.com/wolf-sun/p/7140493.html
Copyright © 2011-2022 走看看