Hidden Form is keeping application open in the background and I can’t get rid of it

Basically I have two buttons on two forms, you click one of the buttons it hides the current form and displays the other form. The problem I have is that if a form is hidden, and I close the App with the “X” in the corner, the App still runs in the background. I’ve tried everything to get rid of it :’)

Code for Form1:

namespace Reg_Login
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            Form2 form2 = new Form2();
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            string relativePath = Path.Combine(baseDirectory, "Users.txt");
            StreamWriter writer = new StreamWriter(relativePath, append: true);

            writer.WriteLine(txtCreateUser.Text + "t" + txtCreatePass.Text);

            writer.Close();

            if (txtCreateUser.Text == "" && txtCreatePass.Text == "")
            {
                MessageBox.Show("Please enter something");
            }
            else
            {
                MessageBox.Show("Account Created");
                this.Hide();
                form2.Show();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            Form2 form2 = new Form2();
            this.Hide();
            form2.Show();
            form2.BringToFront();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }
    }
}

Code for Form2:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Reg_Login
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            string relativePath = Path.Combine(baseDirectory, "Users.txt");
            StreamReader reader = new StreamReader(relativePath);
            string lineRec = reader.ReadLine();
            string[] lineArray = new string[2];
            string userName = "";
            string Password = "";

            while (lineRec != null)
            {
                lineArray = lineRec.Split("t");
                userName = lineArray[0];
                Password = lineArray[1];

                if (txtUser.Text == userName && txtPass.Text == Password)
                {
                    MessageBox.Show("WORKS");
                    break;
                }

                lineRec = reader.ReadLine();
            }

            if (txtUser.Text != userName && txtPass.Text != Password)
            {
                MessageBox.Show("DOES NOT WORK");
            }

            reader.Close();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            Form2 form2 = new Form2();

            this.Hide();
            form1.Show();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }
    }
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    System.Windows.Forms.Application.Exit();
}

Should work but it’s not.

3

To make your app close properly, follow this general advice.

  • Make all child forms members of the MainForm class (in this case the main window is Form 1)
  • Whenever you Show() a child form, pass the this pointer of the parent window. This way the child window will always be on top and you won’t have to “BringToFront”.
  • Make sure to override the FormClosing event in any child form. If user is closing it, cancel the Close and Hide it instead. This way the native window handle doesn’t get disposed before you want it to.

Another change is that I added a handler that tracks the visibility of form 2 and makes form 1 visibility “the opposite of that”.


Some functionality has been shortened for clarity, but the aim here is to show the proper management of window Handle so that your app closes properly.


Form 1 (Main Window)

public partial class Form1 : Form
{
    internal static string UserPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Users.txt");

    /// <summary>
    /// The main window of the app.
    /// </summary>
    public Form1()
    {
        InitializeComponent();
        txtCreatePass.PasswordChar = '*';
#if false
        // A way to reset the file for debugging.
        if(File.Exists(UserPath)) File.Delete(UserPath);
#endif
        form2.VisibleChanged += (sender, e) =>
        {
            // Hide this for when form2 shows.
            if (form2.Visible) Hide();
            else
            {
                if (form2.DialogResult == DialogResult.Yes)
                {
                    // Exit the app if form 2 has requested it.
                    Close();
                }
                else
                {
                    // Show this for when form2 hides.
                    Show();
                }
            }
        };
    }
    // This should be a class member.
    Form2 form2 = new Form2();

    private void button1_Click(object sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(txtCreateUser.Text) || string.IsNullOrWhiteSpace(txtCreatePass.Text))
        {
            // SKIP THIS CHECK by simply making [Button 1] invisible until the form is valid.
            MessageBox.Show("Please fill out form completely");
        }
        else
        {
            MessageBox.Show("Account Created");
            // Shortened for clarity
            // MAKE SURE YOU NEVER 'REALLY' SAVE A PASSWORD IN THIS MANNER. REALLY. NEVER.
            File.AppendAllLines(UserPath, [$"{txtCreateUser.Text}t{txtCreatePass.Text}"]);
            // Add 'this'
            form2.Show(this);
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Hide();
        // Add 'this'
        form2.Show(this);
        // No need to do this form2.BringToFront();
    }

    // Don't do this
    //private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    //{
    //    System.Windows.Forms.Application.Exit();
    //}
}

Form 2

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
        txtPass.PasswordChar = '*';
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Shortened for clarity
        if(File.Exists(Form1.UserPath))
        {
            foreach (var line in File.ReadAllLines(Form1.UserPath))
            {
                var lineArray = line.Split("t");
                if (txtUser.Text == lineArray[0] && txtPass.Text == lineArray[1])
                {
                    MessageBox.Show("WORKS");
                    return;
                }
            }
            MessageBox.Show("DOES NOT WORK - did you ever assign txtName.Text and txtPass.Text?");
            return;
        }
        MessageBox.Show("FILE DOES NOT EXIST");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Hide();
    }

    // DO Add this to prevent this window from disposing when user clicks [X]
    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        if (!Modal && e.CloseReason == CloseReason.UserClosing)
        {
            DialogResult = MessageBox.Show(
                this,
                "Exit app?", 
                "Form 2 wants to close app", 
                buttons: MessageBoxButtons.YesNo);
            e.Cancel = true;
            Hide();
        }
        base.OnFormClosing(e);
    }

    // Don't do this
    //private void Form2_FormClosed(object sender, FormClosedEventArgs e)
    //{
    //    System.Windows.Forms.Application.Exit();
    //}
}

Another thing you can put in the Form 1 constructor, that shouldn’t be necessary but might provide some cheap insurance, is an explicit dispose when the main form does.


// Shouldn't be necessary, but it's cheap insurance.
public Form1()
{
    Disposed += (sender, e) =>
    {
        form2.Dispose();
    };
}

As mentioned, everytime you want to show a form, you create object representing it with new keyword. So you have many abandoned objects that may hold resources and keep your app alive.

You are showing just 2 forms and you just need one object for each form to display and hide them. The trick is that each form has to hold reference to the other form to manage it. Here’s my skeleton code which works as expected:

// Form1.cs
public partial class Form1 : Form
{
    private readonly Form2 _form2;

    public Form1()
    {
        InitializeComponent();
        FormClosing += (s, e) => Application.Exit();
        _form2 = new Form2(this);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Hide();
        _form2.Show();
    }
}

// Form2.cs
public partial class Form2 : Form
{
    private readonly Form1 _form1;

    public Form2(Form1 form1)
    {
        InitializeComponent();
        FormClosing += (s, e) => Application.Exit();
        _form1 = form1;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Hide();
        _form1.Show();
    }
}

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật