发送信息到Windows的过程(而不是它的主窗口) [英] Send message to a Windows process (not its main window)

查看:152
本文介绍了发送信息到Windows的过程(而不是它的主窗口)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有在随后开始检测是否有具有相同名称已经在运行,如果是这样处理的应用,激活运行的应用程序的窗口,然后退出。

的问题是,在主窗口可以被隐藏(只有一个通知区域图标可见),从而留下我没有窗口句柄。

在启动时,previous实例的 MainWindowHandle 属性为0,所以我不能发送的ShowWindow PostMessage的

有没有什么办法可以发送可通过运行应用程序截获的消息,从而使其能够显示其主窗口?

该应用程序是用C#中,code我使用的是实现这一目标如下:

  [STAThread]
静态无效的主要()
{
    布尔createdNew = TRUE;
    使用(互斥互斥=新的mutex(真的,MyMutexName,出createdNew))
    {
        如果(createdNew)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(假);
            Application.Run(新的MainForm());
        }
        其他
        {
            过程电流= Process.GetCurrentProcess();
            的foreach(工艺过程Process.GetProcessesByName(current.ProcessName))
            {
                如果(process.Id!= current.Id)
                {
                    Interop.WINDOWINFO PWI =新Interop.WINDOWINFO();
                    IntPtr的处理= process.MainWindowHandle;
                    VAR ISVISIBLE = Interop.GetWindowInfo(手柄,参考PWI);
                    如果(!ISVISIBLE)
                    {
                        的MessageBox.show(Constants.APP_NAME +已经在运行,检查通知区域(时钟附近)。
                                        Constants.APP_NAME,MessageBoxButtons.OK,MessageBoxIcon.Information); //临时的消息,直到我找到解决方案
                        //Interop.ShowWindow(handle,Interop.WindowShowStyle.ShowNormal);
                        //Interop.PostMessage(handle,Interop.WM_CUSTOM_ACTIVATEAPP,IntPtr.Zero,IntPtr.Zero);
                    }
                    其他
                        Interop.SetForegroundWindow(手柄); //这个作品时,窗口可见
                        打破;
                    }
                }
            }
        }
    }
}
 

解决方案

以下是我已经做到了这一点:

 使用系统;
使用了System.Runtime.InteropServices;
使用的System.Threading;
使用System.Windows.Forms的;
公共部分类的MainForm:表
{
    #区域导入DLL
    私人const int的HWND_BROADCAST = 0xFFFF的;

    私人静态只读INT WM_MY_MSG = RegisterWindowMessage(WM_MY_MSG);

    [的DllImport(USER32)]
    私有静态的extern BOOL PostMessage的(IntPtr的HWND,INT味精,IntPtr的WPARAM,IntPtr的LPARAM);

    [的DllImport(USER32)]
    私人静态外部INT RegisterWindowMessage(字符串消息);
    #endregion导入DLL
    静态互斥_single =新的互斥(真的,{4EABFF23-A35E-F0AB-3189-C81203BCAFF1});
    [STAThread]
    静态无效的主要()
    {
        //查看是否有实例已在运行...
        如果(_single.WaitOne(TimeSpan.Zero,真)){
            //不......正常启动。
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(假);
            尝试 {
                Application.Run(新的MainForm());
            }赶上(例外前){
                //处理异常相应
            } 最后 {
                _single.ReleaseMutex();
            }
        } 其他 {
            //是......把现有的实例顶部并激活它。
            PostMessage的(
                (IntPtr的)HWND_BROADCAST,
                WM_MY_MSG,
                新的IntPtr(0xCDCD)
                新的IntPtr(0xEFEF));
        }
    }

    保护覆盖无效的WndProc(参考消息M)
    {
        如果(m.Msg == WM_MY_MSG){
            如果((m.WParam.ToInt32()== 0xCDCD)及及(m.LParam.ToInt32()== 0xEFEF)){
                如果(的WindowState == FormWindowState.Minimized){
                    的WindowState = FormWindowState.Normal;
                }
                //把窗口前面。
                布尔TEMP =最顶层;
                最顶层=真;
                最顶层=温度;
                //将焦点设置窗口。
                激活();
            }
        } 其他 {
            base.WndProc(REF米);
        }
    }
}
 

我希望我已经正确的转录本。我不得不离开了很多其他的东西,但我想我得到了什么是必要的。我有什么对我的作品没有失败。如果你有问题,让我知道,我会看看有什么我已经错过了。

I have an application that on a subsequent start detects if there's a process with the same name already running and, if so, activates the running app's window and then exits.

The problem is that the main window could be hidden (only a notification area icon visible), thus leaving me with no window handle.

At startup, previous instance's MainWindowHandle property is 0, so I can't send ShowWindow or PostMessage.

Is there any way I can send a message that can be intercepted by the running app, thus allowing it to display its main window?

The application is written in C#, the code I'm using to achieve this below.

[STAThread]
static void Main()
{
    bool createdNew = true;
    using (Mutex mutex = new Mutex(true, "MyMutexName", out createdNew))
    {
        if (createdNew)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
        else
        {
            Process current = Process.GetCurrentProcess();
            foreach (Process process in Process.GetProcessesByName(current.ProcessName))
            {
                if (process.Id != current.Id)
                {
                    Interop.WINDOWINFO pwi = new Interop.WINDOWINFO();
                    IntPtr handle = process.MainWindowHandle;
                    var isVisible = Interop.GetWindowInfo(handle, ref pwi);
                    if (!isVisible)
                    {
                        MessageBox.Show(Constants.APP_NAME + " is already running, check the notification area (near the clock).", 
                                        Constants.APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);//temporary message, until I find the solution
                        //Interop.ShowWindow(handle, Interop.WindowShowStyle.ShowNormal);
                        //Interop.PostMessage(handle, Interop.WM_CUSTOM_ACTIVATEAPP, IntPtr.Zero, IntPtr.Zero);
                    }
                    else
                        Interop.SetForegroundWindow(handle);//this works when the window is visible
                        break;
                    }
                }
            }
        }
    }
}

解决方案

Here's how I've done this:

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
public partial class MainForm : Form
{
    #region Dll Imports
    private const int HWND_BROADCAST = 0xFFFF;

    private static readonly int WM_MY_MSG = RegisterWindowMessage( "WM_MY_MSG" );

    [DllImport( "user32" )]
    private static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

    [DllImport( "user32" )]
    private static extern int RegisterWindowMessage(string message);
    #endregion Dll Imports
    static Mutex _single = new Mutex(true, "{4EABFF23-A35E-F0AB-3189-C81203BCAFF1}");
    [STAThread]
    static void Main()
    {
        // See if an instance is already running...
        if (_single.WaitOne(TimeSpan.Zero, true)) {
            // No...start up normally.
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            try {
                Application.Run(new MainForm());
            } catch (Exception ex) {
                // handle exception accordingly
            } finally {
                _single.ReleaseMutex();
            }
        } else {
            // Yes...Bring existing instance to top and activate it.
            PostMessage(
                (IntPtr) HWND_BROADCAST,
                WM_MY_MSG,
                new IntPtr(0xCDCD),
                new IntPtr(0xEFEF));
        }
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_MY_MSG) {
            if ((m.WParam.ToInt32() == 0xCDCD) && (m.LParam.ToInt32() == 0xEFEF)) {
                if (WindowState == FormWindowState.Minimized) {
                    WindowState = FormWindowState.Normal;
                }
                // Bring window to front.
                bool temp = TopMost;
                TopMost = true;
                TopMost = temp;
                // Set focus to the window.
                Activate();
            }
        } else {
            base.WndProc(ref m);
        }
    }
}

I hope I've transcribed this correctly. I had to leave out a lot of other stuff, but I think I got what is necessary. What I have works for me without fail. If you have a problem, let me know, and I'll see what I've missed.

这篇关于发送信息到Windows的过程(而不是它的主窗口)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆