一尘不染

恢复另一个应用程序的最小化窗口

c#

我正在向某个应用程序添加一些代码,如果该应用程序尚未运行,或者如果正在运行,它将启动另一个应用程序。这需要少量的interop /
WinAPI代码,我已经从其他站点获得了示例,但是似乎无法在Win7中使用。

如果窗口处于某种可见状态,则API的SetForegroundWindow方法的工作方式就像对待(这是主要情况,根据公司政策,如果外部应用程序正在运行,则不应将其最小化)。但是,如果将其最小化(异常但很重要,因为在这种情况下我的应用程序似乎什么也不做),此方法和ShowWindow
/ ShowWindowAsync都不会从任务栏上实际带回该窗口。所有方法只需突出显示任务栏按钮即可。

这是代码;大部分都可以正常工作,但是无论我发送的命令是什么,对ShowWindow()的调用(我也尝试过ShowWindowAsync)都永远不会达到我想要的效果:

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

    private const int SW_SHOWNORMAL = 1;
    private const int SW_SHOWMAXIMIZED = 3;
    private const int SW_RESTORE = 9;

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

...

//The app is named uniquely enough that it can't be anything else,
//and is not normally launched except by this one.
//so this should normally return zero or one instance
var processes = Process.GetProcessesByName("ExternalApp.exe");

        if (processes.Any()) //a copy is already running
        {
            //I can't currently tell the window's state,
            //so I both restore and activate it
            var handle = processes.First().MainWindowHandle;
            ShowWindow(handle, SW_RESTORE); //GRR!!!
            SetForegroundWindow(handle);
            return true;
        }

        try
        {
            //If a copy is not running, start one.
            Process.Start(@"C:\Program Files (x86)\ExternalApp\ExternalApp.exe");
            return true;
        }
        catch (Exception)
        {
            //fallback for 32-bit OSes
            Process.Start(@"C:\Program Files\ExternalApp\ExternalApp.exe");
            return true;
        }

我尝试了SHOWNORMAL(1),SHOWMAXIMIZED(3),RESTORE(9)和其他几个大小调整命令,但似乎没有办法解决问题。有什么想法吗?

编辑:
我发现我认为可以正常工作的其他一些代码有问题。对GetProcessesByName()的调用未找到进程,因为我正在寻找可执行文件名,而不是进程名。这导致我认为正在运行的代码实际上根本无法执行。我以为它起作用了,因为外部应用程序显然还会检测到副本已在运行,并尝试激活该当前实例。我从搜索的进程名称中删除了“
.exe”,现在代码执行了;但是,这似乎倒退了一步,因为当我调用ShowWindow
[Async]时,任务栏按钮甚至都没有突出显示。因此,我现在知道,无论我的应用程序还是我正在调用的外部应用程序,都无法在Win7中以编程方式更改其他实例的窗口状态。什么’


阅读 415

收藏
2020-05-19

共1个答案

一尘不染

…显然,您不能相信流程为您提供的信息。

Process.MainWindowHandle返回应用程序创建的第一个窗口的窗口句柄,通常是该应用程序的主顶级窗口。但是,以我为例,对FindWindow()的调用显示我要还原的实际窗口的句柄不是MainWindowHandle指向的对象。在这种情况下,进程的窗口句柄似乎是程序加载主窗体时显示的初始屏幕的句柄。

如果我在FindWindow返回的句柄上调用ShowWindow,则它可以正常工作。

更为不寻常的是,当打开窗口时,给定进程的MainWindowHandle(在该窗口关闭时应该无效)时,对SetForegroundWindow()的调用可以正常工作。因此很明显,该句柄具有一定的有效性,只是在窗口最小化时没有。

总而言之,如果您陷入困境,请致电FindWindow,将外部应用程序主窗口的已知名称传递给它,以获取所需的句柄。

2020-05-19