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

发布于 2024-09-25 21:59:52 字数 1869 浏览 10 评论 0原文

背景

我正在使用 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;
}

但是,我无法使用 < code>FindWindowEx 以同样的方式。这个问题就是围绕着这个展开的。

为了让非托管代码告诉我哪些 Windows 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. 是否有其他方法可以将键盘敲击发送到通过远程应用程序运行的应用程序?

Background

I'm using SendKeys() to send keyboard commands to the active window, but I'm not having any luck finding the child window when the application is running through RemoteApp. It all works as expected when I run the application locally.

Microsoft RemoteApp allows users to connect to applications through the RDP protocol, but instead of showing the entire remote Virtual machine, it just shows the application window. To the end user, there is no difference between an application running under RemoteApp and it running on their desktop.

I've been using ManagedSpy to determine the class name of the .NET application window so that I can use the Win32 API function FindWindowEx to make one of the child windows active, and it works well. However, I'm having a problem when the application is running over RemoteApp.

I can still use the .NET Process.GetProcessesByName() to find the application, I just have to have it invoke 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;
}

However, I can't use FindWindowEx in the same way. This question revolves around that.

For the unmanaged code to tell me what windows mstsc.exe has active, I used Spy++, but for mstsc.exe it comes back with a different class name, called RAIL_WINDOW:

alt text

Here is the code I'm using to find the Child 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);

Questions

  1. I can use Spy++ to highlight the active child window in the RemoteApp version of the application, and I get RAIL_WINDOW, but I cannot seem to access this window programmatically. Given the code above, what am I missing to be able to do so?

  2. Are there other ways of sending keyboard strokes to an application running over Remote App?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

明媚如初 2024-10-02 21:59:52

了解 Microsoft 的做法后,我敢打赌“铁路窗口”只不过是一个愚蠢的本地代理,它不会响应 SendKeys 发送的内容。我没有看过,但我敢打赌最终会发送 WM_CHAR 消息,而愚蠢的代理可能不会费心响应。相反,尝试手动向其发送 WM_KEYUP 和 WM_KEYDOWN 消息,看看是否有效,因为我希望它会传输这些消息和鼠标点击(以及其他)而不是翻译后的版本。

Knowing how Microsoft does things, I'll bet the "rail window" is nothing more than a dumb, local proxy that doesn't bother responding to what SendKeys is sending. I haven't looked, but I'll bet that ends up sending WM_CHAR messages, to which a dumb proxy probably wouldn't bother responding. Instead, try sending it WM_KEYUP and WM_KEYDOWN messages manually and see if that works, given that I expect it would transmit those and mouse clicks (and what not) rather than the translated versions.

⒈起吃苦の倖褔 2024-10-02 21:59:52

您使用 SendKeys() 发送什么命令?

最好寻找替代解决方案而不是使用“SendKeys()”。

What commands are you sending using SendKeys()?

It may be better to look for an alternative solution instead of using `SendKeys()'.

極樂鬼 2024-10-02 21:59:52

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

And you can probably take advantage of handling IMsTscAxEvents::OnRemoteWindowDisplayed event that gives you the proper window handle at the right time without calling FindWindowEx, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文