Terminate Application on exit in Windows CE 6.0 - c#

I'm running Windows CE 6.0 on an ARM processor device using .NET CF 2.0 SP2 with an application written in C#.
I'm experiencing a problem where my application continues to run after it has closed. The application opens a connection with something connected to the device and doesn't release it until properly closed. Because of this, I cannot reopen and use the application while it continues to run and I can't run other applications which wish to use the attached device either.
I have tried to run Application.Exit() and all of my threads have the IsBackground property set to true but this doesn't work. After closing the application I can use a task manager and see that the process continues to run.
I'd normally use Environment.Exit() but this is not available in CF, unfortunately.
Is there any of methods I can try and use or causes that would be making this happen?
Thanks.

You could try something like this:
Process thisProcess = Process.GetCurrentProcess();
thisProcess.Kill();
And see what happens. It's obviously not ideal to closing a application, but it might work as a last resort, especially if you're handling the saving and discarding of data manually prior to that anyway.

For anyone still struggling with this:
I found the problem was that with Windows CE / WEHH / .NET Compact, applications don't exit on pressing the X button on a form, they are only minimized (meaning the closing event doesn't get called).
As per one of the answers on this page, the close button can be changed to actually exit the application by setting the form property 'MinimizeBox' to false.
this.MinimizeBox = false;
This will change the X button to an OK button, and will exit the application completely.

May be this can Help. Set Thread's Background Property to false before calling Application.exit();
private void BtnExit_Click(object sender, EventArgs e)
{
Thread1.IsBackground = false;
Thread2.IsBackground = false;
Application.exit();
}

Related

Release mode UWP app crashes when in tablet mode and with code in OnSuspended

We have a Xamarin UWP app that needs to be logged out whenever a user minimizes or clicks away from the window.
In my App.xaml.cs I have registered an event handler for the Suspending event. I then put our logout code in this event handler like so:
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.GetDeferral();
AppBackgrounded();
deferral.Complete();
}
This AppBackgrounded() method looks like this:
void AppBackgrounded()
{
if (!_isInBackgroundMode)
{
_isInBackgroundMode = true;
if (UserSetPin)
{
PinPage passcodePin = new PinPage();
Navigation.PushModalAsync(New NavigationPage(passcodePin), false);
}
else
{
App.Logout(null, true, true);
}
// clears the pasteboard so data can't be copied from this app into other apps
Clipboard.Clear();
}
}
We also have a AppLeavingBackground method that we use to restore the app when the user returns, but the app does not crash when returning. It only crashes when running the OnSuspended method.
This crash only occurs when
The App is built for release and
The device is in tablet mode
When in tablet mode, if you press the Task View button and navigate to another application the UWP app freezes trying to run through this code. If you try to return to the app, it will immediately exit.
I have tried to make the navigation to the other pages async and the app will then crash even when its not in tablet mode. I have also tried to put this logic in AppEnteredBackground and it still occurs.
This is hard to debug since it only occurs in release mode. Any ideas?
In my case it was the Clipboard.Clear() function that was crashing the application. For those encountering similar issues, checkout the other answers as they all provide great points.
As a side note, I also found that using async code in these events was crashing my application. I'm not sure why since I was using the deferral, but since it's working i'm not going to pursue it further.
I cannot say that I have read exactly the documentation that says that navigating the pages in suspending will result in a crash, but it is clear that this is the wrong place to do it.
The suspending is not used to prepare your app to be opened again, the whole reason for this lifecycle event is that you need to prepare your app for not being open again, which means saving some data that may eventually get lost. Preparing your app to be opened again is done in resuming.

Windows forms kill background process on app exit

I am making a simple windows form application in Visual Studio. But I have a problem when I want to close the app. When I right-click it from taskbar and close it, I can see background process still running in Task Manager.
How do I kill whole app?
I have paced this in first form that is opening when app starts:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if(!exit)
{
if (MessageBox.Show("Close the app?", "Simple App", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
exit = true;
Close();
}
else
{
e.Cancel = true;
exit = false;
}
}
}
I added Application.Exit(); on all forms in OnFormClosing event. And it is working good.
What you describe is the main problem with background processes. They just don't automatically end their work when the calling process is ended.
In essence you have 2 possible alternatives there both of which have a delay though (and have a possibility of not working depending on how stable your background processes are).
Kill the process manually
When you create the process you save its handler and then send a kill signal to it upon application exit. Like usual when you manually send a kill signal it can be that it takes some while to take an effect. And if if takes effect it can still happen that the process ignores it or ends at a state of process execution you don't want it to end
Habe a kill flag within the process
The process itself has a flag to which he reacts. When you kill the main application you set the flag to the "end me" setting and within the background process you check on each iteration it makes (or at least periodically) if the flag is set and if it is set just end the process from within.
In both cases you can optionally wait in the main application with a while loop and check if the process has ended correctly. Only problem here is that it CAN be depending on the exact implementation of the background process that it never ends as it just ignores the kill command.
Thus in essence it is possible to kill background processes from the main process BUT it probably will be a delayed kill AND it can be that it will not work.
In this case as you want the background process to end at application exit I would ask another question myself there: Are you sure that you want a BACKGROUND process there to be? As a foreground process just does automatically what you want: End at the end of execution of the main process.

Launch thread, do work, close app, continue to do work in background in other thread

I am trying to fulfil some needs for my users and one of them is proving a bit difficult. I can't create a Windows Service to do this, and so I'm not sure how else to do it.
Basically, they keep closing the program after they are done with it. But the application clearly indicates that an operation is still in progress and that they must wait for they close the window. There's no need for an ETA on this operation, and since they insist on closing the app before it's had its chance to do their work, I thought of something.
How can I close an app (not this.Hide() - but this.Dispose(true)) but launch an external thread that runs an operation while the app has been closed?
Lots of apps get "closed to tray", i.e. simply hidden, there is nothing unusual with that. I would suggest to your client that this is a common approach, if you want to keep the app running. Creating a new (hidden) process to do this is just doing this same thing, only more error prone, harder to do properly and harder to monitor.
Also, having a "hidden" process working in the background could likely cause issues if your client decides to start your app again while the background job is still active. But if the app has work to do, I don't see why you couldn't prevent closing it. That's the best way, because you can ensure that there's only one instance running and be able to monitor its progress properly.
If they are forcefully closing it (e.g. using Task Manager), then there's nothing you can do about it.
Problem is once you close the app you also dispose all of its children, you either need to do the this.hide() then call application.exit() once your work is complete, or create a new top level application that launches the main UI app and handles the background work.
You could subscribe to the FormClosing event and cancel attempts to close the app until the process is complete and you're ready to allow it.
private bool isProcessRunning;
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = isProcessRunning;
}
Set isProcessRunning to True before you start the thread; set it to False when you're finished.
I'd also consider displaying an indicator that the process is still running (like a ProgressBar), so they don't sit there trying to close the app, thinking it's simply unresponsive.
Of course, if the process is really important you might want a more robust solution. Can't stop the user from just shutting down their machine, which would also kill your process.
Before I give my solution, permit me to say that I don't think you should do this. Instead, hide the window, or minimize to the tray, or something like that. I think this is what users expect. Lots of applications minimize and continue doing work then exit when they are done. If the app looks like it has exited, but is really still running, the user might reboot, or launch the application again.
If you really do want to do this, either:
1) Do the work in another thread. The EXE will not exit until the thread completes. Example:
private void Form1_Load(object sender, EventArgs e)
{
new Thread(DoWork).Start();
}
private void DoWork()
{
Thread.Sleep(10000);
MessageBox.Show("done!");
}
2) Or do the work after the form exits. Do this by modifying the Program.cs:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
MessageBox.Show("Still running! Can still do work here!");
}

How to keep process running after closing the program?

I am now developing an application on Windows Mobile 6.5 with .Net Compact Framework 3.5 using C#. There is a function in the program that I use it to update the location information periodically from server side, but if I keep running this computation, it would cost too much energe. For this reason, I want to run it in background and I try to use BackgroundWorker to do this and it works well.
The problem I have now is that I can't minimize the program so that I have to keep the main form of the program run in foreground even if it's not doing anything and this is very inconvinence for a user. However, when I close the program, the BackgroundWorker will also be closed.
Is there any method to keep the update process running (somewhere in memory or so) when I close the program? and then can restore the information when I restart the program?
How about creating a Service instead of a background worker?
If your Form closes, then Application.Run (probably called over in Program.Main) returns and the process' primary thread exits, causing the application to terminate.
The solution, then, is don't close the Form, simply Hide it. By default the "MinimizeBox" property for your Form should have been true and it should have an [X] in the upper right corner. Clicking this minimizes the Form and will not exit your application.
The other option in some cases is to not have a Form at all. The challenge here is that the CF doesn't have any Application.Run overload that doesn't accept in a Form (like the desktop framework does). The Smart Device Framework does provide one if you want to go that route.
I have not used the .NETCF 3.5. However in the previous version on .NETCF 1.0/2.0 I observed that even if you close the application using (X) button, it just goes to background but remain in the memory.
If that is the case with .NETCF 3.5 as well then I think you do not need to anything here. The background worked will be running even if you close the application.
I Hope this will help you.

Windows-mobile app won't run after being closed by Task Manager

I've inherited some windows-mobile code that I've been bringing up-to-date. I've come across a weird bug, and I was hoping that even though a bit vague, maybe it will spark someone's memory:
Running the app (which is basically a glorified Forms app with P/Invoke gps code), I switch to the task manager, and close the app via End Task. Seems to exit fine (no errors and disappears from Task Manager). Unfortunately, the app refuses to start a second time until I reboot the phone or reinstall the CAB.
What's worse: this bug is reproducible on a HTC Diamond, but works fine (ie. can run again after EndTask) on an HTC HD2.
The only thing I can think of is some kind of timing race between a Dispose() and the Task Manager. Any ideas?
I'm also thinking of a workaround - I do have a working "Exit Application" routine that correctly cleans up the app; can I catch the EndTask event in the c# code in order to complete a proper cleanup?
Maybe I'm just missing the pain point... all ideas welcome :)
When you use TaskManager to close it, the following happens:
The app Form(s) are send a WM_CLOSE message
If, after a period of time, they are still running TerminateProcess is used.
If you have a worker thread running that does not exit, the process will often not fully terminate. This was really common in CF 1.0 where the IsBackground property for a thread didn't exist.
Since TaskManager only enumerates Form captions, if your forms are all closed, it will not show the app, even through the process is running. When you try to execute again, the shell detects that it's already running and simply swithes to the running (with no UI) process so it looks like nothing happened.
You can verify this behavior with Remote Process Viewer.
The solution is to fix your worker thread code to exit properly. Typically I use a boolean or a WaitHandle to signal that they should exit. Setting IsBackground to true should also happen for all threads that are created.
it's been a year since your question, but this might be the answer.
I had the same sort of problem. My app has MinimizeBox = False, this shows a small Ok in the right top corner of the form and is the only way to handle the Closing Event (the Cross with MinimizeBox = True doesn't raise ClosingEvent). In this event I cancel the closing and do some custom code and minimize the form so that it looks like the standard ‘Cross close thing’ behavior.
The problem is that on htc diamond, when you kill a task it raises the same closing event, and my code cancels it again. The weird thing is that in task manager the app has disappeared, but if you launch the original Microsoft task manager (/windows/taskmgr.exe) and in the menu select show processes, then you see your app still running. That’s why you can’t launch it again. Strangely on HD2 it has the same behavior with the closing event, but it seems to also force a brute kill on the app, so no problem.
The solution :
You just need a little bool to know if your app is on foreground or on background that you set to true in the form activate event and false on deactivate event. In the closing event, you cancel only if your app is in foreground you can run your special code, otherwise let the form close, it's a kill !!!
[DllImport("coredll.dll")]
static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_MINIMIZED = 6;
public static void MinimizeForm(IntPtr pFormHandle)
{
ShowWindow(pFormHandle,SW_MINIMIZED);
}
private bool m_IsFormVisible = false;
void m_MainForm_Deactivate(object sender, EventArgs e)
{
m_IsFormVisible = false;
}
void m_MainForm_Activated(object sender, EventArgs e)
{
m_IsFormVisible = true;
}
void m_MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (m_IsFormVisible)//very important !
{
e.Cancel = true;
//do something if you want
//minimize the form yourself
MinimizeForm(s_Instance.m_MainForm.Handle);
}
}
I don't know exactly what your problem is, but I find WinCE devices tend to only allow one instance of an application to run at once. This could mean that either TaskManager didn't clean up the application properly so it thinks it's still running and doesnt start another copy, OR, it might actually still be running.
Try put some code in your application that detects if it is already running.
Also try double check you are cleaning everything up properly when it exists, especially threads etc as the timing of windows shutting down your application may be different to you doing it manually.
Hope any of that helps

Categories