Windows form application can't be closed normally - c#

I have problem when closing the windows form application. I need to know is it always called private void Form1_FormClosing(object sender, FormClosingEventArgs e) if I press X button on the form and if I just click to shut down computer?
Anyone neither of this times form is not closed as normally. I always have screen to press End now
I have connecting to the databases when form is closing, and copying some records to another database. Is that maybe the problem? Form is closing to fast and sql commands can't finish?
I have tried Enviroment.Exit(0), Application.Exit(). Nothing seems to be working correctly.
How to make it do all the sql and then quit?
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//close database connection
if (Con.State == ConnectionState.Open)
Con.Close();
info.Dispose();
//last check for local database
try
{
// database queries and so on....
}
catch (Exception ex)
{
writeToLogFile(ex.Message);
}
// exit
Environment.Exit(0);
}

UPDATE (based on your last comment):
private const int WM_QUERYENDSESSION = 0x11;
private const int WM_CANCELMODE = 0x1f;
private bool shutdownRequested = false;
...
protected override void WndProc(ref Message ex)
{
if (ex.Msg == WM_QUERYENDSESSION)
{
Message MyMsg = new Message();
MyMsg.Msg = WM_CANCELMODE;
base.WndProc(ref MyMsg);
this.shutdownRequested = true;
}
else
{
base.WndProc(ex);
}
}
...
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.Visible = false; // optional
this.ShowInTaskbar = false; // optional
Task db = Task.Factory.StartNew(() => DBUpdate();
Task.WaitAll(db); // you can have more tasks like the one above
if (this.shutdownRequested)
Process.Start("shutdown.exe","-s");
}
private void DBUpdate()
{
// write your db code here
}
I believe that this will work.

Anyone neither of this times form is not closed as normally. I always have screen to press End now
Are you saying you want the application to automatically shutdown if the computer is restarted or shut down?
If so, just hook up an event to the Microsoft.Win32.SystemEvents.SessionEnding event.
Microsoft.Win32.SystemEvents.SessionEnding += new Microsoft.Win32.SessionEndingEventHandler(SystemEvents_SessionEnding);
void SystemEvents_SessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e)
{
// Run your application shut down code here...
}

Related

WPF C# Windows throws "Application has stopped working" upon Application.Current.Shutdown(); call

I'm in process of learning C# and WPF specifically. I have a program currently written but it's having an issue closing. When a user closes the main window, the program ends, but the process continues running in the background. Each time a new window is open, a new process is created and never ends. I attempted to fix this by adding the following code to my MainWindow.xaml.cs file:
private void InventoryUpdater_Closed(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
This closes the process but causes a window to pop up that acts like the program shutdown incorrectly and prompting the user to "Close the program". That window states, "[Application Name] has stopped working.
How can I end my application process without it prompting the user each time they want to close? Is it possible I've not properly disposed something?
So I figured out what was causing the prompt and what was causing the unending process.
The prompt had to do with my opening and closing of the other 3 windows. Here is what I changed to stop getting the error from Application.Current.Shutdown(). I changed this code:
private void settingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
updateSettings();
e.Cancel = true;
main.Show();
Hide();
}
private void settingsButton_MouseUp(object sender, RoutedEventArgs e)
{
settingsWindow settingsWindow = new settingsWindow(this);
if (!settingsWindow.settingsOpen)
{
settingsWindow.Show();
Hide();
}
}
To this code:
private void settingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
updateSettings();
}
private void settingsButton_MouseUp(object sender, RoutedEventArgs e)
{
settingsWindow settingsWindow = new settingsWindow(this);
if (!settingsWindow.settingsOpen)
{
settingsWindow.ShowDialog();
}
}
Once I close main it was going back through the other window instances that I had initialized on load and was cycling through their Closing events. Once it was getting to main.Show(), it was failing to Show something that had already been closed.
Once I did that, I was about to figure out that the original initializing of the additional windows in my Loaded event was causing the additional trace backs that weren't ending. Here is what I changed. I changed this:
private void InventoryUpdater_Loaded(object sender, RoutedEventArgs e)
{
settingsWindow settings = new settingsWindow(this);
sftpSettings severSettings = new sftpSettings(settings);
TimeSpan na = queueCustomTask();
Stop = true;
runManually.IsEnabled = true;
ssdRunManually.IsEnabled = true;
startAutoRun.IsEnabled = true;
}
To this:
private void InventoryUpdater_Loaded(object sender, RoutedEventArgs e)
{
TimeSpan na = queueCustomTask();
Stop = true;
runManually.IsEnabled = true;
ssdRunManually.IsEnabled = true;
startAutoRun.IsEnabled = true;
}
I'm not even sure why the initializing was still there. Everything had been switched to static global variables so removing those two lines affected nothing. Thanks for all the shoves in the right direction!

I want to run a function when ever the form is clicked on taskbar and it opens

The issue doing so is i have used tips and tricks here but the seems to run in a loop and wont give the results.
Basically i run a BackgroundWorker to hit a url get result and paste result to some Labels.
I have used Form_Activated but it just keeps on running in a loop and wont stop ever reached to the BackgroundWorker completed event .
MAIN CODE BLOCKS:
On Form_Load I Run the Function and get the results and show:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Show();
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
else
{
MessageBox.Show("Thread already running....");
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
loadData(); // scrape a URL and paste info to Labels ....
}
This is it, now the user will minimize the application , now whenever he hits the the taskbar icon the form should rerun the same as in Form_Load. I hope that make sense , i have been able to do that using Form_Activate but it keeps going on .
Any suggestion how to get it done ?
I would store a boolean to remember if the form was minimized at the last FormResized event, and then if it was and if the form isn't currently minimized then call your method.
private bool minimized = false;
public void FormResized(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
minimized = true;
}
if (minimized && this.WindowState != FormWindowState.Minimized)
{
minimized = false;
MyMethod();
}
}

what is the best practice to exit an WPF application?

I am maintaining an existing C# application, and I noticed the following code are not working as expected.
private void Form1_Load(object sender, EventArgs e){
...
if (proc.Length == 0)
{
proc = Process.GetProcessesByName("OpCon");
if (proc.Length == 0)
{
WriteLog("DataloggerService start: no TSS process detected; close;");
this.Close();
}
}
...
}
The code is supposed to exit after the Close() api call. However, it still proceed.
After some reading and research, I modified it to
private void Form1_Load(object sender, EventArgs e){
....
if (proc.Length == 0)
{
proc = Process.GetProcessesByName("OpCon");
if (proc.Length == 0)
{
WriteLog("DataloggerService start: no TSS process detected; close;");
this.Dispose();
Environment.Exit(0);
}
}
....
}
It seems to exit as expected. However, I am not confident whether this is the best practice?
is it really necessary to call this.Close() or this.Dispose() before Environment.Exit()?
Thanks.
regards,
Sqr
In your WPF application whenever your MainWindow that is specified as StartupURI in App.xaml is closed your application exits automatically.
Still if you want to handle this exit of application on your end you can go for below solution.
Override the onClosing of MainWindow and manually exit/shutdown your application.
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
// Shutdown the application.
Application.Current.Shutdown();
// OR You can Also go for below logic
// Environment.Exit(0);
}

Closing() with CancelEventArgs versus Form_Closing with FormClosingEventArgs

We are currently upgrading and remodularizing our code as we transfer from 32 to 64 bit system. In due process, one of our goals is to change from an Init() function where things were added as such example.
this.Closing += new System.ComponentModel.CancelEventHandler(this.Form_Closing);
I'd like Windows events to handle these sorts of things. So I went to the Form_Closing event in the Windows Form Events and [without surprise] saw that this was not the form_closing event. My question to this is, is there any difference between what is actually going on with CancelEventArgs vs FormClosingArgs, or are these two pieces of code literally doing the same thing with one being a Component of System and one being the result of a Windows Event handling what it does best? I'm just sort of diving and indulging myself into this new project as an intern. Is it possible to just replace the CancelEventArgs with the FormClosing one without any loss of data or issues?
Code 1: CancelArgs
private void Form_Closing(object sender, CancelEventArgs e)
{
// If the user hit Cancel, just close the form.
if (this.DialogResult == DialogResult.Ignore)
return;
if (this.DialogResult == DialogResult.OK)
{
// If the address is not dirty, just cancel out of
// the form.
if (!this._editedObject.IsDirty)
{
this.DialogResult = DialogResult.Cancel;
return;
}
// Save changes. If save fails, don't close the form.
try
{
SaveChanges();
return;
}
catch (Exception ex)
{
ShowException se = new ShowException();
se.ShowDialog(ex, _errorObject);
_errorObject = null;
e.Cancel = true;
return;
}
}
Form_Closing -- Preferred Route
private void ScheduleItemDetail_FormClosing(object sender, FormClosingEventArgs e)
{
// If the user hit Cancel, just close the form.
if (this.DialogResult == DialogResult.Ignore)
return;
if (this.DialogResult == DialogResult.OK)
{
// If the address is not dirty, just cancel out of
// the form.
if (!this._editedObject.IsDirty)
{
this.DialogResult = DialogResult.Cancel;
return;
}
// Save changes. If save fails, don't close the form.
try
{
SaveChanges();
return;
}
catch (Exception ex)
{
ShowException se = new ShowException();
se.ShowDialog(ex, _errorObject);
_errorObject = null;
e.Cancel = true;
return;
}
}
}
You don't get the CloseReason property with the CancelEventArgs class, which is the only difference, since FormClosingEventArgs inherits from the CancelEventArgs class. The FormClosingEventArgs was introduced in .Net 2.0.
Alternatively, instead of using the event, you could just override the OnFormClosing method, too.
protected override void OnFormClosing(FormClosingEventArgs e) {
// your code
base.OnFormClosing(e);
}

Is CancelAsync working or not?

I've made a small app where Form is threaded (using BackgroundWorker), and in the form I'm calling a function QuitApplication in Program class when I want to quit.
The DoWork looks like this:
static void guiThread_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
if (Program.instance.form != null)
{
Program.instance.form.UpdateStatus(Program.instance.statusText, Program.instance.statusProgress);
}
Thread.Sleep(GUI_THREAD_UPDATE_TIME);
}
}
and in the Form1 class i have this method attached to the closing of the window:
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Program.instance.SetStatus("Closing down...", 0);
Program.QuitApplication();
}
So what i want is to ensure that everything quits when I press the X on the window. However, the if( worker.CancellationPending == true ) never hits... why is this?
QuitApplication looks like this:
public static void QuitApplication()
{
Program.instance.guiThread.CancelAsync();
Application.Exit();
}
And Im using guiThread.WorkerSupportsCancellation = true
CancelAsync is setting the CancellationPending property, but then you immediately quit the application without giving the background thread a chance to detect that and shut down. You need to change your UI code to wait for the background thread to finish.
Personally, when I write apps like this, I make the form close button act like a Cancel button rather than quit immediately. It's a lot safer for the end user. For example:
private void abortButton_Click(object sender, EventArgs e) {
// I would normally prompt the user here for safety.
worker.CancelAsync();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if(worker.IsBusy) {
// If we are still processing, it's not very friendly to suddenly abort without warning.
// Convert it into a polite request instead.
abortButton.PerformClick();
e.Cancel = true;
}
}

Categories