Beispiel #1
0
        /// <summary>
        /// Reports the current non-fatal exception using a process snapshot (if InitializeHandlesForSnapshot has been called)
        /// </summary>
        /// <returns>true if the report was successfully taken, false otherwise</returns>
        private bool ReportException()
        {
            bool reportTaken = false;

            string dbgHelperPath;

            // If we found the helper exe lets call it
            if (IsHelperExeFound(out dbgHelperPath))
            {
                using (Process p = new Process())
                {
                    // assemble the arguments to the helper, if this returns false we can not proceed
                    string helperArguments;
                    if (PrepareHelperArguments(out helperArguments))
                    {
                        p.StartInfo = new ProcessStartInfo(dbgHelperPath, helperArguments)
                        {
                            // Prevent the helper process from spawning a new window
                            CreateNoWindow = true,

                            // When UseShellExecute is off, the .NET framework will always call CreateProcess with the bInheritHandles true, which is required to trigger the event
                            UseShellExecute = false,
                        };

                        p.Start();

                        if (_eventHandle != IntPtr.Zero)
                        {
                            // wait for the event trigger from the helper or the helper to exit (a maximum of 10 second)
                            // we should keep this timeout low because the IDE will be hung while waiting on this
                            IntPtr[] handles = new IntPtr[] { _eventHandle, p.Handle };

                            // This should be the landing point for all non-fatal watson dumps,
                            // navigate up the callstack to identify the source of the exception
                            UInt32 result = NativeWin32Stubs.WaitForMultipleObjects((UInt32)handles.Length, handles, false, 10000);

                            // If we get an error result back the wait timed out and the report was not taken in time
                            // or if the wait was triggered by the process exiting
                            reportTaken = result == NativeWin32Stubs.WAIT_OBJECT_0;
                        }
                        else // we don't have an eventHandle to wait on so we should just continue
                        {
                            reportTaken = true;
                        }
                    }
                }
            }

            return(reportTaken);
        }
Beispiel #2
0
        protected virtual void Dispose(bool disposing)
        {
            _disposed = true;

#if !SILVERLIGHT
            // This pointer is no longer valid outside of the exception filter
            _exceptionPointersPointer = IntPtr.Zero;
            if (_eventHandle != IntPtr.Zero)
            {
                NativeWin32Stubs.CloseHandle(_eventHandle);
                _eventHandle = IntPtr.Zero;
            }
            if (_processHandleDupe != IntPtr.Zero)
            {
                NativeWin32Stubs.CloseHandle(_processHandleDupe);
                _processHandleDupe = IntPtr.Zero;
            }
            if (_threadHandleDupe != IntPtr.Zero)
            {
                NativeWin32Stubs.CloseHandle(_threadHandleDupe);
                _threadHandleDupe = IntPtr.Zero;
            }
#endif
        }
Beispiel #3
0
        /// <summary>
        /// Sets up for taking a snapshot by initializing the necessary handles for the helper process
        /// </summary>
        /// <remarks>
        /// This must be called from an Exception Filter inorder to gather the current exception information.
        /// </remarks>
        /// <returns>true on success and false on failure</returns>
        private unsafe bool InitializeHandlesForSnapshot()
        {
            // Grab the pointer to the exception
            _exceptionPointersPointer = Marshal.GetExceptionPointers();

            NativeWin32Stubs.SECURITY_ATTRIBUTES secAttrib = new NativeWin32Stubs.SECURITY_ATTRIBUTES();
            secAttrib.bInheritHandle = true;

            // Prepare id (ThreadId_DateTime) is sufficient to uniquely identify this snapshot request (used by helper process to name the dump file)
            _snapshotId = string.Format("{0}_{1}", Thread.CurrentThread.ManagedThreadId, unchecked ((ulong)DateTime.Now.ToBinary()));

            // pointer to the security attributes structure
            IntPtr pSecAttrib = IntPtr.Zero;
            // handle to this thread
            IntPtr hThread = IntPtr.Zero;

            try
            {
                // allocate some native to accommodate the SECURITY_ATTRIBUTES structure needed to create the event object and get its handle
                pSecAttrib = Marshal.AllocHGlobal(sizeof(NativeWin32Stubs.SECURITY_ATTRIBUTES));
                if (pSecAttrib == IntPtr.Zero)
                {
                    return(false);
                }

                // copy the managed structure into native
                Marshal.StructureToPtr(secAttrib, pSecAttrib, true);

                // Create event object in the OS (named eventHandleName) and get the handle to it
                _eventHandle = NativeWin32Stubs.CreateEvent(pSecAttrib, false, false, null);
                if (_eventHandle == IntPtr.Zero)
                {
                    return(false);
                }

                // Get current thread and process' handle and duplicate them (when you open the handle on a System.Process you must dispose it)
                using (Process thisProc = Process.GetCurrentProcess())
                {
                    // Grab the handle to this thread
                    hThread = NativeWin32Stubs.GetCurrentThread();
                    if (hThread == IntPtr.Zero)
                    {
                        return(false);
                    }

                    IntPtr hThisProc = thisProc.Handle;

                    // duplicate the thread handle
                    if (!NativeWin32Stubs.DuplicateHandle(hThisProc, hThread, hThisProc, out _threadHandleDupe, 0, true, (uint)NativeWin32Stubs.DESIRED_ACCESS.DUPLICATE_SAME_ACCESS) || _threadHandleDupe == IntPtr.Zero)
                    {
                        return(false);
                    }

                    // duplicate the process handle
                    if (!NativeWin32Stubs.DuplicateHandle(hThisProc, hThisProc, hThisProc, out _processHandleDupe, 0, true, (uint)NativeWin32Stubs.DESIRED_ACCESS.DUPLICATE_SAME_ACCESS) || _processHandleDupe == IntPtr.Zero)
                    {
                        return(false);
                    }
                }
            }
            finally // cleanup the temp handles and native memory we allocated
            {
                if (pSecAttrib != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pSecAttrib);
                }
                if (hThread != IntPtr.Zero)
                {
                    NativeWin32Stubs.CloseHandle(hThread);
                }
            }

            return(true);
        }