2010-06-22 4 views
3

У меня есть необходимость программно RDP для виртуальной машины (XP SP3/.NET3.5/VS 2008), (учетные данные были сохранены в файле .rdp) и выполнить тестирование автоматизации пользовательского интерфейса. Из-за нашей безопасности домена мне нужно программно ответить «ok» на интерактивный вход в систему. Я могу получить доступ к другим диалоговым окнам Windows и SendMessages к кнопкам и т. Д. После входа в систему, но мне не удалось заставить мой SendMessage работать на этом начальном экране. Я использовал spy ++ для захвата того, что действительно отправляется, когда я нажимаю кнопку ввода, и я, кажется, могу дублировать эти сообщения, когда я просматриваю ответ в журнале spy ++ при запуске моей программы, но независимо от того, какой вариант я использую в сообщении, ничего не происходит , Я хотел бы знать, возможно ли вообще программно это сделать или ОС предотвращает такую ​​автоматизацию из-за проблем с безопасностью?Programmatic RDP Login и SendMessage

Сообщения, которые я вижу в Spy ++, когда я нажал на кнопку ввода (на этом начальном экране, кажется, любой ключ будет делать) Я вижу:

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);' 

ответ

0

Вы почти там, есть несколько других сообщений, которые необходимо отправить, чтобы получить сеанс RDP готов принять ввод с клавиатуры. С Spy ++ вы должны были увидеть еще несколько отправляемых сообщений.

Я был в состоянии получить букву «а» вводится в окно блокнота (или в теории, что когда-либо активное окно в 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 ++ покажет подробности)

0

Как @Spike говорит, вам нужно отправить IME_SETCONTEXT и IME_NOTIFY. Я протестировал код, и он захватывает ввод, однако он отправляет только букву «а», даже если я отправляю 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); 

Перед отправкой VK_A (к примеру), Winspector также обнаруживает WM_KEYDOWN + WM_KEYUP с неизвестным значением/клавиатурным 255. Я здесь застрял, мне очень жаль. Возможно, вы обнаружите, что не так.