我正在向某个应用程序添加一些代码,如果该应用程序尚未运行,或者如果正在运行,它将启动另一个应用程序。这需要少量的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中以编程方式更改其他实例的窗口状态。什么’
…显然,您不能相信流程为您提供的信息。
Process.MainWindowHandle返回应用程序创建的第一个窗口的窗口句柄,通常是该应用程序的主顶级窗口。但是,以我为例,对FindWindow()的调用显示我要还原的实际窗口的句柄不是MainWindowHandle指向的对象。在这种情况下,进程的窗口句柄似乎是程序加载主窗体时显示的初始屏幕的句柄。
如果我在FindWindow返回的句柄上调用ShowWindow,则它可以正常工作。
更为不寻常的是,当打开窗口时,给定进程的MainWindowHandle(在该窗口关闭时应该无效)时,对SetForegroundWindow()的调用可以正常工作。因此很明显,该句柄具有一定的有效性,只是在窗口最小化时没有。
总而言之,如果您陷入困境,请致电FindWindow,将外部应用程序主窗口的已知名称传递给它,以获取所需的句柄。