CefCharp causing program termination to halt - async-await

My program has decided to stop terminating when it is done.
The program is spawned by a service, The Main() function calls some external classes I created which make some PDFs and then terminates with a Return. There are no forms, no UI. This has worked for years.
I have now tried End, Application.Exit() and Environment.Exit(0)
I just added some functionality using CefCharp to one of the external classes the program uses and as part of that I have added some Async functions and Awaits to this class. As far as I can tell I am Dispose()ing each instance of the CefSharp browser I am creating. I am also calling CefSharp.Cef.Shutdown() at the end of the same function that calls CefSharp.Cef.Initialize(). All Awaits appear to be returning fine so I don't think I am leaving any threads hanging.

So it turns out that putting CefSharp.Cef.Shutdown() at the end of the same function that initializes it and does most of the work does not seem to be adequate or maybe it is still busy and not ready for shutdown?
So I put another CefSharp.Cef.Shutdown() in my classes' Dispose() method. Now my program terminates properly.

Related

Detect UI operation which will "hang" the application if running in service mode

Fellow experts!
I have faced the following dilemma: some of our tools (executables) are started as scheduled tasks, some are started as services and others as usual desktop apps with interactive Windows user. We are using the code sharing strategy for source management (this is not debatable for this question).
So the solution I want to find is the following:
Detect UI operation at run-time which leads to hanging service/background task (such as say call to Application.ShowException, ShowMessage, MessageDialog, TForm.Show etc.). And when such an action detected I want to raise the exception instead. Then the operation will fail, we will have stack trace etc. but the process will not hang up! The most problematic hang up is when some event processing is done in transaction and then in some of the code used to process event suddenly (because of error in code, design, whatever) there is UI code executed then the process hangs and the DB parts can be locked!
What I think I need to do is: Use DDetours library to intercept WinAPI calls to a certain routines and raise exception instead (so that the process does not hang, but just fail in some method). Also I know that the creation of forms and windows does not hang the app, but only the tries to show them to the user.
Is there some known method of handling this problem? Or maybe there is some list of WinAPI routine set which hangs in service mode?
Thank you in advance.

ExitProcess behaviour in Windows in relation to atexit handlers

I want to be able to catch any attempts of executing exit()/ExitProcess()/TerminateProcess() or any other such calls.
I thought about registering a handler with atexit(). This works fine for normal program termination (return from main()) or exit() calls (regardless of the thread that calls exit()), but ExitProcess() and TerminateProcess() bypass the handler I registered.
ExitProcess() documentation states:
Note that returning from the main function of an application results
in a call to ExitProcess.
But the observed behaviour is at least different in this regard.
Is there a method of registering a handler for process exit/termination what will always be called (except for external calls to TerminateProcess(), unhandled exceptions thrown by one of my threads or __failfast() calls, I'm guessing these are really impossible to catch).
There is the dirty option of hooking ExitProcess(), but I'd rather not do that.
EDIT: just so this is clear: I'm interested in my own process, not monitoring / controlling another process.
There is a Kernel Mode Event a device driver can subscribe to in order to get notifications of terminations of processes. This is preferred over trying to inject a DLL into processes for API hooks due to the myriad number of internal and external ways that process may end.

how to prevent multiple program loading in windows?

I am developing an windows application.
what I want is to prevent this application running multiple in single OS.
(e.g. we can run multiple instance of notepad.exe, calc.exe at the same time... but I don't want this)
what is the most effective way to implement this?(preventing multiple instance of process running at same time)
I'd rather not use methods like checking process names or sharing some global file as a signal... since it is too easy to circumvent
thank you in advance
This is typically done with mutexs. When your process launches you call CreateMutex and check the return value. If it succeeded then this is the first launch, otherwise there is another instance of your process alive. Your mutex should be in the Global\ namespace. Also make sure to ReleaseMutex when your program finishes running.
What framework are you using? I'm assuming it's .Net? Here's a post from an msdn foum on the same thing.
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/3e139912-45ea-432e-b9e0-e03640c07c9f/
You mentioned you don't want to check current process names or use a global file.
Lock the current executable
.NET example code:
System.IO.File.Open(
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.None);
The FileShare.None keeps any other process (like Windows Explorer) from executing the file until the app closes or the file handle (returned object) is explicitly closed.
Global Mutex
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682411%28v=vs.85%29.aspx
If the mutex is a named mutex and the object existed before this
function call, the return value is a handle to the existing object,
GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored,
and the calling thread is not granted ownership. However, if the
caller has limited access rights, the function will fail with
ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.
Global mutex is the easiest way. To clarify another answer you don't just check the return value you check the GetLastError value as well.

How to override an application's single instance limit in Windows?

I am trying to override the singe instance limit of an application for which I don't have the source. I know that the app is using the good ol' trick of using CreateMutex to determine whether there is another instance running. (If the mutex is created successfully it proceeds, if getlasterror says that the mutex has been created it quits immediately). I found that through sniffing the Win32 api calls.
I thought using Detours would do the trick, but it doesn't quite work out. I am intercepting CreateMutexW, but for some reason, it doesn't catch the first four calls to it. (Again I know what these calls are by sniffing win32 calls and looking at the name of the mutexes). I do get the fifth one intercepted, but the one I actually want to intercept is the first one.
I am using detours through the sample application withdll. I wonder if the problem is that detours is kicking in too late or because of some kind of protection these calls may have. Is detours the best approach? Perhaps using something else may be a better idea?
There might be several reasons for the situation you describe. Here are the most probable of them:
The CreateMutexW call you need to catch occurs within the DllMain
method of one of the DLLs that are imported by the process, and you
are using the DetoursCreateProcessWithDll() function to inject your
code. Detours injects your DLL by placing it at the end of the
process executable import list, and hence all the DLLs that are
imported by the process would be loaded and initialized within the
process prior to yours. In order to overcome this, try using
CreateProcess(CREATE_SUSPENDED) and CreateRemoteThread()-based
injection, although this method raises its own challenges.
The API that is used in the first call is different. Have you tried
overriding CreateMutexExW? Are you sure ANSI methods call Unicode
ones?
Hope this helps.

How to determine the association between a VB6 app and an exe instanced with CreateObject()

We need to figure out how a service can peek at a running VB6 app and/or its DCOM spawned exe and figure out which VB6 app goes with which DCOM exe. The VB6 app and the spawned exe are both on the same server.
We have a VB6 app that spawns an instance of Bartender (from Seagull Scientific) by way of a CreateObject() call. On a given server, we may have ten or twenty instances of our app, each represents a handheld RF gun client in a warehouse. 95% or more of these VB6 apps will have their own Bartender.
Due to circumstances beyond our control, randomly, one of our VB6 instances will be killed, just as if you killed it using Task Manager. This leaves it's Bartender still alive and consuming resources. After fifty or so have been killed over the course of a few hours or days, these orphaned Bartenders become enough of a resource hog to bring the server to its knees.
We are trying to develop a watcher service to detect which of the Bartenders are still connected, so this new service can kill the orphaned Bartenders. We are trying to accomplish this without changing our VB6 app, but we will modify our app if we have to.
I think this routine, aptly named Who's Your Daddy, might be of use to you. It figures out who spawned the process. It probably won't solve your entire problem, but it's a start.
This is going to be hard, if not impossible, to do. Out-of-process COM components (i.e. ActiveX EXE's) are always started by the COM Service Control Manager, not by the process that called CreateObject. This is why the parent process for the ActiveX EXE is svchost.exe.
Therefore, there is no direct parent-child relationship between the process that calls CreateObject and the process that gets created. Only the remote procedure call (RPC) layer that actually passes method calls back and forth between the two processes knows the identities of the processes involved, but the RPC mechanism is specifically designed to be transparent to the COM subsystem, and there isn't an easy way to get access to this information that I know of.
However, there is a pretty hackish way to handle the orphaned process problem if you are willing to change the VB6 application:
Have your monitor service periodically terminate all running Bartender EXE's (once a day or however often is necessary to prevent the server from slowing down too much).
Write a wrapper DLL for the Bartender functionality, and have your VB6 class use this wrapper library instead of directly instantiating raw Bartender objects. This library would contain a wrapper class that creates a Bartender object, and that has methods that delegate to this object. Each wrapper method should catch error 462 ("The remote server machine does not exist or is unavailable"), recreate the Bartender object if this occurs, and then retry the method.
For example (I haven't actually looked at the Bartender documentation, so this is just demonstrating the idea):
'BartenderWrapper.cls
Private m_bartender As Object
Private Sub Class_Initialize()
Set m_bartender = CreateObject("Bartender.Application")
End Sub
Public Sub PrintLabel(Byval sLabelData As String)
On Error Goto ErrorHandler
m_bartender.PrintLabel sLabelData
Exit Sub
ErrorHandler:
If IsRpcError(Err) Then
Set m_bartender = CreateObject("Bartender.Application")
Resume
End If
Err.Raise Err.Number, Err.Source, Err.Description
End Sub
Private Function IsRpcError(Byval e As ErrObject) As Boolean
IsRpcError = (e.Number = 462)
End Function
The idea here is that since you can't reliably determine which Bartender processes are still connected to an instance of your VB6 application, you can kill all of the running Bartender processes periodically, and your application will still be able to run properly (in most cases), because if you kill a Bartender EXE that was being used by a running instance of your VB6 application, your application will create a new Bartender instance and continue running normally.
This solution definitely isn't fool-proof, and may be hard to implement if you are using a lot of methods or the Bartender instance you create has important internal state that could be lost when creating a new instance.
When it comes down to it, there isn't a clean way to detect orphaned ActiveX EXE's if you don't control all of the applications that are involved (one common solution when you do control the ActiveX EXE is to have the ActiveX EXE raise an event with a ByRef parameter every second or so, and have it shut itself down if the client doesn't change the value of the parameter).
What we have decided to do is to have the client write a hint file each time the Client creates a Bartender. The client writes a tiny XML file in a common folder that says an XML equivalent of "I am PID number n. Between time x and time y, I created a Bartender." The times x and y are timestamps obtained immediately before and after the CreateObject call. We will have a monitor service that watches for new Clients, new Bartenders and hint files. By watching all these, we think we can create small groups or associations of clients and their associated bartenders. In any given group, when all the clients go away, any remaining Bartenders that were in that group can be KILLED!

Resources