locked
Sending Keyboard keys, and ending a loop abrubtly. RRS feed

  • Question

  • Greetings! i'm a noob when it comes to C#; however, I have alot of experience with Java. So what i'm trying to do as a simple practice job is send the ENTER key and the UP key in a certain order and loop 100 times. And by doing so i'm trying to get it to focus on an another application such as Notepad. Now i can send the keys in Notepad and that works; however, when i try to send them in other applications it doesn't work Plus the way i wrote it makes it crash alot. Does anyone have any suggesstions? here's the code: I wrote it in Visual C# 2005

    namespace WindowsApplication2 
        public partial class Form1 : Form 
        { 
            public Form1() 
            { 
                InitializeComponent(); 
            } 
            
            private void button1_Click(object sender, System.EventArgs e) 
            { 
            
     
             
                    for (int i = 0; i < 100; i++) 
                    { 
                        System.Threading.Thread.Sleep(7000); 
                        SendKeys.SendWait("{ENTER}"); 
                        System.Threading.Thread.Sleep(2000); 
                        SendKeys.SendWait("{ENTER}"); 
                        System.Threading.Thread.Sleep(2000); 
                        SendKeys.SendWait("{UP}"); 
                        System.Threading.Thread.Sleep(1000); 
                        SendKeys.SendWait("{ENTER}"); 
                        System.Threading.Thread.Sleep(7000); 
                        SendKeys.SendWait("{ENTER}"); 
     
                    } 

            } 
            private void button2_Click(object sender, EventArgs e) 
            { 
                this.Close(); 
            } 
     
        } 

    • Moved by Peter Ritchie Thursday, June 19, 2008 8:37 PM off-topic
    Monday, June 16, 2008 6:45 AM

Answers

  • Um...No.

    Here is something that I think is much simpler.  Use BackgroundWorker.  Just drop the control on your form.  Then change the properties to allow cancel and report progress, then implement the events DoWork, ProgressChanged, RunWorkerCompleted.

    If SendKeys interacts with the GUI, you will get an error about a thread not having access.  But there are ways for the thread to provide that information to the main event loop thread.  I like using the ReportProgress method.

    Here's some example code to start with...
            private void button5_Click(object sender, EventArgs e)  
            {  
                backgroundWorker2.RunWorkerAsync();  
            }  
            private void button6_Click(object sender, EventArgs e)  
            {  
                backgroundWorker2.CancelAsync();  
            }  
     
            private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)  
            {  
                BackgroundWorker bw = sender as BackgroundWorker;  
     
                for (int i = 0; i < 100; i++)  
                {  
                    if (bw.CancellationPending)  
                        return;  
                    System.Threading.Thread.Sleep(7000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(2000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(2000);  
                    SendKeys.SendWait("{UP}");  
                    System.Threading.Thread.Sleep(1000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(7000);  
                    SendKeys.SendWait("{ENTER}");  
                    //use the ReportProgress feature if you like  
                    //bw.ReportProgress(i, i.ToString());  
                }  
            }  
     
            private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)  
            {  
                //txtPercentComplete.Text = e.ProgressPercentage;  
                //txtProgressString.Text = (string)e.UserState;  
            }  
     
            private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
            {  
                // Detect and report completion  
                if (e.Cancelled)  
                {  
                    // report  
                }  
            }  
     
    • Marked as answer by jack 321 Thursday, June 19, 2008 5:35 AM
    Monday, June 16, 2008 7:44 PM

All replies

  • When you call Sleep() in the main GUI, the thread can do nothing else.  This can be troublesome for the event loop.

    Use the Timer control instead.  The code becomes a little less transparent, but may be solve the crashing.  Another approach would be to use the BackgroundWorker component.  It take a very small learning curve to use the BackgroundWorker.  Using BackgroundWorker, your sendKey calls go to a different thread that does not interfere with the GUI.  The BackgroundWorker component is much easier to use (in my opinion) than the standard Thread tools.
    Monday, June 16, 2008 12:02 PM
  • ok I haven't been able to find much examples for what i'm looking for but this is what i came up with and it works with no crashing only wayyyyyy too fast haha takes 2-3 seconds to complete the program XD any suggestions?
    namespace WindowsApplication2 
        public partial class Form1 : Form 
        { 
            public Form1() 
            { 
                InitializeComponent(); 
            } 
            
            private void button1_Click(object sender, System.EventArgs e) 
            { 
     
               timer1.Enabled = true
     
               
            } 
            private void button2_Click(object sender, EventArgs e) 
            { 
                this.Close(); 
            } 
     
            private void button2_Click_1(object sender, EventArgs e) 
            { 
                timer1.Enabled = false
            } 
     
            private void timer1_Tick(object sender, EventArgs e) 
            { 
                           for (int i = 0; i < 100; i++) 
               { 
                   timer1.Interval = (7000); 
                   SendKeys.SendWait("{ENTER}"); 
                   timer1.Interval = (2000); 
                   SendKeys.SendWait("{ENTER}"); 
                   timer1.Interval = (2000); 
                   SendKeys.SendWait("{UP}"); 
                   timer1.Interval = (1000); 
                   SendKeys.SendWait("{ENTER}"); 
                   timer1.Interval = (7000); 
                   SendKeys.SendWait("{ENTER}"); 
     
               } 
            } 
     
        } 
    Monday, June 16, 2008 6:32 PM
  • Um...No.

    Here is something that I think is much simpler.  Use BackgroundWorker.  Just drop the control on your form.  Then change the properties to allow cancel and report progress, then implement the events DoWork, ProgressChanged, RunWorkerCompleted.

    If SendKeys interacts with the GUI, you will get an error about a thread not having access.  But there are ways for the thread to provide that information to the main event loop thread.  I like using the ReportProgress method.

    Here's some example code to start with...
            private void button5_Click(object sender, EventArgs e)  
            {  
                backgroundWorker2.RunWorkerAsync();  
            }  
            private void button6_Click(object sender, EventArgs e)  
            {  
                backgroundWorker2.CancelAsync();  
            }  
     
            private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)  
            {  
                BackgroundWorker bw = sender as BackgroundWorker;  
     
                for (int i = 0; i < 100; i++)  
                {  
                    if (bw.CancellationPending)  
                        return;  
                    System.Threading.Thread.Sleep(7000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(2000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(2000);  
                    SendKeys.SendWait("{UP}");  
                    System.Threading.Thread.Sleep(1000);  
                    SendKeys.SendWait("{ENTER}");  
                    System.Threading.Thread.Sleep(7000);  
                    SendKeys.SendWait("{ENTER}");  
                    //use the ReportProgress feature if you like  
                    //bw.ReportProgress(i, i.ToString());  
                }  
            }  
     
            private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)  
            {  
                //txtPercentComplete.Text = e.ProgressPercentage;  
                //txtProgressString.Text = (string)e.UserState;  
            }  
     
            private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
            {  
                // Detect and report completion  
                if (e.Cancelled)  
                {  
                    // report  
                }  
            }  
     
    • Marked as answer by jack 321 Thursday, June 19, 2008 5:35 AM
    Monday, June 16, 2008 7:44 PM
  •  For questions and discussions regarding client application development using Windows Forms controls and features, please see http://forums.microsoft.com/msdn/ShowForum.aspx?ForumID=8&SiteID=1

    http://www.peterRitchie.com/blog
    Thursday, June 19, 2008 8:35 PM