C#单例运行,窗口最小化后如何最大化,下面代码不能正常运行啊

时间:2021-12-06 06:23:38
我写了个小程序,窗口最小化后,我想通过点击程序图标,让程序显示出来。
在网上找的代码,但是总是运行失败。
1.检测不到程序最小化。
2.不检测最小化,让它直接显示也不到最前端来。
下面是代码,望各位帮忙分析分析。


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

namespace AutoShutdown
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Process proc = SearchProcess();
            if (proc == null)             
            {                 
                Application.EnableVisualStyles();                
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new FormMain());              
            }             
            else             
            {                 
                //处理发现的例程
                HandleProcess(proc);                 
                //MessageBox.Show("当前程序已经运行了!");
            }

            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);           
            //Application.Run(new FormMain());
        }



        #region 只运行一个实例

        /// 恢复一个最小化的程序,并将其激活  
        /// <param name="hWnd">窗口句柄</param>  
        /// <returns>非零表示成功,零表示失败</returns>  
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool OpenIcon(IntPtr hWnd);

        /// 窗口是否已最小化  
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);

        /// 将窗口设为系统的前台窗口  
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern int SetForegroundWindow(IntPtr hWnd);

        /// 与ShowWindow相似,只是这时的ShowWindow命令会投递到指定的窗口,然后进行异步处理。  
        ///     这样一来,就可控制从属于另一个进程的窗口的可视情况。  
        ///     同时无须担心另一个进程挂起的时候,自己的应用程序也会牵连其中返回值  
        /// <param name="cmdShow">为窗口指定可视性方面的一个命令</param>  
        /// <returns>如窗口之前是可见的,则返回TRUE(非零),否则返回FALSE(零)</returns>  
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);


        //相关常量
        private const int SW_HIDE = 0;             //隐藏窗口,活动状态给另一个窗口   
        private const int SW_SHOWNORMAL = 1;       //用原来的大小和位置显示一个窗口,同时令其进入活动状态   
        private const int SW_SHOWMINIMIZED = 2;    //最小化窗口,并将其激活   
        private const int SW_SHOWMAXIMIZED = 3;    //最大化窗口,并将其激活   
        private const int SW_SHOWNOACTIVATE = 4;   //用最近的大小和位置显示一个窗口,同时不改变活动窗口   
        private const int SW_RESTORE = 9;          //用原来的大小和位置显示一个窗口,同时令其进入活动状态   
        private const int SW_SHOWDEFAULT = 10;     //根据默认 创建窗口时的样式 来显示  
 

        public static Process SearchProcess()         
        {             
            Process current = Process.GetCurrentProcess();             
            Process[] processes = Process.GetProcessesByName(current.ProcessName);             
            
            foreach (Process process in processes)             
            {
                //忽略现有的例程
                if (process.Id != current.Id)
                {                     
                    //确保例程从EXE文件运行
                    string location = System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", "\\");
                    if (location.Equals(current.MainModule.FileName))                     
                    {
                        //Console.WriteLine(location);
                        //MessageBox.Show(current.Id + "\n" + current.ProcessName);
                        //返回另一个例程实例
                        return process;                     
                    }                 
                }             
            }             
           
            return null;         
        }         
        

        /// 设置指定进程的窗口为活动  
        private static void HandleProcess(Process process)
        {
            IntPtr hWnd = process.MainWindowHandle;
            bool isIcon = IsIconic(hWnd);
            // 窗口是否已最小化  
            if (isIcon)
            {
                // 还原窗口  
                ShowWindowAsync(hWnd, SW_RESTORE);
            }
            else
            {
                //如果期望窗口显示为Normal模式,可先做如下设置
                ShowWindowAsync(hWnd, SW_SHOWNORMAL);
                // 将窗口设为前台窗口  
                SetForegroundWindow(hWnd);
            }
        }

        #endregion
    } 
       
    }


6 个解决方案

#1


我以前写的

[DllImport("user32.dll")]//设置窗体位活动窗体
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]//设置窗体状态
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
private const int SW_RESTORE = 9;        //用原来的大小和位置显示一个窗口

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createForm = false;//是否创建引用
using (Mutex mutex = new Mutex(true, "AHookProgram", out createForm)) {
if (createForm) {//如果系统中不存在"AHookProgram"元素 则创建窗体
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
} else {//如果系统中存在"AHookProgram"元素 则表明程序已经运行
MessageBox.Show("程序已经运行在进程中!", "提示");
//遍历进程根据进程名找寻窗体
Process current = Process.GetCurrentProcess();
foreach (Process p in Process.GetProcessesByName(current.ProcessName)) {
if (p.Id != current.Id) {//会查上来两个 将不是自己的那个显示出来
SetForegroundWindow(p.MainWindowHandle);//激活窗体
ShowWindowAsync(p.MainWindowHandle, SW_RESTORE);//设置窗体状态
}
}
}
}
}

感觉 你的太.......

#2


创建一个 互斥类 就搞定了 
貌似 你的是通过进程名字来判断是否 程序已经运行?
如果 我开一个程序 然后修改一下 名字 再运行 你怎么判断?、、、

#3


引用 1 楼 crystal_lz 的回复:
我以前写的


C# code?



12345678910111213141516171819202122232425262728293031

[DllImport("user32.dll")]//设置窗体位活动窗体 private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32……

嗯  谢谢啊 我知道这个缺陷  我的问题是 SetForegroundWindow和 ShowWindowAsync没有呈现出效果。

#4


引用 3 楼 tesky0125 的回复:
引用 1 楼 crystal_lz 的回复:我以前写的


C# code?



12345678910111213141516171819202122232425262728293031

[DllImport("user32.dll")]//设置窗体位活动窗体 private static extern bool SetForegroundWind……

GetLastError()

#5


貌似比较久的问题了,先试试可以回复不

#6


我刚才也遇到这个问题,感觉不是这部分的问题,是你界面还有未执行完成的线程导致。
我的解决方法:
    在设置活动窗体结束前,先把未完成的线程结束:
    
while (IsIconic(instance.MainWindowHandle))
                       System.Windows.Forms.Application.DoEvents();

#1


我以前写的

[DllImport("user32.dll")]//设置窗体位活动窗体
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]//设置窗体状态
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
private const int SW_RESTORE = 9;        //用原来的大小和位置显示一个窗口

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createForm = false;//是否创建引用
using (Mutex mutex = new Mutex(true, "AHookProgram", out createForm)) {
if (createForm) {//如果系统中不存在"AHookProgram"元素 则创建窗体
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
} else {//如果系统中存在"AHookProgram"元素 则表明程序已经运行
MessageBox.Show("程序已经运行在进程中!", "提示");
//遍历进程根据进程名找寻窗体
Process current = Process.GetCurrentProcess();
foreach (Process p in Process.GetProcessesByName(current.ProcessName)) {
if (p.Id != current.Id) {//会查上来两个 将不是自己的那个显示出来
SetForegroundWindow(p.MainWindowHandle);//激活窗体
ShowWindowAsync(p.MainWindowHandle, SW_RESTORE);//设置窗体状态
}
}
}
}
}

感觉 你的太.......

#2


创建一个 互斥类 就搞定了 
貌似 你的是通过进程名字来判断是否 程序已经运行?
如果 我开一个程序 然后修改一下 名字 再运行 你怎么判断?、、、

#3


引用 1 楼 crystal_lz 的回复:
我以前写的


C# code?



12345678910111213141516171819202122232425262728293031

[DllImport("user32.dll")]//设置窗体位活动窗体 private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32……

嗯  谢谢啊 我知道这个缺陷  我的问题是 SetForegroundWindow和 ShowWindowAsync没有呈现出效果。

#4


引用 3 楼 tesky0125 的回复:
引用 1 楼 crystal_lz 的回复:我以前写的


C# code?



12345678910111213141516171819202122232425262728293031

[DllImport("user32.dll")]//设置窗体位活动窗体 private static extern bool SetForegroundWind……

GetLastError()

#5


貌似比较久的问题了,先试试可以回复不

#6


我刚才也遇到这个问题,感觉不是这部分的问题,是你界面还有未执行完成的线程导致。
我的解决方法:
    在设置活动窗体结束前,先把未完成的线程结束:
    
while (IsIconic(instance.MainWindowHandle))
                       System.Windows.Forms.Application.DoEvents();