-2

I created a simple autoclicker in C# VIsual Studio 2019 and when I open it and then close it with the red X in the top right it remains in background(I can see it in task manager). I tried to make a button with the code:

private void button2_Click(object sender, EventArgs e)
{
    Application.Exit();
}

but it still doesn't work. Any help?

Here is the full code:

public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    static extern short GetAsyncKeyState(Keys vKey);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

    private const int LEFTUP = 0x0004;
    private const int LEFTDOWN = 0x0002;
    public int intervals = 100;
    public bool Click = false;
    public int parsedValue;
    
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        CheckForIllegalCrossThreadCalls = false;
        Thread AC = new Thread(AutoClick);
        backgroundWorker1.RunWorkerAsync();
        AC.Start();
    }

    private void AutoClick()
    {
        while (true)
        {
            if(Click == true)
            {
                mouse_event(dwFlags: LEFTUP, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
                Thread.Sleep(1);
                mouse_event(dwFlags: LEFTDOWN, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
                Thread.Sleep(intervals);
            }
            Thread.Sleep(2);
        }
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            if (checkBox1.Checked)
            {
                if(GetAsyncKeyState(Keys.Down)< 0)
                {
                    Click = false;
                }
                else if(GetAsyncKeyState(Keys.Up)< 0)
                {
                    Click = true;
                }
                
                Thread.Sleep(1);
            }
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if(!int.TryParse(textBox1.Text, out parsedValue))
        {
            MessageBox.Show("Enter a number");
            return;
        }
        else
        {
            intervals = int.Parse(textBox1.Text);
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }
}
Gigel
  • 1
  • 1
  • Stop whatever long-running task is running in your application before closing it. What long-running tasks do you have? – ProgrammingLlama Jun 01 '21 at 07:58
  • 1
    Does this answer your question? [Application.Exit](https://stackoverflow.com/questions/1057151/application-exit) – Klaus Gütter Jun 01 '21 at 08:00
  • it means you are doing something to stop the windows message pumps which means the application can't process the exit event – Keith Nicholas Jun 01 '21 at 08:00
  • my guess is you have some while(true) somewhere that is holding everything alive – Keith Nicholas Jun 01 '21 at 08:01
  • More radical: https://learn.microsoft.com/dotnet/api/system.environment.exit. But do you use multithreading or do you have an open form, main or other, that is prohibited from closing? –  Jun 01 '21 at 08:09
  • Properly close and exit the application instead of trying the `Application.Exit` shortcut. For starters, ensure all background tasks complete or stop. If you're on the main form, call `Close`. We can't guess what the application does, or why it's blocked, without any code – Panagiotis Kanavos Jun 01 '21 at 08:14
  • 1
    `CheckForIllegalCrossThreadCalls = false;` You shouldn't do this. See [Is it safe just to set CheckForIllegalCrossThreadCalls to false to avoid cross threading errors during debugging?](https://stackoverflow.com/q/13345091/719186) – LarsTech Jun 02 '21 at 15:10

1 Answers1

1

In your code the major reason of not closing properly is that you have running threads in background which you are not stopping before exiting, apply the following changes to make it close strictly

  • Either make the threads realize application is stopping (difficult but efficient approach)
  • Tell threads to terminate automatically when app exits (easy approach)
  • Force every thing to close immediately when app exits (easy but not recommended, cruel approach)

For First Approach to work use a flag instead of hardcoded true in infinite loops e.g.

private void AutoClick()
{
            
    while (!this.isExiting) //set this variable to true before calling Application.Exit()
    {
         if(Click == true)
         {
            mouse_event(dwFlags: LEFTUP, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
            Thread.Sleep(1);
            mouse_event(dwFlags: LEFTDOWN, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
            Thread.Sleep(intervals);
          }
          Thread.Sleep(2);
    }
}

For second approach to work set the IsBackground property of the thread to true so that it will stop automatically on app exit e.g.

private void Form1_Load(object sender, EventArgs e)
{
     CheckForIllegalCrossThreadCalls = false;
     Thread AC = new Thread(AutoClick);
     AC.IsBackground = true; //this will let thread close automatically on app exit
     AC.Start();
     backgroundWorker1.RunWorkerAsync();
}

For third approach to work just call Environment.Exit(Environment.ExitCode); instead of Application.Exit() e.g.

private void button2_Click(object sender, EventArgs e)
{
     //Application.Exit(); do not use this
     Environment.Exit(Environment.ExitCode); //this will forcely close everything started by your app
}
Zain Ul Abidin
  • 2,467
  • 1
  • 17
  • 29