VBA SendKeys and Remote Desktop Connection

Hello all,

I have checked various places online with everyone saying sendkeys does not play nicely with Remote Desktop Connection.  However, I just feel there must be some workaround out there.  So my question is:

Is it possible to simply enter the following text "hello world" using VBA excel into a notepad file that is open within the remote desktop connection.

I dont mind having the remote desktop in a window and I don't mind alt and tabbing but at present whenever I try sendkeys it just closes the remote desktop connection.  The code i was trying is as below:

    Application.SendKeys ("%{TAB 3}"), True
    Application.Wait Now + TimeValue("00:00:02")
    Application.SendKeys ("Hello World"), True

Any help woule be greatly appreciated.

Many thanks.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

As you may have suspected, VBA Sendkeys won't work with the latest version of RDP.  Not sure which earlier version works.  The reason I know this is I was working on the same problem, recently.  If you write a sendkeys app in VB6, I believe you can get that to work.

Here's a link which might work for both of us (I had put my problem on hold till I had the time to get the VB6 app going):


While you can create a compiled program to sendkeys to RDP, I think the link I posted (and from some other research) you can send keys via the API.  I will attempt to do this for the both of us, but might take a while (re: other priorities).  I'll ask to see if other E-E experts I know can help as well.

Canders_12Author Commented:

I appreciate your comments.  Any help you can give would be appreciated :)
Introduction to Web Design

Develop a strong foundation and understanding of web design by learning HTML, CSS, and additional tools to help you develop your own website.

Canders_12Author Commented:
Oh dear, link didn't work :(
Try again. I did it just now from my blackberry

You can also go to the solutions tab above and search on sendkeys remote desktop to find it that way

SendKeys doesn't work? Not surprising. SendKeys is a very unstable method and so people consider it bad programming practice anyway.
The 'Right' way to do it is to use Windows API commands. Two important ones are FindWindow and SendMessage.
First, you need to connect to the API so you can use the functions. Put these lines in a module and then you can use the functions anywhere in your project (the module or sheet/workbook code).

Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long

Open in new window

FindWindow finds open windows based on their class or name. Name is easier. Use it like this:
Dim hwnd As Long
hwnd = FindWindow(vbNullString, "Untitled - Notepad") 'vbNullString is a built in variable. No need to declare it.

Open in new window

If hwnd comes back as a 0, it means it didn't find the window.
Then you can send commands to the window, for example:
Dim WM_CLOSE As Long
SendMessage hwnd, WM_CLOSE, 0, 0&

Open in new window

Without knowing exactly what you are trying to do, it's hard to give any more detail. Most likely those functions will do what you want and it will work in remote desktop and will make you look like a seasoned programmer. Also look up PostMessage to round out the lesson.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Canders_12Author Commented:
Sorry, was a bit poorly yesterday so had a day out. Then just checked to see a flurry of activity :) will have a play and feedback :)
I agree with TommySzalapski - if you can do it without SendKeys, that's fantastic.  I'd like to be educated as well how to send user id/password to initiate an RDP session without sendkeys.

Here's a link to a website that documents Windows API functions:  http://allapi.mentalis.org/apilist/p.shtml

In the meantime, I was able to get the code provided here:  SendAKey() and SendString() to work against Remote Desktop - and logon to an RDP session.  This was something I could not do with scripted SendKeys: http://www.xtremevbtalk.com/showthread.php?t=293802

This code uses the API to simulate keyboard keypresses so bypasses any restrictions RDP has for scripted SendKeys.

First, you need to start an RDP session, I used the Shell command to do that, and I used TommySzalapski's code, adding:

    'set this window to the foreground
    hWnd = SetForegroundWindow(hWnd)

to get the RDP session as the foreground session (as opposed to appactivate).  Then, I sent a password and vbCr to it to log in, using SendAKey() in a loop to send that.

So, my code looks something like this:

Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
Public mvarDestination As Long 'local copy
Public Const KEYEVENTF_KEYUP = &H2
Public Const VK_SHIFT = &H10
Public Declare Function OemKeyScan Lib "user32" (ByVal wOemChar As Integer) As Long
Public Declare Function CharToOem Lib "user32" Alias "CharToOemA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Public Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" (ByVal cChar As Byte) As Integer
Public Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long
Public Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

Private Sub SetKeyState(ByVal Key As Long, ByVal State As Boolean)
  Call keybd_event(Key, MapVirtualKey(Key, 0), KEYEVENTF_EXTENDEDKEY Or 0, 0)
    Call keybd_event(Key, MapVirtualKey(Key, 0), KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
End Sub
Sub TestStartupAndLogin()
Dim hWnd As Long
Dim myAppID As Long

    hWnd = FindWindow(vbNullString, "Remote Desktop Connection")
    If hWnd = 0 Then
        myAppID = Shell("C:\Windows\System32\mstsc.exe /v:BaseNameofSession", vbMaximizedFocus) 'needs to be a name it can recognize
    End If
    'set this window to the foreground
    hWnd = SetForegroundWindow(hWnd)

    'call the SendKey-function with a string of text, byte by byte

    mymsg = Range("A1").Value
    newhour = Hour(Now())
    newminute = Minute(Now())
    newsecond = Second(Now()) + 5
    waittime = TimeSerial(newhour, newminute, newsecond)
    Application.Wait waittime
    For i = 1 To Len(mymsg)
        SendAKey Mid(mymsg, i, 1)
        Debug.Print Asc(Mid(mymsg, i, 1))
    Next i
    SendAKey vbCr
    'SendMessage hWnd, WM_CLOSE, 0, 0& 'closes out the application
End Sub

Public Sub SendAKey(ByVal keys As String)
Dim vk%
Dim shiftscan%
Dim scan%
Dim oemchar$
Dim dl&
Dim shiftkey%
' Get the virtual key code for this char
' acter
vk% = VkKeyScan(Asc(keys)) And &HFF
' See if shift key needs to be pressed
shiftkey% = VkKeyScan(Asc(keys)) And 256
oemchar$ = " " ' 2 character buffer
' Get the OEM character - preinitialize
' the buffer
CharToOem Left$(keys, 1), oemchar$
' Get the scan code for this key
scan% = OemKeyScan(Asc(oemchar$)) And &HFF
' Send the key down
If shiftkey% = 256 Then
'if shift key needs to be pressed
shiftscan% = MapVirtualKey(VK_SHIFT, 0)
'press down the shift key
keybd_event VK_SHIFT, shiftscan%, 0, 0
End If
'press key to be sent
keybd_event vk%, scan%, 0, 0
' Send the key up
If shiftkey% = 256 Then
'keyup for shift key
keybd_event VK_SHIFT, shiftscan%, KEYEVENTF_KEYUP, 0
End If

'keyup for key sent
keybd_event vk%, scan%, KEYEVENTF_KEYUP, 0
End Sub
Public Sub SendString(ByVal keys As String)
Dim x&, t As Integer
'loop thru string to send one key at a t
' ime
For x& = 1 To Len(keys)
'activate target application
'AppActivate (mvarDestination)
'send one key to target
SendAKey Mid$(keys, x&, 1)
Next x&
End Sub

Open in new window

Now, apparently Postmessage can do the same thing (or better) as Sendkeys - http://www.xtremevbtalk.com/archive/index.php/t-120500.html.  I also note there is SendMessage, etc., see:  http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_26550754.html

Which is the most appropriate to use?  

TommySzalapski - Do you have an opinion on which is better, or does it really depend on application?

I'll post back later tonite (hopefully) with my testing of PostMessage for RDP logon.  If it can be used for that it can probably be used for anything in the RDP session.

If PostMessage (or its "sister" routines like SendMessage) works for this, then please be sure to give 100% of the points to TommySzalapski, because that would be a much better solution than the "weak" SendKeys command, or SendAKey which essentially does the same thing.

As usual, thanks TommySzalapski, for the lesson!

Unlike the "SendAKey" method I built with the example above, using this post:  http://www.xtremevbtalk.com/showthread.php?t=293802, I could not get this:  http://www.xtremevbtalk.com/archive/index.php/t-120500.html example to work with RDP, though I was able to emulate the keys sent via PostMessage to Microsoft Outlook.

The reason SendKeys etc. is bad is mainly because you have no way of specifying who gets the keypresses. If Google Talk or something steals focus, then it gets the keys. There are ways to turn off focus stealing, but also, SendKeys fails if the application is waiting for something else to finish and ignores your keys. You have to introduce wait intervals (which you must guess at the length of) before you send additional keys.
The SendMessage and PostMessage commands actually add commands to the message queues of the processes so it doesn't matter if it's busy or lost focus, it will still work. That is why those are better. I haven't used them much and never for Remote Desktop, but I thought I'd throw that out there to give direction.
In my opinion, if you are just writing a short script for personal use, use whatever is quick and easy. But if this is part of a larger project or could ever be sent to a client, then do it the right way.
Of course, even in the first case, if you have time to learn a better way, then it will usually save headaches in the long run. I've started using good code practices even for short scripts because if I don't, invariably I'll come back to the script in a year or so to add a feature and will have trouble figuring out what I did.
Let me recommend a tool to help with any of this.
Winspector Spy (like Spy++ but supposedly better) tells you lots of information about all the open windows and processes on your system. You can use this to post and send messages to individual controls in a window (don't just send the keypresses to the "Remote Desktop Connection" window, send them straight to the edit control). It will also show you what messages you are sending when you click on things (almost like Excel's 'record macro' but for the Windows API).
If you want to do much Windows API stuff, this is a good tool to learn to use.
Canders_12Author Commented:

how do I distribute points?

Some great responses.  Thank you everyone.
There's only two of us.
:)  For what its worth, here's one more:


A link to a site where the guy built a class module around SendKeys.  I tested it and it works.  You can drop it in and use SendKeys and it does the work underneath the covers via keyboard API calls.

PS - I'm still trying to get SendMessage to work with Remote Desktop to no avail - can't seem to get a "handle" on the textbox as yet.

I'll take a look at Winspector.  For login, anyway, Send and/or Post Message doesn't work via Edit control, for some reason.

Canders_12Author Commented:
I know, people happy with 50.50 split?
Yep. Sounds fair.
Canders_12Author Commented:
Greatly appreciated to you both.
Anshuman PandaCommented:
I want help in sending commands like TAB, Enter, Down Arrow to remote login page. It's possible in local machine using SendKeys but I am unable to do this in a remote login page. After the remote login page appears, I can pass my username to the username field which is highlighted. I want to transfer the focus to password field by sending TAB or Down Arrow key command to the remote login page.

Can anybody help please? I am trying this since hours today.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Excel

From novice to tech pro — start learning today.