Results 1 to 11 of 11

Thread: Sending Keys to a Process??

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Sending Keys to a Process??

    Hi,

    I have an external exe file that runs like a console aplication (CLI). It is started as a process and is embedded in a Panel on a form.

    I can type commands directly at its prompt, but I would also like to send it keystrokes from a button.

    Here is the code that starts it, embeds it into a Panel, removes its TitleBar, and positions and sizes it to the size of the Panel.

    Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
            Dim p As New System.Diagnostics.ProcessStartInfo 
            p.FileName = "C:\Program Files\Console2\Console.exe" 
            proc.StartInfo = p 
            proc.Start() 
            proc.WaitForInputIdle() 
            SetParent(proc.MainWindowHandle, Panel1.Handle) 
            SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0) 
            InitialStyle = GetWindowLong(proc.MainWindowHandle, GWL_STYLE) 
            SetWindowLong(proc.MainWindowHandle, -16, InitialStyle And Not WS_DLGFRAME) 
            MoveWindow(proc.MainWindowHandle, Panel1.Left, Panel1.Top, Panel1.Width, Panel1.Height, True) 
        End Sub

    I wondered if SendKeys would work, but the documentation says it should be sent to the 'active window', but there I get confused, as my exe is a process, and I do not know if the Panel it is embedded into is the 'window' referred to, or the proc.MainWindowHandle, and I do not know whether it is active or not.

    How should I go about this?

    Edit: Just tried this, but I get an error at the AppActivate line: Process '{0}' was not found, even though the MessageBox correctly reports that the Window Title of the process is "Console".

    Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
            Dim p As New System.Diagnostics.ProcessStartInfo 
            p.FileName = "C:\Program Files\Console2\Console.exe" 
            pproc.StartInfo = p 
            proc.Start() 
            proc.WaitForInputIdle() 
            SetParent(proc.MainWindowHandle, Panel1.Handle) 
            SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0) 
            InitialStyle = GetWindowLong(proc.MainWindowHandle, GWL_STYLE) 
            SetWindowLong(proc.MainWindowHandle, -16, InitialStyle And Not WS_DLGFRAME) 
            MoveWindow(proc.MainWindowHandle, Panel1.Left, Panel1.Top, Panel1.Width, Panel1.Height, True) 
            MsgBox(proc.MainWindowTitle) 
            AppActivate(proc.MainWindowTitle) 
            SendKeys.SendWait("dir" & "{Enter}") 
        End Sub
    Any ideas?

    TIA

    Rock

  2. #2
    Hyperactive Member Runesmith's Avatar
    Join Date
    Oct 2008
    Posts
    399

    Re: Sending Keys to a Process??

    I found the following remark in the Visual Studio help for AppActivate:
    "You can use AppActivate only with processes that own windows. Most console applications do not own windows, which means that they do not appear in the list of processes that AppActivate searches. When running from a console application, the system creates a separate process to run the application and returns the output to the console process. Consequently, when you request the current process ID, you get the process ID of this separate process, rather than the console application's process ID."
    Runesmith

    The key to getting the right answer is asking the right question

    I just realized: good health is merely the slowest possible rate at which one can die

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Re: Sending Keys to a Process??

    Quote Originally Posted by Runesmith
    I found the following remark in the Visual Studio help for AppActivate:
    "You can use AppActivate only with processes that own windows. Most console applications do not own windows, which means that they do not appear in the list of processes that AppActivate searches. When running from a console application, the system creates a separate process to run the application and returns the output to the console process. Consequently, when you request the current process ID, you get the process ID of this separate process, rather than the console application's process ID."
    Thank you so much for that Runesmith. That explains a lot. I found lots of similar posts about AppActivate errors in other forums, and no answer to any of them. Well done. This will save me heading down the wrong path.

    I may abandon SendKeys then (as I cant think how I can overcome the 'active window' problem), and look at the SendMessage or StreamWriter alternatives instead.

    SendMessage also seems to have issues, accroding to several posts I have seen in other forums, so I will look first at StreamWriter (temporarily redirecting input, sending a message via StreamWriter, then restoring normal input).

    Anyone got any experience of successfully sending a command, such as dir<Enter> to a cmd console, using either the SendMessage API, or by redirection and using StreamWriter?

    Rock

  4. #4
    PowerPoster 2.0 Negative0's Avatar
    Join Date
    Jun 2000
    Location
    Southeastern MI
    Posts
    4,367

    Re: Sending Keys to a Process??

    Could you use the SetForegroundWindow API with the MainWindowHandle of the process? Then I think SendKeys would work.

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Re: Sending Keys to a Process??

    Quote Originally Posted by Negative0
    Could you use the SetForegroundWindow API with the MainWindowHandle of the process? Then I think SendKeys would work.
    Many thanks Negative0, SetForegroundWindow did enable SendKeys to work. However, it did develop a bad case of the stutter, even with a couple of pauses thrown in, as this screenshot shows.

    Any idea why the stuttering occurs?

    Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim p As New System.Diagnostics.ProcessStartInfo
            p.FileName = "C:\Program Files\Console2\Console.exe"
            proc.StartInfo = p
            proc.Start()
            proc.WaitForInputIdle()
            SetParent(proc.MainWindowHandle, Panel1.Handle)
            SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0)
            InitialStyle = GetWindowLong(proc.MainWindowHandle, GWL_STYLE)
            SetWindowLong(proc.MainWindowHandle, -16, InitialStyle And Not WS_DLGFRAME)
            MoveWindow(proc.MainWindowHandle, Panel1.Left, Panel1.Top, Panel1.Width, Panel1.Height, True)
            SetForegroundWindow(proc.MainWindowHandle)
            System.Threading.Thread.Sleep(1000)
            SendKeys.Send("dir")
            System.Threading.Thread.Sleep(1000)
            SendKeys.Send("{Enter}")
        End Sub
    Thanks again,

    Rock

  6. #6
    PowerPoster 2.0 Negative0's Avatar
    Join Date
    Jun 2000
    Location
    Southeastern MI
    Posts
    4,367

    Re: Sending Keys to a Process??

    Try using SendWait instead to see if that helps.

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Re: Sending Keys to a Process??

    Quote Originally Posted by Negative0
    Try using SendWait instead to see if that helps.
    I was just about to Edit my post to say that I had also tried SendWait with no change, but you got there ahead of me!

    Rock

  8. #8
    PowerPoster 2.0 Negative0's Avatar
    Join Date
    Jun 2000
    Location
    Southeastern MI
    Posts
    4,367

    Re: Sending Keys to a Process??

    What about sending 1 character at a time?

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Re: Sending Keys to a Process??

    Quote Originally Posted by Negative0
    What about sending 1 character at a time?
    One character also repeats. I started playing with different sleep values, when I finally got up to 9 seconds (!!!) it behaved and the dir command executed.

    Code:
    SetForegroundWindow(proc.MainWindowHandle)
    System.Threading.Thread.Sleep(9000)
    SendKeys.SendWait("dir")
    SendKeys.SendWait("{Enter}")
    A Google for 'SendKeys' and 'Repeated' brought up posts on other forums from as far back as 2005 showing the same repetition as in my screenshot, and none had an answer

    Rock

  10. #10

    Thread Starter
    Junior Member
    Join Date
    Jan 2009
    Posts
    31

    Re: Sending Keys to a Process??

    Having learnt a lot now about the vagaries of SendKeys, its unreliability, its lack of cohesion across platforms, and its dangers, I have decided to abandon this approach.

    However, with what should I replace it?

    Just to recap, I am embedding a cmd console window inside a panel, positioning and resizing it to the dimensions of the Panel, and I want to be able to both type commands at the prompt AND be able to click buttons on my form that will send it various commands.

    So, if SendKeys is not the answer, how about:

    a) SendInput
    b) StreamWriter
    c) SendMessage
    d) None of the above

    I would welcome suggestions/advice on which is the best method to send text commands to a cmd window.

    TIA

    Rock

  11. #11
    PowerPoster 2.0 Negative0's Avatar
    Join Date
    Jun 2000
    Location
    Southeastern MI
    Posts
    4,367

    Re: Sending Keys to a Process??

    If you are trying to use the command line, then I would start with RedirectStandardInput/Output.

    It looks like you have replied on this thread, but it is a good starting point:
    http://www.vbforums.com/showthread.p...hlight=Console

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width