Is it possible in .NET to ascertain whether my application is closing due to Windows being given a shutdown command (as opposed to any old application closing) in order to either write out some temporary cache files or even block the shutdown long enough to prompt for user input?
Whilst my current scope involves a Winform app and a windows service, I am interested in understanding this in a generic way if possible
SystemEvents.SessionEnding looks like a good starting point for you. That article talks about the event sequence involved when a logout/shutdown is occurring.
In general, you will want to handle the WM_QUERYENDSESSION Windows message. This will give your application a chance to do cleanup, or to block the shutdown if it's really necessary.
Handle the SessionEnded event on the Microsoft.Win32.SystemEvents type.
Related
I have an application (C# + WPF) that attempts to wrest control of the graphical interface of any process passed to it as an input and resize/reposition for my own purposes.
It does its job rather well, I think. Upon expected termination (the base class inherits from IDisposable) the "captured" process is released - its parent is set to the original, its windowstyle is reset, etc. etc.
In fact, on testing, I can capture, release, recapture, and so on, the same process as many times as I want with no issues.
However, upon unexpected termination (say another process forcefully kills it), the process never regains its graphical interface! I can tell its still running but I can never set that process back to its original state.
It almost seems like the process doesn't respond to window-based Win32 API calls that set specific window features anymore (for example, I can get information with GetParent, GetWindowThreadProcessId, etc but calling ShowWindow or related results in nothing).
Any suggestions on why this is happening? I'm guessing that since I set the parent of the process to my WPF application (which then unexpectedly closes) it causes some issue in trying to recover the initial interface?
This is why it's happening (or, at least, an indication of why I had so much difficulty finding the issue out on my own); can I recover from it? And, if so, how?
Edit -
IInspectable makes a good point in the comments, question adjusted to make better sense for this particular application.
It seems I've gotten my answer; so, for the sake of completeness I'll post what I've gotten here in case anyone else has a similar issue.
According to the information provided by IInspectable in here and here (with more context in the comments), it seems that what I'm trying to do here (assign a new parent cross-process) is essentially unsupported behavior.
My Solution:
Recovering (at least at the point that I'm talking about - i.e. unexpected crashes or exits) probably isn't feasible, as we've already gone off the end in undetermined/unknown behavior. So I've decided to go for the preventative route.
Our current project already makes use of the Nancy framework to communicate across servers/processes so I'm going to "refine" our shutdown procedure a bit for my portion of the program to allow it to exit more gracefully.
In the case of a truely unexpected termination, I'm still at a loss. I could just restart the processes (actually services with a console output, in our case, but w/e) but my application is just a GUI/Interface and isn't very important when compared to the function these processes serve. I may make some sort of semaphore file that indicates whether a successful shutdown occurs and branch my code off so that it indicates that the processes are no longer visible until the next time they're restarted.
(context: Windows 10 desktop, no UWP)
For handling Windows Action Center notification activation events I use a LocalServer32 C# console application, STA and Thread.CurrentThread.Join() calls*. This works just fine. The executable is started and I get Activate calls from COM.
You start getting these calls after calling RegisterTypeForComClients and they stop after calling UnregisterTypeForComClients. The problem is, even without real concurrency in my case (at least in my direct communication with the object -- I could be wrong as I'm no COM expert) I expect some final Activate call(s) might still come in just after I called UnregisterTypeForComClients. Missing Activate calls is bad and shouldn't happen. I need to handle events for just a bit longer -- but how much longer?
Is there a by-the-book method of making sure I get all the last COM events? Something of a WaitForComMessageLoopToShutDown method? I don't want to go with 'a one second wait should be enough'.
notes
RegisterTypeForComClients is the equivalent of CoRegisterClassObject in COM.
UnregisterTypeForComClients is the equivalent of CoDisconnectObject in COM.
(*) I know I could use MTA with some synchronization, but the question applies there as well. I don't use MTA because I'd just be serializing stuff with no real concurrency.
edit -- A more elaborate description
My executable application (an out-of-process server) gets started by OLE automation in Windows because 'things' happen for me to handle. I handle these 'events' (calls to the Activate method)
knowing there could me more than one
knowing there could be time between them
using an inactivity timeout of, say, 30 seconds before self terminating
(for the user within this time span clicking multiple items, or Windows processing delays -- the latter being very small)
Upon expiry of my inactivity timeout I stop the COM object with UnregisterTypeForComClients. Now, crux of my problem: I ended my loop handling events but a new event from Windows was sent to my server just before unregister. Windows says: this event (activation) was sent, I scratch it off my list. But - my application hasn't registered it because my handling loop exited already. Event lost! I hope for a solution in the form of:
The issue described never occurs, or
Something along the lines of you need to call xyz until it returns x
As a side note, I started out with the sample (titled 'Sending toast notifications from desktop apps sample' on MSDN) on Github linked to by Hans Passant in the comments. It doesn't address this issue.
Supopse I have a unhandled exception (or a known serious, unrecoverable error). The scariest situation is a security breach, but it could apply to anything that means my state is so badly hosed I can't expect to continue safely.
What do I do?
In a traditional application, the usual technique is to end my process, quickly. as soon as possible. I'm calling Process.Exit, TerminateProcess, die, or whatever other tool the environment has that means "END. NOW". Eric Lippert's post expresses the reasoning for this attitude well.
In a production ASP.NET application running on IIS, it's not so simple. I can certainly end the current process and cough an error to the event log or wherever. That's essentially what happens with any unhandled exception. But the next time a request comes in, IIS is just going to spin up a new worker process. If my fatal error was a transient problem that's great.
But if my problem persists past the lifetime of my process, the new one won't be any better. It could even be compounded by the intialization code or a reattempt. Plus, if IIS is running multiple worker processes within the same application pool, even killing my process doesn't kill the application. Logically speaking all those other workers may be hosed too and just not know it yet.
So far I've only come up with two options.
End the process and hope for the best. Knowing that the app will just be restarted, this is pretty much the same as "catch(Exception) {}". Hardly satisfying.
"Reaching out" to tell IIS to disable the app, stop IIS, the machine, etc. This seems like a brutal hack. Moreover I'd guess it's likely to require elevated security credentials. During termination of a possibly-compromised process seems like a poor time to have those.
What I can think of are something as following:
You can go ahead use the advanced setting of an Application Pool in IIS named "Rapid-Fail protection", set the Failure Interval long enough as you like, and make the Maximum Failures as 1, then go ahead thrown the exception and make the IIS think this application pool can't work correctly so that it will send back Service Unavailable to client side or even reset the connection(depend on your setting). For more detail please check it here: Failure Settings for an Application Pool . However you need to be very careful to not overkill, I mean you need to write a very good application that all exception been handled properly and only the one you want to terminate application can really been detected by IIS, otherwise maybe a single user click just brought down your site.
Another solution is just go ahead make it your own code, I mean you can record such an error in some certain way like creating a file named SystemCrashed, and then terminate the Application, then check if file exist on Application_Startup and do nothing but terminate the Application if file been found. Something like a lock. This need more code but maybe safer than IIS settings, I mean there can't be too much overkill as long as you get it right to remove the lock.
Ok, long story short I have a Windows service that handles Win32_VolumeChangeEvent and logs USB disk device arrivals to the Event Log and to a SQL database. An additional component to this is a hidden UI (WinForms) which loads in the user session at login - this pops up a message box reminding users of company policy about USB keys etc. AFAIK, this was the best way to go since services can no longer run in interactive mode.
Anywho... architecturally, v1 of this little thing ran with the UI component handling WndProc messages for device insertion, then passed the device identifier through IPC (named pipes) to the service which would handle WMI methods / EventLog writing (as not all users have local admin rights). This had the downside of the UI element being process killed and no longer detecting device insertions.
So, current version is that the service handles Win32_VolumeChangeEvents and gets the needed details from the device, then logs to EventLog and SQL. All is outstanding and works perfectly. Except now I'm wondering what the best way to trigger the UI into displaying the popup is.
I've researched around Google and here, looking for ideas about eventing over IPC, so I can just subscribe to an event from the UI component and fire it within the service, but I'm not finding much that jumps out as being helpful. I'm also constrained to .net2, so WCF is out of the picture (although I'm not afraid of p/invoke if you want to go that way).
So. How would you do it? Links, thoughts, ramblings, pseudocode, actual code... all is appreciated. I'm trying to stick to what I believe is best practice, although I also think programming is a bit of an art form and my best practice may be someone else's horror story.
So SO - what would you do? Let me know if I need to clarify :)
Back in the bad old days of Windows API programming, we'd sometimes use RegisterWindowMessage to register a unique message ID that (presumably) only our window knew how to handle. We could then trigger that window from another application by calling PostMessage with a window handle of HWND_BROADCAST, and the msg parameter being that unique message value. That works great if everything you want to share between the processes can fit into two DWORD values (wparam and lparam). Sharing more data can be done if you allocate global memory and pass a reference as one of the parameters.
That should still be possible with .NET. Certainly there's no trouble calling PostMessage. As for handling the message in the UI code, you have to override the Form's WndProc. See How do I send/receive windows messages between VB6 and c#? for an example.
You could do something with named events, although that would only notify the UI that some change had occurred. It wouldn't actually tell you what happened. I suppose, if there's only a small set of possible events, you could have multiple events, but that gets complicated pretty quickly.
You could go the named event route and use shared memory (memory mapped file) to share the state.
Or, you could set up sockets, named pipes, TcpListener/TcpClient, or even a UdpClient. All should work, with varying degrees of complexity and/or reliability.
The only idea that comes to my mind is to have a service check the state of the UI application periodically and restart it if it has been killed. There seems to be no standard module that would run within user's session and let the service send notifications to this module. There exist third-party solutions but they can be killed (not saying that they should be installed in order to be used).
Update: after re-reading the question I think that maybe your UI doesn't receive windows messages, so you need another mechanism. Why not create a Semaphore synchronization object in service and wait for it in UI process (in a separate thread)?
I have an application which can only have 1 instance running at each time, however if a 2nd instance is launched it needs to be logged to a common logfile that the first could also be using.
I have the check for how many instances are running and I was planning on simply logging it to the event logger initially but the application can be running in user or system context and exceptions are thrown when attempting to query the eventlog source as a user so that idea is scrapped as the security logs are inaccessible to the user.
So I wanted to find out what the safest method of have 2 seperate instances of the same application write to a log file would be that would ensure both get an opportunity to write to it.
I would prefer not to use an existing additional framework if avoidable
Any help appreciated.
A Mutex could be used for interprocess synchronization of a shared resource such as log file. Here's a sample.
You could always write to the system event log. No locking or anything needed and the event viewer is more robust than some give it credit for.
In response to your comment, another user asked the question about write permissions for the event log here on SO. The answer linked to the msdn article that describes how to perform that.
See that question here.
You can dodge the problem if you prefer...
If this is a windows app, you can send the first instance a message and then just quit. On receiving the message, the original instance can write to the log file without any issues.
Why not use syslog protocol ? This will allow you to deliver the logs in a very standards-based and flexible manner. The protocol itself is quite simple, but there are plenty of examples on the Net, e.g. here. If your app is destined for the enterprise use, having a standard way of logging could be a big plus. (And, you do not need to maintain the files either - it becomes a job of a specialized software that does just that)
One way to hack it would be to memory-map the log file. That way, both instances of the application are sharing the same virtual memory image of the file. Then there are a number of ways of implementing a mutex inside the file.