在网上找的代码,但是总是运行失败。
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
嗯 谢谢啊 我知道这个缺陷 我的问题是 SetForegroundWindow和 ShowWindowAsync没有呈现出效果。
#4
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
嗯 谢谢啊 我知道这个缺陷 我的问题是 SetForegroundWindow和 ShowWindowAsync没有呈现出效果。
#4
GetLastError()
#5
貌似比较久的问题了,先试试可以回复不
#6
我刚才也遇到这个问题,感觉不是这部分的问题,是你界面还有未执行完成的线程导致。
我的解决方法:
在设置活动窗体结束前,先把未完成的线程结束:
我的解决方法:
在设置活动窗体结束前,先把未完成的线程结束:
while (IsIconic(instance.MainWindowHandle))
System.Windows.Forms.Application.DoEvents();