ActiveBlog

Supressing the Windows Error Report MessageBox with Subprocess and Ctypes
by

, November 27, 2007

Hands up, anyone who's written a Python script that was supposed to run for a long period of time unattended on a Windows box, only to come in the next morning to see this kind of dialog box on their...

Hands up, anyone who's written a Python script that was supposed to run for a long period of time unattended on a Windows box, only to come in the next morning to see this kind of dialog box on their screen 5% of the way through?

You wrote your script to handle failures of subprograms, but instead it got stuck waiting for a user to push a button before it would continue. [I can't convince typepad to display the full-size image, but it's the ubiquitous Windows crash notification dialog box that makes sense for graphical apps, but not for command-line ones.  Click on the graphic if you want to see the original].

This is an easy four line fix in Python, as long as you're either using Python 2.5, or have ctypes installed.

At some point in your program's initialization state, state that you don't want the process to put up the crash notification dialog:

        if sys.platform.startswith("win"):
            # Don't display the Windows GPF dialog if the invoked program dies.
            # See comp.os.ms-windows.programmer.win32
            #  How to suppress crash notification dialog?, Jan 14,2004 -
    #     Raymond Chen's response [1]
   
            import ctypes
            SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
            ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX);
            subprocess_flags = CREATE_NO_WINDOW
        else:
            subprocess_flags = 0

Now when you launch your sub-processes, make sure on Windows that you don't 'or' the CREATE_DEFAULT_ERROR_MODE flag in, or the subprocess will put up the notification dialog if it crashes.

        import subprocess
        subprc = subprocess.Popen(self._cmd,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.STDOUT,
                                  shell=True,
                                  cwd=self._cwd,
                                  universal_newlines=True,
                                  creationflags=subprocess_flags)

[1] Reference: http://groups.google.com/group/comp.os.ms-windows.programmer.win32/tree/browse_frm/thread/eeade5ecfa04d000/658b412a62ef5d7a?hl=en&rnum=1
(http://tinyurl.com/2cycse for the full tree-view)

Subscribe to ActiveState Blogs by Email

Share this post:

Comments

12 comments for Supressing the Windows Error Report MessageBox with Subprocess and Ctypes
Permalink

Good call. I actually wrote this code to deal with running perl and wperl. I suppose I could write a Python extension that deliberately triggers a seg fault, but it was handier to simply run this Perl code (using the seemingly moribund http://search.cpan.org/~kevina/Fraction-v.53b/ package from CPAN).

Permalink

Hi,

WER (Windows Error Reporting)has settings that can be used to turn on queued and headless reporting.

For Windows Vista the following settings can be used:

KEY:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting

VALUE NAME:
ForceQueue

VALUE TYPE:
REG_DWORD

Turn the value to 1 to enable forcequeue.

No UI is shown in force queue mode, but you will still be able to investigate the crashes as the crash data is logged.

For Windows XP

KEY:
HKLM\Software\Microsoft\PCHealth\ErrorReporting

VALUE NAME:
ForceQueueMode

VALUE TYPE:
REG_DWORD

Turn the value to 1 to enable forcequeue.

Please feel free to email at kinshu [at] microsoft [dot] com if you need more input and I will be glad to help.

Thanks

Permalink

When you make a change to the registry, isn't that global? Here's my use case:

* you have a GUI app where if there's a crash, you want to present the crash notification dlg

* the GUI app runs a windowless console program out-of-proc -- you communicate with it via stdin/stdout/stderr

* By temporarily setting the error level as I demonstrated while running the subprocess, the notification is suppressed. Other apps behave the same.

Am I missing something by not using the registry?

Permalink

Hi,
I am trying to use the above code to supress the crash dialog for python.exe. I am not able to understand what does this mean
"Now when you launch your sub-processes, make sure on Windows that you don't 'or' the CREATE_DEFAULT_ERROR_MODE flag in, or the subprocess will put up the notification dialog if it crashes"
I tried using the above code but I still get the crash dialog..

Thanks in advance for your help

Permalink

Could you post your code? It's hard for me to answer your question otherwise.

Permalink

Sorry for the late response..
The code below still does not supress the crash dialog. I am running this on Windows XP with python 2.5.1.
----

import sys,glob,subprocess

if sys.platform.startswith("win"):
# Don't display the Windows GPF dialog if the invoked program dies.
# See comp.os.ms-windows.programmer.win32
# How to suppress crash notification dialog?, Jan 14,2004 -
# Raymond Chen's response [1]

import ctypes
SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
#ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)
#This may be required as suggested in http://bytes.com/forum/thread282039.html
ctypes.windll.kernel32.SetErrorMode(ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)|SEM_NOGPFAULTERRORBOX)
subprocess_flags = 0x8000000 # hex constant equivalent to win32con.CREATE_NO_WINDOW
else:
subprocess_flags = 0

#Get a list of all .py files
pyTestList = glob.glob("c:\\temp\\*.py")

#Path to PyExe
pyExec = sys.executable

#Run each pyfile

for pyfile in pyTestList:
testToRun = pyExec + " " + pyfile
p = subprocess.Popen(testToRun,stdout=None,stderr=None,shell=False,universal_newlines=True,creationflags=subprocess_flags)

Permalink

ctypes.windll.kernel32.SetErrorMode(ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)|SEM_NOGPFAULTERRORBOX)

should just be

ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)

Also my code sets shell=True, yours sets it to
False. That might cause a problem as well.

Good luck.

Permalink

Actually i had tried ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX) but that would still not suppress the crash dialog..
I don't want to use shell=True as that causes an extra cmd.exe process along with python.exe when i call a.py file. Also with shell=True the pid returned by Popen() is that of cmd.exe and not python.exe. So If i need to terminate the process I can only terminate cmd.exe and have no control over the python.exe started by cmd.exe.
I will next try the Registry settings suggested in the comments above.. But that's not a neat solution as I have to make sure i flip the registry value back after the script is run..

Permalink

I tried the same python code (which has shell=False) to call a C++ exe which crashes when called(the code for the exe dereferences a null pointer). I was able to supress the crash dialog when I launch this exe. So now the question is can the crash dialog produced by python.exe be suppressed. Do you have a .py file which when run causes the python.exe to crash? You mentioned about perl extension in your blog post. My email is deelesh [at] gmail [dot] com

Thanks for your help

Permalink

I finally got the crash dialog to get supressed. The code that you provided in the blog works. I actually got a .py file which would produce a crash for python.exe and then ran your code. The dialog was suppresed. However the kind of python.exe crash that i was getting was i think beyond SEM_NOGPFAULTERRORBOX and so it would still show up. I even tried using the registry setting mentioned above. But that would result in a different dialog box.
So I eventually solved this by using AppActivate and SendKeys methods in VBScript to detect and send ALT+C keys to python.exe dialog. I used a seperate process to launch the vbscript and look for any "python.exe" dialog.

Permalink

Good to hear you got it to work.