Skip to content

Instantly share code, notes, and snippets.

@MrGung
Created August 27, 2011 17:47
Show Gist options
  • Save MrGung/1175654 to your computer and use it in GitHub Desktop.
Save MrGung/1175654 to your computer and use it in GitHub Desktop.
Disable exceptions in Visual Studio programamtically using F#
// list of exceptions that will be disabled in the script.
// if an exception is not yet known to Visual Studio the exception will be added to VS's list of exceptions automatically.
let exceptionsToDisable = [|"Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException"
"System.Data.SqlClient.SqlException"
"System.IO.FileNotFoundException"
"System.IO.IOException"
"System.IO.PipeException"
"System.Net.WebException"
"System.NullReferenceException"
"System.Reflection.TargetInvocationException"
"System.Runtime.InteropServices.InvalidComObjectException"
"System.ServiceModel.CommunicationException"
"System.ServiceModel.EndpointNotFoundException"|]
// references
#r @"EnvDTE.dll"
#r @"EnvDTE80.dll"
#r @"EnvDTE90.dll"
open EnvDTE
open EnvDTE80
open EnvDTE90
open System
open System.Diagnostics
open System.Runtime.InteropServices
open System.Runtime.InteropServices.ComTypes
(*
In order to connect to the running VS-process its process-id must be known.
The following code determines that process-id.
The code was taken from http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html
Using VisualBasic the process-id is not necessary because VB automatically has access to the currently running instance of VS.
Since F# runs in a separate process (a child-process of the running instance of VS) the process-id of the parent VS-process must be determined.
*)
let getParentProcess (processId:int) =
let proc = Process.GetProcessById processId
let myProcID = new PerformanceCounter("Process", "ID Process", proc.ProcessName)
let myParentID = new PerformanceCounter("Process", "Creating Process ID", proc.ProcessName)
myParentID.NextValue() |> int
let currentProcess = Process.GetCurrentProcess().Id
let myVS = getParentProcess currentProcess
module Msdev =
[<DllImport("ole32.dll")>]
extern int GetRunningObjectTable([<In>]int reserved, [<Out>] IRunningObjectTable& prot)
[<DllImport("ole32.dll")>]
extern int CreateBindCtx([<In>]int reserved, [<Out>]IBindCtx& ppbc)
let tryFindInRunningObjectTable (name:string) =
//let result = new Dictionary<_,_>()
let mutable rot = null
if Msdev.GetRunningObjectTable(0,&rot) <> 0 then failwith "GetRunningObjectTable failed."
let mutable monikerEnumerator = null
rot.EnumRunning(&monikerEnumerator)
monikerEnumerator.Reset()
let mutable numFetched = IntPtr.Zero
let monikers = Array.init<ComTypes.IMoniker> 1 (fun _ -> null)
let mutable result = None
while result.IsNone && (monikerEnumerator.Next(1, monikers, numFetched) = 0) do
let mutable ctx = null
if Msdev.CreateBindCtx(0, &ctx) <> 0 then failwith "CreateBindCtx failed"
let mutable runningObjectName = null
monikers.[0].GetDisplayName(ctx, null, &runningObjectName)
if runningObjectName = name then
let mutable runningObjectVal = null
if rot.GetObject( monikers.[0], &runningObjectVal) <> 0 then failwith "GetObject failed"
result <- Some runningObjectVal
//result.[runningObjectName] <- runningObjectVal
result
let getVS2010ROTName id =
sprintf "!VisualStudio.DTE.10.0:%i" id
(*
The above code was all taken from someone else. Following some of my stuff.
Two functions are defined:
First, all exceptions will be enabled (which takes rather long - even when done via the GUI.
Then the exceptions from the list defined above will be disabled.
If an exception is not yet known to VS it will be made known to be able disable it.
*)
let enableAll (excSettings:EnvDTE90.ExceptionSettings) =
for excSetting in excSettings do
excSettings.SetBreakWhenThrown(false, excSetting)
let disableSelected (excSettings:EnvDTE90.ExceptionSettings) exceptionsToDisable =
for exceptionToDisble in exceptionsToDisable do
try
excSettings.SetBreakWhenThrown(false, (excSettings.Item exceptionToDisble))
with
| :? System.Runtime.InteropServices.COMException ->
printfn "Error occurred disabling %s" exceptionToDisble
excSettings.SetBreakWhenThrown(false, excSettings.NewException(exceptionToDisble, 0u))
// Instead of SetBreakWhenThrown it is also possible to SetBreakWhenUserUnhandled
// ------------------------------------------------------------------------------------------------------
// Getting some objects from Visual Studio's object-model for automation...
let dte = (tryFindInRunningObjectTable (getVS2010ROTName myVS) |> Option.get) :?> DTE2
let dbg = dte.Debugger :?> EnvDTE90.Debugger3
let excSettings = dbg.ExceptionGroups.Item "Common Language Runtime Exceptions"
//enableAll excSettings; // commented out because it really takes long.
disableSelected excSettings exceptionsToDisable
printfn "Exceptions were disabled."
(*
Links:
http://msdn.microsoft.com/en-us/library/za2b25t3.aspx
http://books.google.de/books?id=21mIZpxyKz0C&pg=PA537&lpg=PA537&dq=%2B%22f%23%22+EnvDTE80&source=bl&ots=_jYg-zoGFA&sig=YlFK4sFMc-ZrHe6zEPrSqvi2N9s&hl=de#v=onepage&q=%2B%22f%23%22%20EnvDTE80&f=false
http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment