FormClosing shutdown event doesn't write to file - c#

I have a backup power supply for my computer which is attached inline with it and the wall. When I pull the power cord from the wall, I have 2-5 minutes before the backup supply shuts down the computer. It is during this time that I want to write data to a file with the code below:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.Equals(CloseReason.WindowsShutDown))
{
writeContents("Interrupted");
sendMessage("PWR - The Spring Test Machine has stopped");
return;
}
if (e.CloseReason.Equals(CloseReason.UserClosing))
{
if (MessageBox.Show("You are closing this application.\n\nAre you sure you wish to exit ?", "Warning: Not Submitted", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Stop) == DialogResult.Yes)
{
writeContents("Interrupted");
return;
}
else
e.Cancel = true;
}
}
The problem is that it didn't work. I don't think the the closing event ever got called. Any ideas would greatly be appreciated. Thank you.

From here http://www.daniweb.com/software-development/csharp/threads/253249/application-exit-does-not-trigger-the-formclosing
when you use taskmanager to "kill" the appliction, it doesn't fire any
events, It simply stops the execution, This is how you close an
application that has frozen. if you waited for it to handle any
events, then it would still be frozen.
as for when you restart the computer or shutdown, the event will be
called only if there is enough time, they system tells all
applications it is shutting down and only gives them a short amount of
time to handle business before it kills them. Windows 7 will show a
dialog telling you which applications are still busy and ask you if
you want to kill them and shutdown, or cancel. But as for XP, it just
kills them after X amount of seconds.
That's pretty much how I would have imagined the behavior of FormClosing... Would Application.ApplicationExit Event be a better event to listen for?

Here is some usful info about Properties of FormClosing event:
Bug in FormClosingEventArgs.CloseReason?
And you can try using switch statement, like here:
Detect reason for form closing

Not sure if it works cuase i need to check it first and im not infront of my machine now .. but have you also tried the other elements of the CloseReason enum ?
try TaskManagerClosing .
In any case try first to throw a message( messagebox ) to see if you actually have the correct CloseReason you want and also don't forget to use the e.Cancel = true if you dont want the pc to close everytime you check it .
After that check if the method you have for writting to the file is ok .
maybe this will help also
Prompt user to save when closing app

Related

Why the Process Exited event raise automatic all the time?

In the top of Form1 i did:
private Process zipFileDirectoryProcess;
In the constructor i did:
zipFileDirectoryProcess = new Process();
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
zipFileDirectoryProcess.StartInfo.CreateNoWindow = true;
zipFileDirectoryProcess.EnableRaisingEvents = true;
zipFileDirectoryProcess.Exited += new EventHandler(zipFileDirectoryProcess_Exited);
Then i have a method i call it from a button click event:
private void Compress()
{
zipFileDirectoryProcess.StartInfo.Arguments = zipFileDirectoryProcess.StartInfo.Arguments = "/select," + Path.GetFullPath(t);
zipFileDirectoryProcess.Start();
zipFileDirectoryProcess.WaitForExit();
this.TopMost = true;
}
And then in the bottom the Exited event:
private void zipFileDirectoryProcess_Exited(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
this.TopMost = false;
}));
}
What i wanted to do is only when i close the process window after started it in the method only if closed the window/process then do the Exited event.
The problem is that once the process started after 2-3 seconds its jumping automatic to the Exited event.
How can i fix it ? Tried examples cant figure out.
Tried to add this line:
zipFileDirectoryProcess.WaitForExit();
But no effect.
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
Trying to start Windows Explorer again when it is already running, and it is always running, will have a disappointing outcome. It is a "heavy" process and it intentionally tries the minimize the number of running copies. Otherwise known as a "single-instance app". There are lots like that, the Microsoft Office programs are single instance apps for example.
So what really happens is that explorer.exe actually starts up, but sees that another instance is already running. And uses process interop to ask that first instance to do the job that you asked it to do. Since you didn't ask it to do anything, you just get another window, displayed by the first instance. The one that you started immediately quits, it doesn't have anything else to do.
So, yes, you'll see that the Exited event fires without you doing anything. Accurately telling you that the explorer.exe process you started did in fact quit. Easy to see in the Taskmgr.exe Processes tab btw. Waiting for that window to be closed is never going to work, it is displayed by the original instance of explorer.exe.
This will just not work the way you hope it will work. What you are actually trying to do is not quite obvious but can be guessed at. Creating a ZIP archive is not difficult, there are excellent libraries available for C# to get the job done, no point in asking another program to do it for you. DotNetZip and SharpZipLib are very popular. It got finally added to .NET as well in version 4.5, Microsoft finally getting over the lost Stacker lawsuit, about time. If you really, really want another program to do it for you then use a console mode zipper like 7-zip.
To show output folder in windows explorer to the user, it's simply enough to do this:
Process.Start("explorer.exe", OutputDir);

How to cancel the shutdown event of PC?

I am making an application in which i want to execute some database queries just before system get shut down. I am using this code -
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
e.Cancel = true;
MessageBox.Show("Shut down canceled");
}
I did execute this application and tried to shut down the system and this code captured the shut down event also but the problem is after showing message box it shows this screen also- [I can't post the image as i don't have 10 points.]
it shows the name of my application that stopped the system to get shut down and it also provide "Force Shut down button" , i dont want this screen to be displayed as user can forcefully shut down the system before completion of execution of my queries.
Need expert advices on this, thanks a lot in advance.
The Short Reliable Answer:
On any recent Windows version, you can try to cancel shutdown but Windows may decide to ignore you; this is sadly by design. If you absolutely have to finish operations before your process is terminated, the right place to do this is in the SessionEnded handler. If you have tasks that must complete before your process terminates, you must not return from your SessionEnded handler until all your work is done (so your queries, etc. have finished.)
So instead of (or as well as, if you prefer) handling SessionEnding, handle SessionEnded and do you work there:
static void SystemEvents_SessionEnded(object sender, SessionEndedEventArgs e)
{
WaitForQueriesToFinishOrSaveState(); // new code
}
How you implement that waiting will depend on your application; if you need to run queries afresh you may be able to do them therein, or you may need to Thread.Join() or otherwise wait for background tasks to complete; but it must be a blocking wait (so you need to not return from the function until you're done).
Since you can't absolutely stop shutdown, there's perhaps little point in attempting the cancellation in this case, so I'd recommend not setting e.Cancel in SessionEnding at all. On older Windows versions this was more meaningful, very much less so now unfortunately.
It's also recommended by the API docs not to do any significant work in SessionEnding (including message boxes), but to set any flags you need to return immediately and then do the work in SessionEnded. (Unproven aside: I'm suspicious that if you don't return quickly enough, this may hasten the appearance of the "programs are misbehaving, do you want to kill them" screen for the user, as Windows believes you're not playing nice any more.)
Behind the Scenes:
Setting e.Cancel indicates to Windows that you'd like the session not to end; but the user still gets a look in; and Windows may decide to ignore your request for any reason it feels pertinent. That's just the way the cookie crumbles. You may find hacks that work situationally, but there's no API or approach which is Microsoft-approved and therefore likely to work consistently now and in the future.
Under the covers, Windows is sending your process' windows a WM_QUERYENDSESSION message, which .NET receives for you and translates into the SessionEnding event) and will pass your cancellation (or lack of) back to Windows; returning TRUE if you don't cancel, FALSE if you do.
After this, Windows takes a look at all process' requests and depending on the cause of the shutdown and other factors may well still decide to go ahead despite such requests. It may also alert the user if processes are not cooperating and give them the option of killing the process.
Whether you handle WM_QUERYENDSESSION (SessionEnding) or not, you always get one last chance to clean up: you're sent a WM_ENDSESSION message (translated into SessionEnded). The tricky part is that you have to do all your vital tasks before all your SessionEnded handlers have returned!
Once Windows hears back from its WM_ENDSESSION (SessionEnded) call, all bets are off as far as your application's lifetime is concerned and Windows can terminate your process at any point.
Raymond Chen covered this quite expertly and quite recently.
http://blogs.msdn.com/b/oldnewthing/archive/2013/06/27/10429232.aspx
As a footnote, SystemEvents.SessionEnded is a convenience; if yo have a top level application window you can bypass it entirely and achieve the same via:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x16) // WM_ENDSESSION
{
WaitForQueriesToFinishOrSaveState();
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
in shutdown command there's a switch for abort shutdown. you have to call this command by your c# code
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = false;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine(#"shutdown -a");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());

How to save my state in Windows Store App?

I have a little problem with saving my state to localsettings. Everything is ok except the situation when someone close my application using alt + f4 and open it before 10 seconds elapsed(after 10 seconds application is in state suspending and data is saved). (Technology xaml/c#)
I save my data in event OnSuspending.
I load my data in event OnLaunched like this:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated ||
args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)
{
// save data
}
How to handle this situation ? I know i can save my state every time it is changed but i think it is not good idea in my application.
Thanks for help !
When you close and launch your application before 10 seconds elapsed another instance of it is created and the previous one does not run OnSuspending event (it is strange because it means that asynchronous operations like this event can end or never start without warning us). I think that this is annoying but why would your user do something like that? Most of the times the user "restart" your application because it crashed or he is stuck and can't go back to the main page. You should try to prevent those scenarios and such think rarely will happen.
However, this can also happen because the user forgot to do something and want to start the app again. To prevent lost user data I save the most important data whenever I get the chance and save the rest only OnSuspending method. You need to think about what data will upset your users when lost.
I think Microsoft should get a better way of saving application state. I searched a lot about this problem and didn't found an explanation so for now I will continue to do what I said above. I hope this question you made can help and clarify me about this, in my opinion, strange case.
onLaunched :
CoreWindow.GetForCurrentThread().Activated += App_Activated;
and event:
void App_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//save Data
}
}
When you load data, remove:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated || args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)`.
It works !

How do I close COM1 after I left it open?

I'm working in Visual Studio C#, and I opened up a serial port, but I didn't properly close it. Now I cannot run my program to try to close it. I know it was me that was using it, but somehow I've lost control of it..? Is there a way to close it otherwise?
I've tried exiting out of visual studio and it still says that my access is denied. I've unplugged and replugged in the actual object I'm using. My next step is to restart the computer, but I don't want to have to do that everytime I mess up (which is frequently!)
On a side-note, I'm working in a lab and do not have administrative access on this computer. Another note is that the error's text is "Access to the port 'COM1' is denied."
In response to those asking for code,.. comPort.Open(); What else are you looking for?
private void updateAccuSwayData() {
Console.WriteLine("Update thread started...");
comPort.Open();
comPort.WriteLine("Q");
Thread.Sleep(5);
while (!cancelRequested) {
//do stuff...
}
Console.WriteLine("Update thread halted.");
comPort.WriteLine("R");
comPort.Close();
}
In a nutshell, I ended my debugging session while it was in middle of something it seems. That's about all I know.
You'll likely need to reboot to clear this up, although one approach would be to use Process Explorer and search for a handle to \Device\Serial0. You can then see if closing this handle works, it may not however.
To work to keep this from happening in the future, you need to put the comPort.Close() call in a finally-block:
try
{
comPort.Open();
// ...
}
finally
{
// Almost always ensures the COM port will be cleaned up,
// however, the MSDN remarks state that the port may not
// be closed immediately.
comPort.Close();
}

C# Windows application prevents Windows from shutting down / logging off

I have written a C# Windows Forms application, not a service (it is only used when the user is logged in and has a graphical user interface) that has a background thread running in an infinite loop.
When I try shutting down Windows (7) however, it tells me the program is preventing it from shutting down or logging off and asks me whether I want to force a shutdown.
Now, is there any possibility for my program to become aware (get a handler) of Windows trying to quit it or to log off?
So, what I need is to make the application realize when Windows tries to quit.
Thanks in advance.
EDIT: Thanks for the great advice! Is it in any way possible to use the idea with the form closing event if it has a CANCEL event handler?
public Form1()
{
InitializeComponent();
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// Or any of the other reasons suitable for what you want to accomplish
if (e.CloseReason == CloseReason.WindowsShutDown)
{
//Stop your infinite loop
}
}
You call that thread a "background thread" but does it have IsBackground = true; ?
The system will only stop a thread that does.
I think Capture console exit C# should also be usable in your scenario.
Apart from that, maybe it is sufficient to set up your thread as background thread?
Take a look at the Microsoft.Win32.SystemEvents.SessionEnding event.

Categories