I'm creating an app using WinUI3 (UNO actually, but I don't think this is relevant) to babysit an application written in 2007 that I have no control over. I'm starting it like this:
try
{
using var process = Process.Start("child.exe");
await process.WaitForExitAsync();
//...do some processing here
}
catch (Exception)
{
throw; //only here so that I can set a breakpoint to debug this issue
}
Peculiarly, when the child.exe exits it takes down the parent app with it. This is not the default behavior since starting other programs the same way do not do this. Things I have already looked into:
The catch block never catches anything. The same thing happens even if I comment out the await line and everything after.
Breakpoints after the try block are not hit. Visual Studio debugger simply detaches from the parent app.
Event Viewer does not log any error events related to this.
Attaching spy++ to the parent app shows that WM_Close isn't being sent to it. In fact, the moment the child terminates spy++ logs no more messages from the parent at all. (If I close the parent app normally then spy++ does log window messages associated with closing)
Overriding App.Closed event and setting WindowEventArgs.Handled = true does not prevent the parent from dying. (The close button is disabled as expected, so the event is working fine)
At this point I'm pretty sure the child.exe is actively doing something to kill the parent, although running the program directly doesn't seem to do the same thing to explorer. While I'm curious about what it could be doing to cause this, I'm more interested in ways to prevent my parent app from dying.
Related
I have a simple process that accesses the Excel application object. It subscribes to an event and then attaches a debugger to itself.
The entire source code of the app is as follows:
void Main()
{
var excel = (Application)Marshal.GetActiveObject("Excel.Application");
// if any event has a subscription, attaching the debugger
// freezes the message loop in Excel while the debugger is paused
excel.WorkbookNewChart += (a,b) => {};
Debugger.Launch();
}
When the debugger (e.g. Visual Studio) starts, it freezes (all the threads in) my console app.
What I find puzzling is, this also blocks the message loop in Excel, making Excel unresponsive. However, the message loop in Excel is only blocked if I subscribe to some event, e.g. WorkbookNewChart. It doesn't matter which event and it doesn't matter if the event is fired or not.
My questions are:
Why might attaching the debugger to this console app freeze Excel's message loop and is there something I can do prevent it?
I'm only seeing the behavior of Excel as a black box - are there any tools I could use to figure out what might be blocking the message pump in the Excel process?
[Update: running the same three lines of code in a WPF window's Loaded event handler has the same outcome.]
Background - why I'm interested in this:
I'm making an IDE inside Excel which can be used to build small apps. These apps run in their own processes but access Excel via Marshal.GetActiveObject. My IDE is an Excel add-in running inside the Excel process. I'd like my IDE to be able to debug the runner processes that I spawn from the IDE. Things seem to work ok when starting the apps, but I get deadlocked in situations like the one above, where the debugger freezes the runner process which then blocks the excel process, which makes me unable to use the debugger.
I can, of course, run my debugger/IDE in another separate process, but from a user experience perspective I'd love to keep it inside the Excel task pane if possible.
I have to enumerate all process running on my machine and notify if some changement will happen (for example: change of visibility of windows, open a new window, close a window).
To enumerate all processes I can use this function provided by MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspxI thought that I need to save a list of running processes and check (how without polling?) if it changes. Can I do it without saving current running processes?
For the visibility changes here https://msdn.microsoft.com/it-it/library/windows/desktop/ms646274(v=vs.85).aspx I found that VM_ACTIVATE message is sent to both windows. How can I catch it? Can I do it in another way?
For whom is interested in this topic, I found that to check if a window is created or destroyed I've to use SetWinEventHook(), like in the example of its MSDN page. I simply check if event value is EVENT_OBJECT_CREATE or EVENT_OBJECT_DESTROY. For other events, check the event constants list.
I have a piece of code in C# that's essentially like the following...
WriteFile();
try {
RunTest();
} finally {
DeleteFile();
}
Now this has been planned so that even on failure, it cleans up the files it left behind. This works when not run in debug mode (although it pops up a message asking if I want to debug the program or close it. Closing it produces the appropriate results).
When I run this in debug mode and hit an exception inside of RunTest, I only seem to have two options. In the first one, I tell debugging to stop. This is equivalent to killing the program and the block in finally does not run (so the file doesn't get deleted like it should). If I tell it to continue, it doesn't propogate the exception up and instead, it just hits an exception somewhere else.
Is there anyway to get debug mode to continue like a normal program after hitting an exception?
From the Debug menu, choose Exceptions (or use Ctrl + Alt + E). This will bring up a dialog where you can uncheck appropriate checkboxes in the "User-unhandled" column for exceptions which you don't want to stop at while debugging.
I believe that will make exception propagation work normally. And you can still set a breakpoint either in the try or finally block to see what's happening.
Check Debug/Exceptions if there are any exceptions set.
Another option would be to handle the event Application.ThreadException (Windows Forms) or Application.UnhandledException (Silverlight etc.) and tell the application to continue or exit, depending on the severity of your exception.
Here's the problem: The main GUI thread is performing a SendMessage to another GUI thread (yes, there are multiple GUI threads, and unfortunately this cannot change). When that second GUI thread receives the SendMessage, it may decide to display a message box. Some of the time, that MessageBox will 'freeze' the entire application.
More specifically, the message box shows up, but the entire GUI is hung (user input does not work anywhere).
I've verified with a debugger that the second GUI thread is spinning in the DialogBox2() function defined in user32.dll. I can see in the disassembly that a message pump is being executed (I see IsDialogMessage/TranslateMessage/DispatchMessage being called). Using spy++, I do not see any messages being processed for the message dialog box window. I do see messages getting processed on the main GUI window (such as WM_SETCURSOR, though I do not thin they are being processed as I believe SendMessage doesn't execute a message pump).
The second thread is executing code that is part of an MFC extension DLL, if that matters.
I've tried using AfxMessageBox() / CWnd::MessageBox / ::MessageBox(NULL parent window,...). All exhibit the same problem.
Has anyone seen anything similar before?
Thanks,
Andrew
It must be that blocking one of the GUI threads causes the problem.
Try this:
Replace the ::SendMesage with ::PostMessage followed by a ::MsgWaitForMultipleObjects loop. You will need to pass an event handle that signals when the message box is closed.
It will probably solve the problem.
Just be careful which messages you dispatch in you ::MsgWaitForMultipleObjects loop.
According to Using Rich Edit Controls I use RichEdit in such way:
MyControl::OnCreate()
{
handle = LoadLibrary(_T("Riched20.dll"));
}
MyControl::OnDestroy()
{
FreeLibrary(handle);
}
It works fine for win32 but recently I’ve built x64 configuration and now my control fails after the page reload.
I’ve noticed that if do this:
MyControl::OnCreate()
{
handle = LoadLibrary(_T("Riched20.dll"));
FreeLibrary(handle);
handle = LoadLibrary(_T("Riched20.dll"));
}
everything works fine.
I don't wish to put this code into production, so is there any suggestions about better solution/workaround?
Since the reported fault module is Richedit20.dll_unloaded it means you are unloading the DLL while code from it is still in use.
For example, if you still have a richedit window open when you (completely) free the DLL, you can see crashes like that as soon as anything triggers a call to the control's window-proc. This is because the control's window-proc was inside the unloaded DLL code.
It should be safe to call LoadLibrary and FreeLibrary multiple times (so long as the calls balance out), so I doubt that is the problem. It may just be triggering the problem. Also, the problem was there in 32-bit builds; you just got lucky and never triggered it.
OnDestroy is the wrong place to call FreeLibrary. There are several window messages which get sent to a window after WM_DESTROY (e.g. WM_NCDESTROY).
Child windows also still exist when OnDestroy is called. If the richedits are children of your control (rather than the control itself) then moving the FreeLibrary into OnNcDestroy may save you. (Child windows are destroyed by the time WM_NCDESTROY is called.) I'd still say it's not a good place to free the library, however.
So you definitely want to move your FreeLibrary call. I would move both it and the LoadLibrary completely out of the control itself. It's not normal to have controls which load/free libraries whenever an instance of them is created. Instead, have some static init/uninit code somewhere which loads the libraries you need once and for all and frees them when the application is shutting down.
(If your app only rarely uses the control then it might make sense to load/free the library only when windows using the control are active. That situation is rare, though. Usually you're better off just leaving the DLL loaded.)