Windows Server 2008上的SetForegroundWindow失败

时间:2012-01-02 15:54:29

标签: c# windows winapi

情景 我的主应用程序最初是用Borland C ++编写的,它是由C#.Net应用程序启动的。这个主要应用程序偶尔会从一个名为BRWSEXE的进程打开一个模态对话框。弹出模态对话框窗口后,您可能会意外地单击主应用程序中的某个位置(而不是对话框),导致焦点暂时更改为主应用程序在Z顺序中发送模式对话框。但是你实际上无法在主应用程序上执行任何操作,它会被必须先关闭的模式对话框窗口锁定,然后才能继续。

问题 使用启动所有内容的.net应用程序,我可以找出与主应用程序相关的BRWSEXE实例并强制它们进入前台。这个策略在我到目前为止测试它的任何地方都能完美运行(Windows xp,Windows 7,Windows Server 2003 R2),但它在Windows Server 2008上不起作用。所以据我所知,我的代码工作得很好......但是那个环境中的东西正在把它扔掉。

我的代码

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

[DllImport("user32.dll")]
static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, bool fAttach);


private void PushBRWSEXEToFront()
{
    //Make sure MyApplication is running
    if (Process.GetProcessesByName("MyApplicationName").Length == 1)
    {
        Process[] brwsProc = Process.GetProcessesByName("BRWSEXE"); //Locate any processes for the browse dialog windows
        for (int x = brwsProc.Length - 1; x > -1; x--)
        {
            //Make sure the browse window we are looking at is associated with the active program we are looking at
            if (brwsProc[x].SessionId == Process.GetCurrentProcess().SessionId
                || brwsProc[x].SessionId == Process.GetProcessesByName("MyApplicationName")[0].SessionId)
            {
                //attach to the main applications thread
                AttachThreadInput(brwsProc[x].MainWindowHandle, Process.GetProcessesByName("MyApplicationName")[0].MainWindowHandle, true);

                //Call Set foreground window to push the browse window in front of the rest of the program.
                SetForegroundWindow(brwsProc[x].MainWindowHandle);

                //Detach from the main thread
                AttachThreadInput(brwsProc[x].MainWindowHandle, Process.GetProcessesByName("MyApplicationName")[0].MainWindowHandle, false);
            }
        }
    }
}

2 个答案:

答案 0 :(得分:3)

您的AttachThreadInput声明完全错误。它返回bool,参数为uint。你使用它错了,你应该传递线程ID,而不是窗口句柄。您需要GetWindowThreadProcessId()

你根本没有检查错误,所以你显然无法诊断失败。需要SetLastError属性,使用Marshal.GetLastWin32Error()检索错误。使用pinvoke.net获得更好的pinvoke声明。

答案 1 :(得分:0)

我使用过SwitchToThisWindow(),虽然MSDN说它可以在未来版本的Windows中删除,但它仍然适用于我。