I have an application that sometimes causes exceptions. And I need to restart it if it crashed. But the problem is, that I have Windows 7 here and when application crashes, Windows shows me nice dialog box with a suggestion to close the application. But the application itself is still running until I click "Close". How to get rid of this Window and make application terminate immediately without any dialog boxes?
Ideally you would catch all exceptions in the most outer scope of your program. However, sometimes you don't have the luxury of making such changes and the crash dialogs prevent you from recovering from a crash. In these cases you can consider disabling Windows Error Reporting, either entirely or for a specific program.
On Windows 7: Start Orb -> Control Panel -> Action Center -> Maintenance -> Check for solutions to problem reports -> Settings
Update: to completely disable the error reporting UI change the DontShowUI registry setting:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\DontShowUI
You can use the concept of the Dr Watson for detecting the crash and restarting the application. Use the following:
Set a Timer like:
SetTimer( eIsDwwin, 30000, NULL);
This will check the Dr Watson process after every 30 seconds in the system process using the following:
void CMainFrame::OnTimer(UINT nIDEvent) {
case eIsDwwin:
HANDLE hndl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
DWORD dwsma = GetLastError();
DWORD dwExitCode = 0;
PROCESSENTRY32 procEntry={0};
procEntry.dwSize = sizeof( PROCESSENTRY32 );
Process32First(hndl,&procEntry);
do {
if(((!strcmpi(procEntry.szExeFile,"dwwin.exe"))||
(!strcmpi(procEntry.szExeFile,"drwatson.exe"))||
(!strcmpi(procEntry.szExeFile,"drwtsn32.exe"))||
(!strcmpi(procEntry.szExeFile,"WerFault.exe"))) &&
(procEntry.th32ParentProcessID == GetCurrentProcessId())) {
WSACleanup();
PostMessage( WM_CLOSE);
Sleep(500);
if(0==strcmpi(procEntry.szExeFile,"dwwin.exe")) {
system("TASKKILL /IM dwwin.exe /F");
} else if(0==strcmpi(procEntry.szExeFile,"drwatson.exe")) {
system("TASKKILL /IM drwatson.exe /F");
} else if(0==strcmpi(procEntry.szExeFile,"drwtsn32.exe")) {
system("TASKKILL /IM drwtsn32.exe /F");
} else if(0==strcmpi(procEntry.szExeFile,"WerFault.exe")) {
system("TASKKILL /IM WerFault.exe /F");
} else {
system("TASKKILL /IM WerFault.exe /F");
}
break;
}
} while(Process32Next(hndl,&procEntry));
CloseHandle(hndl);
break;
}
}
This will close the application which has crashed, gracefully.
Anothe way would be to use the Signal API in Windows for handling the exceptions and crashes.
Not knowing the language of your application makes it a little tough, but you can typically handle that by running your application within the equivalent of a try / catch block (as in C#, C++, or Python). In pseudo-Csharp-ish-code:
bool done = false;
main()
{
while( !done )
{
AppClass aclass = new AppClass();
try
{
aclass->Run();
}
catch( Exception x )
{
LogErrorSomehow(x);
delete aclass;
continue;
}
}
}
Essentially, the best way to get around an "unhandled exception" error is to handle the exception by catching it and taking appropriate action (even if that action is doing nothing).
In this example, if someone wanted to close your app you'd set the "done" value to true and return from Run().
Related
I working on an MFC class which derives from CWnd and creates a hidden window in its constructor. The object itself is constructed inside a derived CWinApp::InitInstance function.
if (
this->CWnd::Create(
nullptr,
nullptr,
WS_DISABLED, // Even disabled it will receive broadcast messages.
{0, 0, 0, 0},
CWnd::GetDesktopWindow(),
fakeWindowId
) == FALSE
)
throw runtime_error{"failed to create window"};
When I run this code in a debug build it triggers the following assertion:
Debug Assertion Failed!
Program: C:\WINDOWS\SYSTEM32\mfc140ud.dll File:
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp Line: 571
For information on how your program can cause an assertion failure,
see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
If I ignore the assertion, the code works fine and no ill effect is observable. How do I address this assertion?
I'm registering the window as follows as well:
BOOL HiddenWindow::PreCreateWindow(CREATESTRUCTW& cs)
{
if ( ! CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
WNDCLASSEXW wc;
ZeroMemory(&wc, sizeof(WNDCLASSEXW));
wc.cbSize = sizeof(WNDCLASSEXW);
const auto instance{AfxGetInstanceHandle()};
if (GetClassInfoExW(instance, this->className_.c_str(), &wc) == FALSE)
{
wc.lpszClassName = this->className_.c_str();
if ( ! RegisterClassExW(&wc))
{
Logger::Fatal(
"Registering the window for copy data message failed! Messages will not be "
"copied, error code {}.",
GetLastError()
);
return FALSE;
}
}
else
Logger::Debug(
"There is already a window registered under the class name '{}'.",
toString(this->className_)
);
cs.lpszClass = _wcsdup(this->className_.c_str());
return TRUE;
}
So, I was unable to ever figure out what caused the MFC assertion. The solution was to remove the MFC window entirely and replace it with a Win32 window underneath the class, i.e. CreateWindowExW, GetClassinfoExW, and RegisterClassExW.
We have an application that misbehaves when the user changes the date format in his Windows region settings. (Yes, the solution would be to fix the misbehaviour--- not the point here.)
Changing the settings braodcasts a WM_SETTINGCHANGE message to all applications. We're trying to avoid our problem by ignoring this message and keep the date format as it was (for now, as a hotfix).
Whatever I do, the TMonthCalendar component still changes its format, as well as TDateTimePicker which uses TMonthCalendar as its popup.
I tried (all with the same result):
Overriding TForm::WndProc()
void __fastcall TfrmMainWindow::WndProc( TMessage & msg )
{
if( msg.Msg == WM_SETTINGCHANGE ) return; // ignore
TForm::WndProc( msg );
}
Setting a hook with Application->HookMainWindow( hookWindowsMessage );
Setting TApplication.UpdateFormatSettings = false;
Setting Application->OnEvent = onApplicationEvent; to catch all events... but unfortunately this specific case falls under the "OnMessage only receives messages that are posted to the message queue, not those sent directly with the Windows API SendMessage function." rule.
It would seem that overriding WndProc() is almost a good idea, only that it only affects that one window, not the application as a whole. I thought that's what Application->HookMainWindow() was for, but apparently not.
Anyone any idea how to solve or circumvent this problem?
As Cody Gray states in the comment above, the problem is not the message handling but the TMonthCalendar component which uses the Win32 API calendar and thus works outside the application context.
However, for all other components (ie. TDateTimePicker's line edit) and internal global variables (like ShortDateFormat etc.) it is possible to ignore the format change as follows:
class TfrmMainWindow : public TForm
{
public:
__fastcall TfrmMainWindow( TComponent * Owner )
: TForm( Owner )
{
Application->HookMainWindow( hookWindowsMessage );
}
__fastcall ~TfrmMainWindow()
{
Application->UnhookMainWindow( hookWindowsMessage );
}
private:
bool __fastcall hookWindowsMessage( TMessage & msg )
{
if( msg.Msg == WM_SETTINGCHANGE )
{
String sLParam( (char *)msg.LParam );
// Check for Region Settings change (not Desktop background etc.)
if( sLParam.LowerCase() == "intl" )
{
return true; // ignore message
}
}
return false; // handle message as usual
}
};
Sources:
"Trapping Messages Sent to an Application"
"TMonthCalendar displays dates according to the system locale (ignoring the BiDiMode setting)."
"The Win32 API provides a control used to select dates on a colorful calendar. The dates used and the way they display are based on the Regional Settings of the Control Panel."
I am using JNA to access User32 functions (I dont think it has got to do with Java here, more of concept problem). In my application, I have a Java process which communicates with the Canon SDK. To dispatch any messages I am using the below function:
private void peekMessage(WinUser.MSG msg) throws InterruptedException {
int hasMessage = lib.GetMessage(msg, null, 0, 0);
if (hasMessage != 0) {
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
Thread.sleep(1);
}
peekMessage is called in a loop and it all works well. Whenever an Image is taken from camera, I get the event and do the rest.
But I have observed, say after about 15 seconds (sometimes never or sometimes just at start) of no activity with camera, taking picture does not give me any download event. Later the whole application becomes unusable as it doesn't get any events from camera.
What can be the reason for this? Please let me know of any other info needed, I can paste the respective code along.
Edit:
Initialization:
Map<String, Integer> options = new HashMap<String, Integer>();
lib = User32.INSTANCE;
hMod = Kernel32.INSTANCE.GetModuleHandle("");
options.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
this.EDSDK = (EdSdkLibrary) Native.loadLibrary("EDSDK/dll/EDSDK.dll", EdSdkLibrary.class, options);
private void runNow() throws InterruptedException {
while (!Thread.currentThread().isInterrupted()) {
Task task = queue.poll();
if (task != null) {
int taskResult = task.call();
switch (taskResult) {
case (Task.INITIALIZE_STATE):
break;
case (Task.PROCESS_STATE):
break;
case (Task.TERMINATE_STATE): {
//queue.add(new InitializeTask());
Thread.currentThread().interrupt();
break;
}
default:
;
}
}
getOSEvents();
}
}
WinUser.MSG msg = new WinUser.MSG();
private void getOSEvents() throws InterruptedException {
if (isMac) {
receiveEvents();
} else {
peekMessage(msg);
}
}
Above, whenever I get my camera event, it add's it to the queue and in each loop I check the queue to process any Task. One more important information: This is a process running on cmd and has no window. I just need the events from my camera and nothing else.
The code where I register callback functions:
/**
* Adds handlers.
*/
private void addHandlers() {
EdSdkLibrary.EdsVoid context = new EdSdkLibrary.EdsVoid(new Pointer(0));
int result = EDSDK.EdsSetObjectEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsObjectEvent_All), new ObjectEventHandler(), context).intValue();
//above ObjectEventHandler contains a function "apply" which is set as callback function
context = new EdSdkLibrary.EdsVoid(new Pointer(0));
result = EDSDK.EdsSetCameraStateEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new StateEventHandler(), context).intValue();
//above StateEventHandler contains a function "apply" which is set as callback function
context = new EdSdkLibrary.EdsVoid(new Pointer(0));
result = EDSDK.EdsSetPropertyEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new PropertyEventHandler(), context).intValue();
//above PropertyEventHandler contains a function "apply" which is set as callback function
}
You are getting ALL messages from ALL windows that belong to this thread, that includes all mouse moves, paints etc. if you aren't rapidly calling this function your message queue will overflow and cause the behavior you describe.
The sleep you definitely don't want as GetMessage yields if no message is waiting.
So if there exists a normal message pump(s) (i.e GetMessage/DispatchMessage) loop somewhere else for this threads window(s) then you should let that pump do most of the work, perhaps use wMsgFilterMin, wMsgFilterMax to just get the event message you require; or even better in this case use peekmessage with PM_NOREMOVE (then you will need your sleep
call as peekmessage returns immediately).
Alternatively provide the hWnd of the window that generates the event to reduce the workload.
Use spy++ to look into which windows this thread owns and what messages are being produced.
To take this answer further please provide answers to: what else is this thread doing and what windows does it own; also is this message pump the only one or do you call into the SDK API where it may be pumping messages too?
There is an OpenSource project wrapping EDSDK with JNA and it has a version of your code that is probably working better:
https://github.com/kritzikratzi/edsdk4j/blob/master/src/edsdk/api/CanonCamera.java#L436
Unfortunately this is not platform independent and specifically the way things work on windows. I am currently in the process of trying to get a MacOS version of things working at:
https://github.com/WolfgangFahl/edsdk4j
i want to use ILspy debug a dll,as pic:
but it only can show two process:
but in vs2010,i can attach more process:
how to show w3wp.exe in ILspy? who can help me?
Running ILSpy as an administrator solved this problem for me.
From the ILSpy source code (ICSharpCode.ILSpy.Debugger.UI.AttachToProcessWindow):
Process currentProcess = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcesses()) {
try {
if (process.HasExited) continue;
// Prevent attaching to our own process.
if (currentProcess.Id != process.Id) {
bool managed = false;
try {
var modules = process.Modules.Cast<ProcessModule>().Where(
m => m.ModuleName.StartsWith("mscor", StringComparison.OrdinalIgnoreCase));
managed = modules.Count() > 0;
} catch { }
if (managed) {
list.Add(new RunningProcess {
ProcessId = process.Id,
ProcessName = Path.GetFileName(process.MainModule.FileName),
FileName = process.MainModule.FileName,
WindowTitle = process.MainWindowTitle,
Managed = "Managed",
Process = process
});
}
}
} catch (Win32Exception) {
// Do nothing.
}
}
Seems relatively straight forward...
It is preview software, so perhaps there is a flaw in this algorithm for determining if a process uses managed code.
You might be able to move pass this issue just by downloading the source code and changing
bool managed = false;
to
bool managed = true;
and recompiling.
I don't have the full version of IIS7 installed so I can't attempt to recreate your issue, but I doubt I would have the same problem anyways because my visual studio development server shows up fine in ILSpy while yours does not. Perhaps there is something different about your environment that messes with the above algorithm.
32-bit vs 64-bit might also play some role
in the ServiceStart() call of a windows service, I create a thread and start it.
Thread1 = New TThread1(false)
In the Execute procedure of the subthread, there is a loop that runs forever and does that the service is supposed to do.
The problem is that when I get an error in this thread, I want to terminate the thread, and stop the service too.
How can I get the service to stop itself if a thread that it has started stops (fails).
A possibility is to use watchdog timers:
in your thread you reset the timer (eg. every time you enter the loop).
when interval of timer is expired, you know that the thread is probably not working anymore, so you can restart the service or what ever...
A better approach might be to catch exceptions in the thread and log them. Or you could catch the exception, log it, then stop the service. That way you are in control of the service stopping and you also have some insight into the errors being generated.
make a call to stop service :
bool StopService(string svr_name)
{
bool ret = false;
if (svr_name.Length > 0)
{
try
{
ServiceController sc = new ServiceController(svr_name);
if (sc.Status == ServiceControllerStatus.Stopped)
{
return true;
}
sc.Stop();
}
catch (Exception)
{
return false;
}
}
return ret;
}