【发布时间】:2012-02-24 08:22:31
【问题描述】:
我正在向一个应用程序添加一些代码,如果该应用程序尚未运行,它将启动另一个应用程序,或者如果它已运行,则将其置于最前面。这需要少量的互操作/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 中以编程方式更改不同实例的窗口状态。这是怎么回事?
【问题讨论】:
-
在尝试恢复它之前,您是否尝试过让窗口可见,例如:
ShowWindow(handle, SW_SHOW);? -
我尝试了很多排列,包括首先调用 ShowWindow。问题是Process.MainWindowHandle提供的线程不是“主窗口”的线程。
标签: c# winapi windows-7 interop