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

时间:2010-10-01 17:10:11

标签: c# .net winforms winapi remoteapp

背景

我正在使用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。这个问题围绕着这个问题。

对于非托管代码告诉我哪些窗口mstsc.exe处于活动状态,我使用了Spy ++,但对于mstsc.exe,它返回了一个名为RAIL_WINDOW的不同类名:

alt text

以下是我用来查找子窗口的代码:

[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 个答案:

答案 0 :(得分:2)

知道微软如何做事,我敢打赌,“铁路窗口”只不过是一个愚蠢的本地代理,它不会回应SendKeys发送的内容。我没看过,但我敢打赌,最终发送WM_CHAR消息,哑代理可能不会打扰响应。相反,尝试手动发送WM_KEYUP和WM_KEYDOWN消息,看看是否有效,因为我希望它会传输那些和鼠标点击(而不是翻译版本)。

答案 1 :(得分:0)

您使用SendKeys()发送了哪些命令?

寻找替代解决方案而不是使用`SendKeys()'可能更好。

答案 2 :(得分:0)

您可以利用处理IMsTscAxEvents :: OnRemoteWindowDisplayed事件,在适当的时间为您提供正确的窗口句柄,而无需调用FindWindowEx等。