以编程方式查找 Microsoft RemoteApp 内的子窗口
题
背景
我在用着 SendKeys()
将键盘命令发送到活动窗口,但当应用程序通过 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
以同样的方式。这个问题就是围绕着这个展开的。
对于非托管代码告诉我什么是windows mstsc.exe
已激活,我使用了 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);
问题
我可以使用 Spy++ 突出显示应用程序的 RemoteApp 版本中的活动子窗口,然后我得到
RAIL_WINDOW
, ,但我似乎无法以编程方式访问此窗口。鉴于上面的代码,我缺少什么才能做到这一点?是否有其他方法将键盘敲击发送到通过远程应用程序运行的应用程序?
解决方案
了解 Microsoft 的做法后,我敢打赌“铁路窗口”只不过是一个愚蠢的本地代理,它不会响应 SendKeys 发送的内容。我没有看过,但我敢打赌最终会发送 WM_CHAR 消息,而愚蠢的代理可能不会费心响应。相反,尝试手动向其发送 WM_KEYUP 和 WM_KEYDOWN 消息,看看是否有效,因为我希望它会传输这些和鼠标点击(以及其他)而不是翻译后的版本。
其他提示
您使用什么命令发送 SendKeys()
?
最好寻找替代解决方案而不是使用“SendKeys()”。
您也许可以利用处理 IMsTscAxEvents::远程窗口显示时 事件在正确的时间为您提供正确的窗口句柄,而无需调用 FindWindowEx 等。