How to execute code when the user close the session? - c#

i am writing an application which use microscope.
When the user close the application, the application turned off the microscope.
Is there a way to execute this code when the application is closed because the user close the windows session ?
Regards,

You can use the FormClosing event to catch a form closing action, and perform tasks before closure, or prevent it from closing at all. Here is an example I use regularly.
private void Form_FormClosing(Object sender, FormClosingEventArgs e)
{
//Do stuff here:
if (prevent_close)
{
//or cancel the closing here:
e.Cancel = true;
}
}

Related

Unable to close window application with user defined button and what is perfect process to call application from window service [duplicate]

This question already has answers here:
How do I properly exit a C# application?
(4 answers)
Closed 5 years ago.
I am new for c# developer and I tried to close my window application with following code. I hide close button of form and add user defined button to close application.
private void closeBtn_Click(object sender, EventArgs e)
{
System.Environment.Exit(0);
//Environment.Exit(1);
//Application.Exit();
//this.Close();
}
But process still running on Task Manager. Actually I am calling this application from Window service. But application is not closing properly.
private void callback(Object state)
{
string strAppPath;
strAppPath = #"D:\VSPythonProject\Reminder_WApp\Reminder_WApp\bin\Debug\Reminder_WApp.exe"; //System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles) +
System.Diagnostics.Process.Start(strAppPath);
ApplicationLoader.PROCESS_INFORMATION procInfo;
ApplicationLoader.StartProcessAndBypassUAC(strAppPath, out procInfo);
}
check ApplicationLoader event. That call twice.
For closing application use below code :
System.Windows.Forms.Application.Exit();
instead of
System.Environment.Exit(0);
To close running threads use:
System.Windows.Forms.Application.ExitThread( );
To close running form use :
this.close();
For console application use:
System.Environment.Exit(0);

C#: Run process and then kill it using a button

I hope that you can help me with this one, my C# is very rusty.
I'm running an executable when the form loads.
private void Form1_Load(object sender, EventArgs e)
{
ProcessStartInfo exe = new ProcessStartInfo();
exe.Arguments = "arguments";
exe.FileName = "file.exe";
Process.Start(exe);
}
And I would like to kill that process using a button, but I don't know how to achieve that.
private void button1_Click(object sender, EventArgs e)
{
}
Thanks.
Process.Start returns an object of type Process. You can save it into variable, then use the method Kill, which Immediately stops the associated process (msdn)
For example declare a field at Form1 level:
class Form1
{
private Process process;
private void Form1_Load(object sender, EventArgs e)
{
//running notepad as an example
process = Process.Start("notepad");
}
//and then at button handler kill that process
private void button1_Click(object sender, EventArgs e)
{
//consider adding check for null
process.Kill();
}
}
You should call Process.CloseMainWindow which performs an orderly termination of the process and closes all windows. As opposed to Process.Kill which causes abnormal termination. CloseMainWindow is preferable for applications with a user interface.
process = Process.Start(exe);//in form load set field
private void button1_Click(object sender, EventArgs e)
{
process.CloseMainWindow();
}
The remarks on MSDN reveals important information regarding the asynchronous behavior and other relevant details.
Kill forces a termination of the process, while CloseMainWindow only
requests a termination. When a process with a graphical interface is
executing, its message loop is in a wait state. The message loop
executes every time a Windows message is sent to the process by the
operating system. Calling CloseMainWindow sends a request to close to
the main window, which, in a well-formed application, closes child
windows and revokes all running message loops for the application. The
request to exit the process by calling CloseMainWindow does not force
the application to quit. The application can ask for user verification
before quitting, or it can refuse to quit. To force the application to
quit, use the Kill method. The behavior of CloseMainWindow is
identical to that of a user closing an application's main window using
the system menu. Therefore, the request to exit the process by closing
the main window does not force the application to quit immediately.
etc...
try this
try
{
Process [] proc Process.GetProcessesByName("notepad");
proc[0].Kill();
}

c# show hidden window of a process [duplicate]

This question already has answers here:
Run one instance of program
(2 answers)
Closed 9 years ago.
There is an option in my application to hide the window - form.hide(), and to put an notifyicon in the system tray, and when you click the notifyicon there will be a form.show().
If someone will try to run two instances of the app, I want
a. not to run the new instance
b. to show the window of the first instance
I already have a loop to check if a process with the same name exists.
and I can tell the new app not to run ( return in the program.cs before Application.run(new form()))
but I yet have to tell the first app to show its main window.
I have the process (of the first instance) , i can get its handle its id etc.
the question
How to show the window using it's process?
For the first part of the question, here is what you can do. Add this in the Main before you show your form. The benefit of this is that you don't check by process name (which might not be unique), but you create a mutex which is somehow "global".
using (Mutex applicationMutex = new Mutex(true, "SomeRandomTextHere", out mutexCreated))
{
if (!mutexCreated)
{
// Application is already running. Aborting..
return;
}
// Application.Run(..) goes here, plus other interesting stuff
}
For the second part of your question I would suggest the following:
Create a named event and set it initially to false. Then create a worker thread in your application that monitors this event. When it is signaled, Invoke your Show method from your main form.
Another approach is to search for the window handle of the main process and bring it to front. This article can give you ideas.
Bear in mind that doing a loop through all processes is not as efficient as using a mutex. If you don't care about speed, clean code and you just want this app to work then use this loop.. To me code is poetry.
Rewrote the code just for you this will give you exactly what you want. It will check for duplicates and focus the screen when a duplicate is opened.
EventWaitHandle ProgramOpen = new EventWaitHandle(false, EventResetMode.ManualReset, "ProgramOpen198472");
EventWaitHandle FocusProgram = new EventWaitHandle(false, EventResetMode.ManualReset, "FocusMyProgram198472");
private delegate void focusConfirmed(); Thread FocusCheck;
private void focus() { FocusProgram.WaitOne(); this.Invoke(new focusConfirmed(()=>{this.Show(); this.BringToFront();}));}
private void Form1_Load(object sender, EventArgs e)
{
if (ProgramOpen.WaitOne(0))
{
FocusProgram.Set();
this.Close();
}
ProgramOpen.Set();
}
private void HideButton_Click(object sender, EventArgs e)
{
this.Hide();
FocusProgram.Reset();
FocusCheck = new Thread(focus);
FocusCheck.Start();
}
private void showToolStripMenuItem_Click(object sender, EventArgs e)
{
FocusProgram.Set();
}

ShowDialog in Closing-Event

If the user closes the Application a Save-File-Message have to be shown (to be sure that he wants to discard the changes of edited files).
to implement this, i have a menuitem with a command-binding (without key-gesture):
private void Command_Exit(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown();
}
the mainwindow has a closing-event. in this event i check if there unsaved files. if yes, the savedialog has to be opened (to choose, which files have to be saved):
private void Window_Closing(object sender, CancelEventArgs e)
{
if (sdl.Count() > 0)
{
SaveDialog sd = new SaveDialog();
IEnumerable<Doc> close = sd.ShowDialog(this);
if (close == null)
e.Cancel = true;
else
foreach (Doc document in close)
document.Save();
}
}
in this ShowDialog-Method (implemented in my SaveDialog-Class) i call
bool? ret = ShowDialog();
if (!ret.HasValue)
return null;
if (!ret.Value)
return null;
The problem is:
If i use the Alt+F4-Shortcut to close the Application (default-behaviour of the mainwindow) it works and i get the savedialog if there are unsaved files. but if i close the application by executing the Command_Exit-Method, the Method-Call
bool? ret = ShowDialog();
returns null and the dialog does not appear.
If i assign the Alt+F4 KeyGesture to the CommandBinding, the problem is switched: Executing Command_Exit works well but Alt+F4 Shortcut not.
What is the reason that the ShowDialog()-Method works not in both cases and how to fix it?
The Application.Current.Shutdown route allows you to listen for the shutdown request by handling the Exit event as detailed here:
http://msdn.microsoft.com/en-us/library/ms597013.aspx
It doesn't detail how it closes windows, so I wouldn't necessarily be convinced that the closing event handler would fire before it closes the application.
The other very standard way to shut the application down is to close the main window (the one shown at the very beginning). This would likely be the Window.Close method, if you are in the context of the window already, just call Close(). This will then hit the closing event handler.
Your Command_Exit implementation is wrong. Application.Current.Shutdown() means that the application is already shutting down, which can prevent the dialogs from opening.
You should implement the command other way: in the command you should ask your business logic if it's safe to shutdown, and issue Application.Current.Shutdown() only in that case. Otherwise, you should ask the business logic to start the shutdown sequence, which would in turn save the open files, and issue a Shutdown upon completing save operations.
Moreover, you should trigger the same routine when the user tries to close the main window (that is, on its Window.Closing).

delay Application Close best practice?

Is there a better way to handle the task of doing something after the user has chosen to exit a WinForms program than this :
[edit 1 : in response to comment by 'NoBugz] In this case there is no ControlBox on the Form, and there is a reason for putting one level of indirection in what happens when the user chooses to close the Form [/edit 1]
[edit 2 : in response to all comments as of GMT +7 18:35 January 20 ] Perhaps using fading out the MainForm is a simple illustration of what you might want do as the Application is being closed : the user cannot interact with that : it is self-evidently related to the user's decision to terminate the application. [/edit 2]
(use some form of threading ?) (implications for a multi-threaded app ?) (does this code "smell bad" ?)
// 'shutDown is an external form-scoped boolean variable
//
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// make sure we don't block Windows ShutDown
// or other valid reasons to close the Form
if (e.CloseReason != CloseReason.ApplicationExitCall) return;
// test for 'shutDown flag set here
if (shutDown) return;
// cancel closing the Form this time through
e.Cancel = true;
// user choice : default = 'Cancel
if (MessageBox.Show("Exit Application ?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.OK)
{
// user says Exit : activate Timer, set the flag to detect Exit
timer1.Enabled = true;
shutDown = true;
}
}
Summary : In a very standard WinForms application (one MainForm launched in Program.cs in the standard way) : in the FormClosing Event handler of the MainForm :
exit immediately (triggering the default behavior : which is to close the MainForm and exit the Application) if :
a. the CloseReason is anything other CloseReason.ApplicationExitCall
b. if a special boolean variable is set to true, or
if no immediate exit : cancel the "first call" to FormClosing.
the user then makes a choice, via MessageBox.Show dialog, to Exit the Application, or Cancel :
a. if the user Cancels, of course, the Application stays "as is."
b. if the user has chosen to 'Exit :
set the special boolean flag variable to true
run a Timer that does some special stuff.
when the internal test in the Timer code detects the "special stuff" is done, it calls Application.Exit
My suggestions, both as a developer and a user:
A very fast task
Just do the task in the Closing event handler.
A less fast, but not incredibly slow task
Create a non-background thread (so it's not shut down when the application exits) with the task in the Closing event handler.
Let the application exit. Forms will go away, et cetera, but the process will keep running until the task is done.
Just remember to handle exceptions and such in that worker thread. And make sure that things doesn't crash if the user reopens your application before that task is done.
Slower tasks
In the Closing event handler, open a shutting-down-form and let the form itself close.
Do the task in the/behind the shutting-down-form while displaying some friendly progress and information.
Exit application when task is done.
Some untested example code. We are doing something similar to this in one of our applications. The task in our case is to store window properties (location, size, window state, et cetera) to a database.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// If it wasn't the user who asked for the closing, we just close
if (e.CloseReason != CloseReason.UserClosing)
return;
// If it was the user, we want to make sure he didn't do it by accident
DialogResult r = MessageBox.Show("Are you sure you want this?",
"Application is shutting down.",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (r != DialogResult.Yes)
{
e.Cancel = true;
return;
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
// Start the task
var thread = new Thread(DoTask)
{
IsBackground = false,
Name = "Closing thread.",
};
thread.Start();
base.OnFormClosed(e);
}
private void DoTask()
{
// Some task to do here
}
I don't see anything "wrong" with this. My only recommendation would be to let the user know that the program is "shutting down" by raising a non-modal window or perhaps a notification toaster above the system tray.
A couple of minor points:
I'd question the need for a timer: as the application is exiting anyway, and the user won't therefore expect the UI to be responsive, why not simply do the clean-up code on the UI thread? As suggested by #Dave Swersky, a little notification window during cleanup would be polite.
What happens if the application exit is triggered by a Windows shutdown or a user logoff?

Categories

Resources