以编程方式查找Microsoft RemoteApp中的子窗口

3

背景

我正在使用SendKeys()向活动窗口发送键盘命令,但在通过RemoteApp运行应用程序时,我无法找到子窗口。当我本地运行应用程序时,一切都按预期工作。

Microsoft RemoteApp允许用户通过RDP协议连接到应用程序,但它只显示应用程序窗口,而不是整个远程虚拟机。对于最终用户来说,在RemoteApp下运行的应用程序与在其桌面上运行的应用程序没有区别。

我一直在使用ManagedSpy确定.NET应用程序窗口的类名,以便我可以使用Win32 API函数FindWindowEx使其中一个子窗口处于活动状态,并且它工作得很好。然而,在应用程序通过RemoteApp运行时,我遇到了问题。

我仍然可以使用.NET Process.GetProcessesByName()查找应用程序,只需让它调用mstsc.exe

IntPtr hwndChild = IntPtr.Zero;
Process[] processess = Process.GetProcessesByName("mstsc");
IntPtr appHandle = IntPtr.Zero;

foreach (Process p in processess)
{
    if ((p.MainWindowHandle != IntPtr.Zero))
    {
        appHandle = p.MainWindowHandle;
    }
}

if (appHandle == IntPtr.Zero)
{
    MessageBox.Show("Application is not Running.");
    return;
}

然而,我无法以同样的方式使用FindWindowEx。这个问题围绕着它。
为了让非托管代码告诉我哪些窗口是活动的,我使用了Spy++,但是对于mstsc.exe,它返回了一个不同的类名,称为RAIL_WINDOW
以下是我用来查找子窗口的代码:
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
hwndChild = FindWindowEx(appHandle, IntPtr.Zero, "RAIL_WINDOW", "MyApplication (Remote)");
SetForegroundWindow(hwndChild);

问题

  1. 我可以使用Spy++在RemoteApp版本的应用程序中突出显示活动子窗口,并获得RAIL_WINDOW,但似乎无法通过编程方式访问此窗口。根据上面的代码,我错过了什么才能够这样做?

  2. 还有其他方法可以将键盘按键发送到在Remote App上运行的应用程序吗?

3个回答

2

了解微软的做法,我敢打赌“铁路窗口”只是一个愚蠢的本地代理,不会回应SendKeys发送的内容。虽然我没有查看,但我敢打赌它最终会发送WM_CHAR消息,对于这些消息,一个愚蠢的代理可能不会回应。相反,尝试手动发送WM_KEYUP和WM_KEYDOWN消息,看看是否有效,因为我预计它将传输这些消息以及鼠标点击(等等),而不是翻译版本。


1
Microsoft文档:“某些类别的用户输入不会直接作为键盘或鼠标输入被RAIL窗口/图标接收。例如,右键单击窗口任务栏图标;组合键以最小化、最大化或还原所有窗口;以及所有与通知图标的用户交互。这些交互作为非键盘或非鼠标消息发布到RAIL窗口/图标,因此不能通过核心RDP通道发送。客户端将这些交互作为RAIL虚拟通道消息发送到服务器。” https://msdn.microsoft.com/en-us/library/cc242508.aspx - George Stocker
看起来你是对的;似乎没有办法做到这一点。 - George Stocker

0

你正在使用 SendKeys() 发送哪些命令?

最好寻找替代方案,而不是使用 `SendKeys()'。


我正在发送键盘命令。除了Sendkeys,还有什么其他方法可以编程方式向活动窗口发送键盘命令? - George Stocker

0
而且你可能可以利用处理IMsTscAxEvents::OnRemoteWindowDisplayed事件,以便在适当的时间获得正确的窗口句柄,而无需调用FindWindowEx等函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接