1

关于我首先制作的一些背景知识。它是一个基于 C# 的启动程序,允许在主要的家庭影院媒体播放器(在我的例子中是 Plex、MediaPortal 和 Kodi)之间轻松切换,以便它们都可以用于各自的优点(Plex 用于下载内容,MediaPortal 用于电视录音和直播电视,以及其他所有内容的 Kodi,通常是流媒体)。
这些应用程序使用 pssuspend 暂停,这意味着它们可以同时保持打开状态,这对于速度较慢的计算机非常有用。

用户按下一个按钮(在他们的遥控器上)切换回启动器以选择另一个应用程序。

我几乎处于可用版本,但我已经有一段时间了,我已经缩小了范围。

如果我的启动器切换到应用程序(使用下面提到的方法),我无法切换回我的启动器进程。

在以下情况下发生:

  • VisualStudio 未调试或“Visual Studio 托管进程”(进程的 vshost 版本)运行。
  • 键盘/远程输入已应用于正在切换到的应用程序
    • 即:如果我向下移动到切换到的应用程序的任何位置,我可以很好地返回启动器,但是一旦我按下应用程序中的任何其他内容,我就无法切换出去。
  • 从启动器切换到切换的应用程序,而不是切换到它。

在所有其他时间,一切都按预期工作。

要切换,我目前正在使用SwitchToThisWindow(IntPtr hWnd, bool fAltTab)(来自http://www.pinvoke.net/default.aspx/user32/SwitchToThisWindow.html)。我也使用过Microsoft.VisualBasic.Interaction.AppActivate(来自http://msdn.microsoft.com/en-us/library/x9784w8e(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1)。

这两个都有相同的结果。

我已经确认的事情与问题无关:

  • pssuspend:如果我在切换回启动器之前没有暂停应用程序就运行,也会发生同样的事情
  • 操作系统和计算机:我在 3 台计算机上出现同样的问题,我的 Windows 8 安装和两台 Windows 7 安装
  • 侦听器返回主屏幕:这是使用来自 EventGhost 的 UDP 广播并执行其他所有需要完成的操作,例如更新启动器上的界面,只是不切换到启动器
  • 在本地机器上编译:我最初认为这有帮助,但这只是因为上述情况。只要打开了 vshost 进程,在我的 Windows 8 机器上编译的版本就可以在 Windows 7 上正常工作。我没有在任何其他系统上尝试过。
    • 以管理员身份运行没有效果

不应该成为问题但应该注意以防万一的是,启动器的前端都使用 CefSharp(CEF 是 Chrome 浏览器的集成版本)。尽管在添加此问题之前就出现了问题。

我的潜在想法:

  • 由于 中提到的事情AppActivate,我意识到 UIPermission 级别可能很重要,但是手动将其设置为完全信任不会产生任何变化。
    我还在 VisualStudio 中意识到,“安全”的属性设置为使用“OneClick 安全”设置,并且在“这是一个完全信任的应用程序”选项上。这对我来说很有意义,因为调试器会给它这些提升的权限,但大概这应该在没有调试运行的情况下工作。

我的应用程序在上下文中切换的一些代码:

[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

static Process currentProcess = Process.GetCurrentProcess();  
public static void SwitchToApplication(Process toSwitchTo)
{
    SwitchProcess(toSwitchTo);
}

public static void SwitchToLauncher()
{
    FrontendBridge.GetInstance().Reset();
    SwitchProcess(Process.GetCurrentProcess());
    Taskbar.Hide();
}

private static void SwitchProcess(Process toSwitchTo)
{
    if (currentProcess == toSwitchTo)
        return;

    if (toSwitchTo.MainWindowHandle != IntPtr.Zero)
    {
        SwitchToThisWindow(toSwitchTo.MainWindowHandle,true);
    }
    currentProcess = toSwitchTo;
}

希望有人有一些想法或过去有过类似的问题。
如果您需要任何其他信息或源代码,请告诉我。

4

1 回答 1

1

所以我设法解决了这个问题。

事实证明,这个问题不是由于我的任何围绕这些 API 调用的代码,或者是被切换到它们自己的应用程序。

突破性的答案来自这里: http:
//www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo

这解释了如何在调试时允许设置前台窗口,但如果不调试,窗口必须是最后一个获得键盘输入的窗口,否则它将没有焦点。

解决方案是让代码保持 alt 键让窗口允许我的程序设置前景窗口,然后可以使用 SetForegroundWindow 或 SwitchToThisWindow (当切换到可能尚未打开的东西时,我有更好的结果)。

我在这里找到了一个使用此代码的示例:http:
//csharpapprentice.blogspot.co.nz/2013/03/ok-ok-its-c.html

于 2015-01-12T00:31:24.487 回答