编程式 RDP 登录和发送消息

发布于 2024-09-07 06:56:38 字数 2247 浏览 3 评论 0原文

我需要以编程方式 RDP 到虚拟机(XP SP3 / .NET3.5 / VS 2008)(凭据已保存在 .rdp 文件中)并进行 UI 自动化测试。由于我们的域安全性,我需要以编程方式对交互式登录回答“确定”。登录后,我可以访问其他对话窗口和发送消息到按钮等,但我无法让我的发送消息在这个初始屏幕上工作。我使用间谍++来捕获当我按回车键时实际发送的内容,并且当我在运行程序时查看间谍++日志中的响应时,我似乎能够复制这些消息,但无论我在消息中使用什么变体,都不会发生任何情况。 我想知道是否可以通过编程方式执行此操作,或者操作系统是否由于安全问题而阻止这种自动化?

当我按下回车按钮时(在初始屏幕上似乎任何键都可以),我在间谍++中看到的消息我看到:

WM_KEYDOWN nVirtKey:00FF cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 Up:0
WM_KEYUP   nVirtKey:00FF cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 Up:1

当我执行下面的代码并观看发送到 IHWindowClass(下面的 hwnd6)的消息时,我看到我生成了上面的内容向该窗口发送消息。任何帮助将不胜感激!

以下是代码的相关部分:

'UIntPtr ip = new UIntPtr(0x0D); //ENTER
UIntPtr ip2 = new UIntPtr(0xFF); //00FF
UIntPtr kyDwnlParam = new UIntPtr(0x001);
UIntPtr kyUplParam = new UIntPtr(0xc0000001);

// used UISpy to get these class names...
string lpszParentClass = "TscShellContainerClass";
string lpszParentWindow = "test2 - test2 - Remote Desktop Connection";
string lpszClass2 = "TscShellAxHostClass";
string lpszClass3 = "ATL:2D33D580";
string lpszClass4 = "UIMainClass";
string lpszClass5 = "UIContainerClass";
string lpszClass6 = "IHWindowClass";


hWnd2 = FindWindowEx(ParenthWnd, IntPtr.Zero, lpszClass2, IntPtr.Zero);
hWnd3 = FindWindowEx(hWnd2, IntPtr.Zero, lpszClass3, IntPtr.Zero);
hWnd4 = FindWindowEx(hWnd3, IntPtr.Zero, lpszClass4, IntPtr.Zero);
hWnd5 = FindWindowEx(hWnd4, IntPtr.Zero, lpszClass5, IntPtr.Zero);
hWnd6 = FindWindowEx(hWnd5, IntPtr.Zero, lpszClass6, IntPtr.Zero);

string hexValue = hWnd6.ToString("X"); //Convert to hex to use find in spy++

SetForegroundWindow(hWnd6); // for good measure....

// tried this....

SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYDOWN, ip2, kyDwnlParam);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYUP, ip2, kyUplParam);

// tried this....

SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYDOWN, ip, kyDwnlParam);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYUP, ip, kyUplParam);

// tried this...
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_CHAR, ip, UIntPtr.Zero);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_CHAR, ip, UIntPtr.Zero);'

I have the need to programmatically RDP to a virtual machine(XP SP3 / .NET3.5 / VS 2008), (credentials have been saved in .rdp file) and do UI automation testing. Because of our domain security, I need to programmatically answer 'ok' to the interactive logon. I am able to access other dialogue Windows and SendMessages to buttons, etc, after login, but I have not been able to get my SendMessage to work on this initial screen. I used spy++ to capture what actually gets sent when I press enter and I seem to be able to duplicate those messages as I view the response in the spy++ log as I run my program, but no matter what variant I use in the message nothing happens.
I would like to know if it is even possible to programmatically do this or does the OS prevent this kind of automation due to security issues?

The messages I see in spy++ when I hit the enter button( on that initial screen it seems any key will do) I see:

WM_KEYDOWN nVirtKey:00FF cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 Up:0
WM_KEYUP   nVirtKey:00FF cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 Up:1

When I exercise the code below and watch the messages sent to IHWindowClass(hwnd6 below) I see I generate the above messages to that window. Any help would be appreciated!

Here are the pertinent sections of the code:

'UIntPtr ip = new UIntPtr(0x0D); //ENTER
UIntPtr ip2 = new UIntPtr(0xFF); //00FF
UIntPtr kyDwnlParam = new UIntPtr(0x001);
UIntPtr kyUplParam = new UIntPtr(0xc0000001);

// used UISpy to get these class names...
string lpszParentClass = "TscShellContainerClass";
string lpszParentWindow = "test2 - test2 - Remote Desktop Connection";
string lpszClass2 = "TscShellAxHostClass";
string lpszClass3 = "ATL:2D33D580";
string lpszClass4 = "UIMainClass";
string lpszClass5 = "UIContainerClass";
string lpszClass6 = "IHWindowClass";


hWnd2 = FindWindowEx(ParenthWnd, IntPtr.Zero, lpszClass2, IntPtr.Zero);
hWnd3 = FindWindowEx(hWnd2, IntPtr.Zero, lpszClass3, IntPtr.Zero);
hWnd4 = FindWindowEx(hWnd3, IntPtr.Zero, lpszClass4, IntPtr.Zero);
hWnd5 = FindWindowEx(hWnd4, IntPtr.Zero, lpszClass5, IntPtr.Zero);
hWnd6 = FindWindowEx(hWnd5, IntPtr.Zero, lpszClass6, IntPtr.Zero);

string hexValue = hWnd6.ToString("X"); //Convert to hex to use find in spy++

SetForegroundWindow(hWnd6); // for good measure....

// tried this....

SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYDOWN, ip2, kyDwnlParam);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYUP, ip2, kyUplParam);

// tried this....

SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYDOWN, ip, kyDwnlParam);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_KEYUP, ip, kyUplParam);

// tried this...
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_CHAR, ip, UIntPtr.Zero);
SendMessage(hWnd6, (uint)WindowsUtilities.WindowsMessages.WM_CHAR, ip, UIntPtr.Zero);'

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

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

发布评论

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

评论(2

四叶草在未来唯美盛开 2024-09-14 06:56:38

您即将完成,您需要发送一些其他消息以使 RDP 会话准备好接受键盘输入。使用 Spy++,您应该会看到更多消息被发送。

我能够使用以下代码在记事本窗口中输入字母“a”(或者理论上 RDP 会话中的活动窗口是什么):

SendMessage(cWind, (int)WM.IME_SETCONTEXT, new UIntPtr(0x00000001), new UIntPtr(0xC000000F));
SendMessage(cWind, (int)WM.IME_NOTIFY, new IntPtr(0x00000002), new IntPtr(0x00000000));
Thread.Sleep(1);

SendMessage(cWind, (int)WM.SETFOCUS, new UIntPtr(0x00203794), new UIntPtr(0x00000000));
Thread.Sleep(1);
//Random keypress
SendMessage(cWind, (int)WM.KEYDOWN, new UIntPtr(0x000000FF), new UIntPtr(0x00000001));
SendMessage(cWind, (int)WM.KEYUP, new UIntPtr(0x00000041), new UIntPtr(0xC0000001));
Thread.Sleep(1);
//A key presses
SendMessage(cWind, (int)WM.KEYDOWN, new IntPtr(0x00000041), new IntPtr(0x001E0001));
SendMessage(cWind, (int)WM.KEYUP, new UIntPtr(0x00000041), new UIntPtr(0xC01E0001));

可能需要也可能不需要睡眠,但 Spy++ 显示调用返回所以我先等一会儿再继续。您可能还应该“撤消”setfocus/setcontext 操作,但对于我的需要来说,这做得很好。 (Spy++将透露详情)

You are nearly there, there are a couple of other messages that you need to send to get the RDP session ready to accept keyboard input. With Spy++ you should have seen some more messages being sent.

I was able to get the the letter 'a' entered into a notepad window (or in theory what ever the active window in the RDP session is) with the below code:

SendMessage(cWind, (int)WM.IME_SETCONTEXT, new UIntPtr(0x00000001), new UIntPtr(0xC000000F));
SendMessage(cWind, (int)WM.IME_NOTIFY, new IntPtr(0x00000002), new IntPtr(0x00000000));
Thread.Sleep(1);

SendMessage(cWind, (int)WM.SETFOCUS, new UIntPtr(0x00203794), new UIntPtr(0x00000000));
Thread.Sleep(1);
//Random keypress
SendMessage(cWind, (int)WM.KEYDOWN, new UIntPtr(0x000000FF), new UIntPtr(0x00000001));
SendMessage(cWind, (int)WM.KEYUP, new UIntPtr(0x00000041), new UIntPtr(0xC0000001));
Thread.Sleep(1);
//A key presses
SendMessage(cWind, (int)WM.KEYDOWN, new IntPtr(0x00000041), new IntPtr(0x001E0001));
SendMessage(cWind, (int)WM.KEYUP, new UIntPtr(0x00000041), new UIntPtr(0xC01E0001));

Sleeps may or may not be required, but Spy++ showed the calls returning so I wait briefly before continuing. You should probably also "undo" the setfocus/setcontext operations, but for my needs this did the job fine. (Spy++ will reveal the details)

墨小墨 2024-09-14 06:56:38

正如@Spike所说,您需要发送IME_SETCONTEXT和IME_NOTIFY。
我已经测试了代码,它获取输入,但是,即使我发送 VK_A - VK_Z,它也只发送字母“a”。

                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_IME_SETCONTEXT, 0x00000001, 0xc000000f);
                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_IME_NOTIFY, 0x00000002, 0x00000000);
                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_SETFOCUS, 0x00000000, 0x00000000);

在发送 VK_A(例如)之前,Winspector 还检测到 WM_KEYDOWN + WM_KEYUP 的未知值/键码为 255。我被困在这里,抱歉。
也许你会发现哪里出了问题。

As @Spike says , you need to send IME_SETCONTEXT and IME_NOTIFY.
I have tested the code , and it grabs the input , however , it only sends letter 'a', even if I send VK_A - VK_Z.

                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_IME_SETCONTEXT, 0x00000001, 0xc000000f);
                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_IME_NOTIFY, 0x00000002, 0x00000000);
                SendMessageKey.SimulateKey.SendMessage((IntPtr)hwnd, SendMessageKey.MessageCode.WM_SETFOCUS, 0x00000000, 0x00000000);

Before sending VK_A (for example) , Winspector also detects WM_KEYDOWN + WM_KEYUP with an unknown value/keycode of 255. I'm stuck here , I'm sorry.
Maybe you will find what's wrong.

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