激活窗体

using System;
using System.Runtime.InteropServices;

internal static class Program
{
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

// [DllImport("user32.dll")]
// private static extern int BringWindowToTop(IntPtr hWnd);

private const int SW_MAXIMIZE = 3;

private static void Main()
{
IntPtr hwnd = (IntPtr)0x002A0682;

ShowWindow(hwnd, SW_MAXIMIZE);
// BringWindowToTop(hwnd);
}
}





C# WinForm 如果已经有其实例在运行,再运行新的实例就只闪一下屏幕,什么也看不到,导致不知所错。其实它的实例已经在“任务管理器”中,如果想结束它,可以按以下三个组合键 Ctrl + Alt + Del,点击其中的“任务管理器”进入Windows任务管理器,再点击“进程”页面,点选你的进程,再按“结束进程”将其结束。

  以下代码只允许 C# WinForm 运行一个实例 ,如果已经有其实例在运行,就将其窗口激活到前段显示。

主要代码如下:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
//只运行一个实例
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;

namespace WindowsApplication10
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
 //1.这里判定是否已经有实例在运行
            //只运行一个实例
            Process instance = RunningInstance();
            if (instance == null)
            {
                //1.1 没有实例在运行
                Application.Run(new Form1());
            }
            else
            {
                //1.2 已经有一个实例在运行
                HandleRunningInstance(instance);
            }

        }
//2.在进程中查找是否已经有实例在运行
        #region  确保程序只运行一个实例
        private 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;
        }
//3.已经有了就把它激活,并将其窗口放置最前端
        private static void HandleRunningInstance(Process instance)
        {
            MessageBox.Show("已经在运行!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            ShowWindowAsync(instance.MainWindowHandle, 1);  //调用api函数,正常显示窗口
            SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端
        }
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(System.IntPtr hWnd);
        #endregion

    }
}

=======更多的网上例子见下面====

==1==
 
 
  • 只运行一个实例,单击程序快捷方式让程序激活到前台

涉及类:

1、 启动画面类:

public class SplashForm : System.Windows.Forms.Form

{

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label lbl_version;

///

/// 必需的设计器变量。

///

private System.ComponentModel.Container components = null;

public SplashForm()

{

//

// Windows 窗体设计器支持所必需的

//

InitializeComponent();

lbl_version.Text = "版本:" + Application.ProductVersion;

//

// TODO: 在 InitializeComponent 调用后添加任何构造函数代码

//

}

//以下省略

2、 应用程序加载类:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Runtime.InteropServices;

using System.Diagnostics;

using System.Reflection;

using System.IO;

namespace Heroic.TempAnalyse.TempGui

{

///

/// AppLoader 的摘要说明。

///

public class AppLoader

{

private static ApplicationContext context;

private static SplashForm sForm = new SplashForm();

private static MainWindow mForm = null;

//0不可见但仍然运行,1居中,2最小化,3最大化

private const int WS_SHOWNORMAL = 3;

[STAThread]

static void Main(string[] args)

{

// [8/12/2004]用于更新该程序。

doUpData();

// [7/19/2004] 改变顺序,目的使得开始加载速度加快

//得到正在运行的例程

Process instance = RunningInstance();

if(instance == null)

{

sForm.Show();

mForm = new MainWindow();

context = new ApplicationContext();

Application.Idle += new EventHandler(OnAppIdle);

Application.Run(context);

}

else

{

//处理发现的例程

HandleRunningInstance(instance);

//MessageBox.Show("当前程序已经运行了!");

}

}

//在线更新用,不再本文范围

private static void doUpData()

{

System.Diagnostics.Process.Start(Application.StartupPath+@"update.exe",Application.StartupPath+@"Heroic.TempAnalyse.TempGui.exe0");//

}


private static void OnAppIdle(object sender, EventArgs e)

{

if(context.MainForm == null)

{

Application.Idle -= new EventHandler(OnAppIdle);

mForm.PreLoad();

context.MainForm = mForm;

context.MainForm.Show();

sForm.Close();

sForm = null;

}

}

//不允许有两个程序同时启动

public static Process RunningInstance()

{

Process current = Process.GetCurrentProcess();

Process[] processes = Process.GetProcessesByName (current.ProcessName);

//遍历正在有相同名字运行的例程

foreach (Process process in processes)

{

//忽略现有的例程

if (process.Id != current.Id)

{

//确保例程从EXE文件运行

if (Assembly.GetExecutingAssembly().Location.Replace("/", "") ==

current.MainModule.FileName)

{

//返回另一个例程实例

return process;

}

}

}

//没有其它的例程,返回Null

return null;

}


public static void HandleRunningInstance(Process instance)

{

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

ShowWindowAsync (instance.MainWindowHandle , WS_SHOWNORMAL);


//设置真实例程为foreground window

SetForegroundWindow (instance.MainWindowHandle);

}


[DllImport("User32.dll")]


private static extern bool ShowWindowAsync(

IntPtr hWnd, int cmdShow);

[DllImport("User32.dll")] private static extern bool

SetForegroundWindow(IntPtr hWnd);

}

}

3、 加载完毕正式运行后的类:

public void PreLoad()

{

// 如果已经加载毕,则返回

if (_Loaded)

return;

// 把机器生成的代码放到这里

initCustomControl();

_Loaded = true;


}


// 是否加载完毕

private bool _Loaded = false;


protected override void OnLoad(EventArgs e)

{

// 确保 PreLoad()函数已经调用

if (!_Loaded)

throw new InvalidOperationException("Must call PreLoad before calling this function.");


}

 
==2==
方法一:
using System;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using System.Runtime.InteropServices;
 using System.Diagnostics;
 using System.Reflection;
 
 namespace WinFormStudy
 {
     static class Program
     {
 
         /// <summary>
         /// 应用程序的主入口点。
         /// </summary>
         [STAThread]
         static void Main()
         {
             Process instance = RunningInstance();
             if (instance == null)
             {
                 //没有实例在运行
                 Application.Run(new Form1());
             }
             else
             {
                 //已经有一个实例在运行
                 HandleRunningInstance(instance);
             }
         }
         #region  确保程序只运行一个实例
         private 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;
         }
 
         private static void HandleRunningInstance(Process instance)
         {
             MessageBox.Show("已经在运行!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
             ShowWindowAsync(instance.MainWindowHandle, 1);  //调用api函数,正常显示窗口
             SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端
         }
         [DllImport("User32.dll")]
         private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
         [DllImport("User32.dll")]
         private static extern bool SetForegroundWindow(System.IntPtr hWnd);
         #endregion
     }
 }
 
 
方法二:
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, "有一个和本程序相同的应用程序已经在运行,请不要同时运行多个本程序。 这个程序即将退出。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                 // 提示信息,可以删除。  
                 Application.Exit();//退出程序  
             }
         }
     }
 }
 
==3==

C#限制程序只能运行一個实例

  (2012-06-16 16:46:31)
 

方法一:只禁止多个进程运行

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DuoYeMianIE
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            bool ret;
            System.Threading.Mutex mutex = new System.Threading.Mutex(true, Application.ProductName, out ret);
            if (ret)
            {
                System.Windows.Forms.Application.EnableVisualStyles();   //这两行实现   XP   可视风格  
                System.Windows.Forms.Application.DoEvents();             //这两行实现   XP   可视风格   
                System.Windows.Forms.Application.Run(new LamBrowser());
                //   Main   为你程序的主窗体,如果是控制台程序不用这句   
                mutex.ReleaseMutex();
            }
            else
            {
                MessageBox.Show(null, "有一个和本程序相同的应用程序已经在运行,请不要同时运行多个本程序。 这个程序即将退出。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                //   提示信息,可以删除。   
                Application.Exit();//退出程序   
            }
        }
    }
}

方法二:禁止多个进程运行,并当重复运行时激活以前的进程

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

namespace DuoYeMianIE
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
{
    //Get   the   running   instance.   
    Process instance = RunningInstance();
    if (instance == null)
    { System.Windows.Forms.Application.EnableVisualStyles();   //这两行实现   XP   可视风格   
        System.Windows.Forms.Application.DoEvents();
        //There   isn't   another   instance,   show   our   form.   
        System.Windows.Forms.Application.Run(new LamBrowser());
    }    
    else
    {
        //There   is   another   instance   of   this   process.   
        HandleRunningInstance(instance);
    }
}

   
public static Process RunningInstance()
{
    
    Process current = Process.GetCurrentProcess();
    Process[] processes = Process.GetProcessesByName(current.ProcessName);
    //Loop   through   the   running   processes   in   with   the   same   name   
    foreach (Process process in processes)
    {
        //Ignore   the   current   process   
        if (process.Id != current.Id)
        {
            //Make   sure   that   the   process   is   running   from   the   exe   file.   
           
            if (Assembly.GetExecutingAssembly().Location.Replace("/", "") == current.MainModule.FileName)
            {
                //Return   the   other   process   instance.   
                return process;
            }
        }
    }
    //No   other   instance   was   found,   return   null. 
    return null;
}
public static void HandleRunningInstance(Process instance)
{
    //Make   sure   the   window   is   not   minimized   or   maximized   
    ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
    //Set   the   real   intance   to   foreground   window
    SetForegroundWindow(instance.MainWindowHandle);
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private const int WS_SHOWNORMAL = 1;
    }
}

来自:http://fateful.blog.sohu.com/136259304.html

==4==

C# 只允许运行一个实例 ,如果运行了激活它 

 
 
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
 
namespace GrabData
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Common.StaticVariables sv = new GrabData.Common.StaticVariables();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
 
            Process instance = RunningInstance();
            if (instance == null)
            {
                if (sv.ReadXml())
                    Application.Run(new Main());
            }
            else
            {
                HandleRunningInstance(instance);
            }
        }
 
        // <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>
        /// 获取正在运行的实例,没有运行的实例返回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 (System.Reflection.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);            //放到前端
        }
 
    }
}
==5==
 

    互斥进程(程序), 简单点说,就是在系统中只能有该程序的一个实例运行. 现在很多软件都有这功能,如Maxthon 可以设置为"只允许打开一个窗体",还有Bitcomet等. 我也是看到这些软件的这个功能才来研究这个问题的.  要实现程序的互斥,通常有三中方式,下面用 C#  语言来实现:

实现方式一: 使用线程互斥变量. 通过定义互斥变量来判断是否已运行实例.C#实现如下:

    把program.cs文件里的Main()函数改为如下代码:

        static void Main()
        {
            bool runone;
            System.Threading.Mutex run = new System.Threading.Mutex(true, "xinbiao_a_test", out runone);
            if (runone)
            {
              run.ReleaseMutex();
              Application.EnableVisualStyles();
              Application.SetCompatibleTextRenderingDefault(false);
              Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("已经运行了一个实例了。");
            }
        }

  说明:程序中通过语句 System.Threading.Mutex run = new System.Threading.Mutex(true, "xinbiao_a_test", out runone); 来申明一个互斥体变量run,其中"xinbiao_a_test"为互斥体名,布尔变量runone用来保存是否已经运行了该程序事例.

实现方式二:   采用判断进程的方式,我们在运行程序前,查找进程中是否有同名的进程,同时运行位置也相同程,如是没有运行该程序,如果有就就不运行.在C#中应用System.Diagnostics名字空间中的Process类来实现,主要代码如下:

        1,在program.cs文件中添加函数如下:

        public static System.Diagnostics.Process RunningInstance()
        {
            System.Diagnostics.Process current = System.Diagnostics.Process.GetCurrentProcess();
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();
            foreach (System.Diagnostics.Process process in processes) //查找相同名称的进程
            {
                if (process.Id != current.Id)  //忽略当前进程
                { //确认相同进程的程序运行位置是否一样.
                    if (System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", @"/") == current.MainModule.FileName)
                    { //Return the other process instance.                      
                        return process;
                    }
                }
            } //No other instance was found, return null.
            return null;
        } 

        2,把Main ()函数改为如下代码:

        static void Main()
        {
            if(RunningInstance()==null)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("已经运行了一个实例了。");
            }
        }

实现方式三:全局原子法,创建程序前,先检查全局原子表中看是否存在特定原子A(创建时添加的),存在时停止创建,说明该程序已运行了一个实例;不存在则运行程序并想全局原子表中添加特定原子A;退出程序时要记得释放特定的原子A哦,不然要到关机才会释放。C#实现如下:

1、申明WinAPI函数接口:

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]

        public static extern UInt32 GlobalAddAtom(String lpString);  //添加原子

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]

        public static extern UInt32 GlobalFindAtom(String lpString);  //查找原子

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]

        public static extern UInt32 GlobalDeleteAtom(UInt32 nAtom);  //删除原子

2、修改Main()函数如下:

        static void Main()
        {
            if (GlobalFindAtom("xinbiao_test") == 77856768) //没找到原子"xinbiao_test"
            {
                GlobalAddAtom("xinbiao_test");  //添加原子"xinbiao_test"
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                MessageBox.Show("已经运行了一个实例了。");
            }                       
        }


3、在FormClosed事件中添加如下代码:

       GlobalDeleteAtom(GlobalFindAtom("xinbiao_test"));//删除原子"xinbiao_test"

以上为创建互斥程序(进程)的基本通用的思想,个人认为,第一种方法最好。以上所有代码都在VS.NET2005 中测试通过。

==6==

C#中让程序只运行一个实例(单实例运行)

两个主流的方法。

方法一:使用Mutex来进行

1. 首先要添加如下的namespace:

using System.Threading;

2. 修改系统Main函数,大致如下:

        bool bCreatedNew;

      

        //Create a new mutex using specific mutex name

        Mutex m =new Mutex( false, "myUniqueName", out bCreatedNew );

        if( bCreatedNew )

            Application.Run(new yourFormName());

如上面编码就可以了,要注意的一点是,在给Mutex起名字的时候,不要太简单,以防止和其他程序的Mutex重复,从而达不到所预想的效果。

方法二:使用Process来进行

1. 首先要添加如下的namespace:

using System.Diagnostics;

using System.Reflection;

2. 添加如下函数:

        public static Process RunningInstance()

        {

            Process current = Process.GetCurrentProcess();

            Process[] processes = Process.GetProcessesByName(current.ProcessName);

            //Loop through the running processes in with the same name

            foreach (Process process in processes)

            {

                //Ignore the current process

                if (process.Id != current.Id)

                {

                    //Make sure that the process is running from the exe file.

                    if (Assembly.GetExecutingAssembly().Location.Replace("/", "") == current.MainModule.FileName)

                    {

                        //Return the other process instance.

                        return process;

                    }

                }

            }

            //No other instance was found, return null.

            return null;

        }

3. 修改系统Main函数,大致如下:

            if( RunningInstance() == null )

                Application.Run(new yourFormName());

如上面编码就可以了,要注意的一点是,在判断进程模块文件名是否相等这部分的代码,是可选的。如果当前的程序在文件系统中只存在一个的话,以上的方法是可以的;否则不要删除这部分的代码。

对比两种方法,就效率和简便性来说,前一种方法是最好的,也是我比较喜欢的;后一种方法,速度比较慢,其次通过ProcessName去系统中查寻,有可能查出来的Process并不是我想要得,虽说在后面加了文件目录判断,但是其含有潜在的问题(前面已经说出来)。不过,第一种方法也有缺陷,就是扩展性操作不方便,例如:让程序只运行一次,如果程序已经运行,把它弹出并显示到最前面。对于此,后一种方法就很有优势了。

原文地址:https://www.cnblogs.com/1175429393wljblog/p/5359613.html