Ejemplo n.º 1
0
        /// <summary>
        /// Constructor for ProcessInfo
        /// </summary>
        /// <param name="procID">The id of the process</param>
        /// <param name="debugger">The debugger</param>
        public ProcessInfo(Process process, CorDebugger debug)
        {
            if (debug == null)
            {
                throw new ArgumentException("Null Debugger Exception");
            }

            processThreads     = new Dictionary <int, ThreadInfo>();
            processCorThreads  = new List <CorThread>();
            generalThreadInfos = new Dictionary <int, ProcessThread>();

            attachedCompletedProcessEvent = new ManualResetEvent(false);
            debugger           = debug;
            processId          = process.Id;
            generalProcessInfo = Process.GetProcessById(processId);

            //CorPublish cp = new CorPublish();
            //cpp = cp.GetProcess(processId);
            processFullName  = process.MainModule.FileName;
            processShortName = System.IO.Path.GetFileName(process.MainModule.FileName);
            FileVersionInfo fileInfo = FileVersionInfo.GetVersionInfo(processFullName);

            description = fileInfo.FileDescription;
            company     = fileInfo.CompanyName;

            //debuggerProcessInfo will be set when the updateInfo function is called
            //the reason for this is that the process must be stopped for this to take place
            //this happen only when we want it to
        }
Ejemplo n.º 2
0
    public static void SetUpTestEnvironment()
    {
        if (testProcess == null || testProcessInfo == null || debugger == null || testProcess.HasExited)
        {
            Console.WriteLine("Starting the unit test helper from " + testProgram + " ...");
            testProcess = Process.Start(testProgram, "");

            //wait for program to finish initializing
            while (true)
            {
                try
                {
                    if (File.Exists(testFile))
                    {
                        debugger        = new CorDebugger(CorDebugger.GetDefaultDebuggerVersion());
                        testProcessInfo = new ProcessInfo(testProcess, debugger);
                        File.Delete(testFile);
                        break;
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                    throw;
                }
            }
        }
    }
Ejemplo n.º 3
0
        private static void Main(string[] args)
        {
            int pid;

            if (args.Length == 1 && int.TryParse(args[0], out pid))
            {
                try
                {
                    var process = Process.GetProcessById(int.Parse(args[0]));

                    var mh = new CLRMetaHost();
                    mh.EnumerateLoadedRuntimes(process.Id);
                    var version     = MdbgVersionPolicy.GetDefaultAttachVersion(process.Id);
                    var debugger    = new CorDebugger(version);
                    var processInfo = new ProcessInfo(process, debugger);
                    foreach (var line in processInfo.GetDisplayStackTrace())
                    {
                        Console.WriteLine(line);
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine("Error getting process thread dump: " + e);
                }
            }
            else
            {
                Console.Error.WriteLine("Simple utility to generate .NET managed process thread dump (similar to Java jstack)");
                Console.Error.WriteLine("Usage: " + AppDomain.CurrentDomain.FriendlyName + " <PID>");
            }
        }
        public static List <String> getListOfManagedProcess(bool showDetails)
        {
            var managedProcesses = new List <String>();
            int currentProcessId = Process.GetCurrentProcess().Id;
            var corPublish       = new CorPublish();

            foreach (CorPublishProcess corPublishProcess in corPublish.EnumProcesses())
            {
                if (currentProcessId != corPublishProcess.ProcessId)
                {
                    // don't include the current process
                    if (showDetails)
                    {
                        managedProcesses.Add("[" + corPublishProcess.ProcessId + "] [ver=" +
                                             CorDebugger.GetDebuggerVersionFromPid(corPublishProcess.ProcessId) + "] " +
                                             corPublishProcess.DisplayName);
                    }
                    else
                    {
                        managedProcesses.Add(corPublishProcess.DisplayName);
                    }
                }
            }
            return(managedProcesses);
        }
Ejemplo n.º 5
0
        static private MDbgProcess GetProcessFromCordb(ICorDebug cordbg)
        {
            Debugger.Processes.FreeStaleUnmanagedResources();
            CorDebugger cordebugger = new CorDebugger(cordbg);

            Debugger.Processes.RegisterDebuggerForCleanup(cordebugger);
            return(new MDbgProcess(Debugger, cordebugger));
        }
Ejemplo n.º 6
0
 void AttachToProcessImpl(int procId)
 {
     attaching = true;
     MtaThread.Run(delegate
     {
         var iCorDebug = CoreClrShimUtil.CreateICorDebugForProcess(dbgShimInterop, procId, RuntimeLoadTimeout);
         dbg           = new CorDebugger(iCorDebug);
         process       = dbg.DebugActiveProcess(procId, false);
         SetupProcess(process);
         process.Continue(false);
     });
     OnStarted();
 }
Ejemplo n.º 7
0
        protected override void OnRun(DebuggerStartInfo startInfo)
        {
            // Create the debugger

            string dversion = CorDebugger.GetDebuggerVersionFromFile(startInfo.Command);

            dbg = new CorDebugger(dversion);

            Dictionary <string, string> env = new Dictionary <string, string> ();

            foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
            {
                env[(string)de.Key] = (string)de.Value;
            }

            foreach (KeyValuePair <string, string> var in startInfo.EnvironmentVariables)
            {
                env[var.Key] = var.Value;
            }

            // The second parameter of CreateProcess is the command line, and it includes the application being launched
            string cmdLine = "\"" + startInfo.Command + "\" " + startInfo.Arguments;

            process   = dbg.CreateProcess(startInfo.Command, cmdLine, startInfo.WorkingDirectory, env);
            processId = process.Id;

            process.OnCreateProcess       += new CorProcessEventHandler(OnCreateProcess);
            process.OnCreateAppDomain     += new CorAppDomainEventHandler(OnCreateAppDomain);
            process.OnAssemblyLoad        += new CorAssemblyEventHandler(OnAssemblyLoad);
            process.OnAssemblyUnload      += new CorAssemblyEventHandler(OnAssemblyUnload);
            process.OnCreateThread        += new CorThreadEventHandler(OnCreateThread);
            process.OnThreadExit          += new CorThreadEventHandler(OnThreadExit);
            process.OnModuleLoad          += new CorModuleEventHandler(OnModuleLoad);
            process.OnModuleUnload        += new CorModuleEventHandler(OnModuleUnload);
            process.OnProcessExit         += new CorProcessEventHandler(OnProcessExit);
            process.OnUpdateModuleSymbols += new UpdateModuleSymbolsEventHandler(OnUpdateModuleSymbols);
            process.OnDebuggerError       += new DebuggerErrorEventHandler(OnDebuggerError);
            process.OnBreakpoint          += new BreakpointEventHandler(OnBreakpoint);
            process.OnStepComplete        += new StepCompleteEventHandler(OnStepComplete);
            process.OnBreak         += new CorThreadEventHandler(OnBreak);
            process.OnNameChange    += new CorThreadEventHandler(OnNameChange);
            process.OnEvalComplete  += new EvalEventHandler(OnEvalComplete);
            process.OnEvalException += new EvalEventHandler(OnEvalException);

            process.Continue(false);

            OnStarted();
        }
Ejemplo n.º 8
0
 protected override void OnRun(DebuggerStartInfo startInfo)
 {
     MtaThread.Run(() => {
         var workingDir = PrepareWorkingDirectory(startInfo);
         var env        = PrepareEnvironment(startInfo);
         var cmd        = PrepareCommandLine(startInfo);
         int procId;
         var iCorDebug = CoreClrShimUtil.CreateICorDebugForCommand(
             dbgShimInterop, cmd, workingDir, env, RuntimeLoadTimeout, out procId);
         dbg       = new CorDebugger(iCorDebug);
         process   = dbg.DebugActiveProcess(procId, false);
         processId = process.Id;
         SetupProcess(process);
         process.Continue(false);
     });
     OnStarted();
 }
Ejemplo n.º 9
0
        //////////////////////////////////////////////////////////////////////////////////
        //
        // Controlling Commands
        //
        //////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// creates a new debugged process.
        /// </summary>
        /// <param name="commandLine">The command to run.</param>
        /// <param name="commandArguments">The arguments for the command.</param>
        /// <param name="debugMode">The debug mode to run with.</param>
        /// <param name="deeVersion">The version of debugging interfaces that should be used for
        ///   debugging of the started program. If this value is null, the default (latest) version
        ///   of interface is used.
        /// </param>
        /// <returns>The resulting MDbgProcess.</returns>
        public MDbgProcess CreateProcess(string commandLine, string commandArguments,
                                         DebugModeFlag debugMode, string deeVersion)
        {
            CorDebugger debugger;

            if (deeVersion == null)
            {
                debugger = new CorDebugger(CorDebugger.GetDefaultDebuggerVersion());
            }
            else
            {
                debugger = new CorDebugger(deeVersion);
            }
            MDbgProcess p = m_processMgr.CreateLocalProcess(debugger);

            p.DebugMode = debugMode;
            p.CreateProcess(commandLine, commandArguments);
            return(p);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns the version of the runtime to debug in a process
        /// we are attaching to, assuming we can only pick one
        /// </summary>
        /// <param name="processId">The process to attach to</param>
        /// <returns>The version of the runtime to debug, or null if the policy can't decide</returns>
        public static string GetDefaultAttachVersion(int processId)
        {
            try
            {
                CLRMetaHost           mh       = new CLRMetaHost();
                List <CLRRuntimeInfo> runtimes = new List <CLRRuntimeInfo>(mh.EnumerateLoadedRuntimes(processId));
                if (runtimes.Count > 1)
                {
                    // It is ambiguous so just give up
                    return(null);
                }
                else if (runtimes.Count == 1)
                {
                    return(runtimes[0].GetVersionString());
                }
            }
            catch (EntryPointNotFoundException)
            {
                try
                {
                    return(CorDebugger.GetDebuggerVersionFromPid(processId));
                }
                catch (COMException) { }
            }

            // if we have neither failed nor detected a version at this point then there was no
            // CLR loaded. Now we try to determine what CLR the process will load by examining its
            // binary
            string binaryPath = GetBinaryPathFromPid(processId);

            if (binaryPath != null)
            {
                string version = GetDefaultRuntimeForFile(binaryPath);
                if (version != null)
                {
                    return(version);
                }
            }

            // and if that doesn't work, return the version of the CLR the debugger is
            // running against (a very arbitrary choice)
            return(Environment.Version.ToString());
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Refreshes the processes hash which stores info on all managed process running
        /// </summary>
        public void RefreshProcessList()
        {
            processes.Clear();

            foreach (var process in Process.GetProcesses())
            {
                if (Process.GetCurrentProcess().Id == process.Id)
                {
                    // let's hide our process
                    continue;
                }

                // list the loaded runtimes in each process, if the ClrMetaHost APIs are available
                CLRMetaHost mh;
                try
                {
                    mh = new CLRMetaHost();
                }
                catch (Exception)
                {
                    continue;
                }

                IEnumerable <CLRRuntimeInfo> runtimes;
                try
                {
                    runtimes = mh.EnumerateLoadedRuntimes(process.Id);
                }
                catch (Exception)
                {
                    continue;
                }

                // TODO: only one CLR version for now...
                if (runtimes.Any())
                {
                    var version  = MdbgVersionPolicy.GetDefaultAttachVersion(process.Id);
                    var debugger = new CorDebugger(version);
                    processes[process.Id] = new ProcessInfo(process, debugger);
                }
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Attach to a process with the given Process ID
        /// </summary>
        /// <param name="processId">The Process ID to attach to.</param>
        /// <returns>The resulting MDbgProcess.</returns>
        public MDbgProcess Attach(int processId)
        {
            string deeVersion;

            try
            {
                deeVersion = CorDebugger.GetDebuggerVersionFromPid(processId);
            }
            catch
            {
                // GetDebuggerVersionFromPid isn't implemented on Win9x and so will
                // throw NotImplementedException.  We'll also get an ArgumentException
                // if the specified process doesn't have the CLR loaded yet.
                // Rather than be selective (and potentially brittle), we'll handle all errors.
                // Ideally we'd assert (or log) that we're only getting the errors we expect,
                // but it's complex and ugly to do that in C#.

                // Fall back to guessing the version based on the filename.
                // Environment variables (eg. COMPLUS_Version) may have resulted
                // in a different choice.
                try
                {
                    var cp = new CorPublish.CorPublish();
                    CorPublishProcess cpp           = cp.GetProcess(processId);
                    string            programBinary = cpp.DisplayName;

                    deeVersion = CorDebugger.GetDebuggerVersionFromFile(programBinary);
                }
                catch
                {
                    // This will also fail if the process doesn't have the CLR loaded yet.
                    // It could also fail if the image EXE has been renamed since it started.
                    // For whatever reason, fall back to using the default CLR
                    deeVersion = null;
                }
            }

            MDbgProcess p = m_processMgr.CreateLocalProcess(deeVersion);

            p.Attach(processId);
            return(p);
        }
Ejemplo n.º 13
0
        protected virtual void PrintStartupLogo()
        {
            string myVersion = GetBinaryVersion();

            IO.WriteOutput(MDbgOutputConstants.StdOutput,
                           "MDbg (Managed debugger) v" + myVersion + " started.\n");
            IO.WriteOutput(MDbgOutputConstants.StdOutput,
                           "Copyright (C) Microsoft Corporation. All rights reserved.\n");
            IO.WriteOutput(MDbgOutputConstants.StdOutput,
                           "\nFor information about commands type \"help\";\nto exit program type \"quit\".\n\n");

            // Check for and output any debugging warnings
            try
            {
                (new CorDebugger(CorDebugger.GetDefaultDebuggerVersion())).CanLaunchOrAttach(0, false);
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                IO.WriteOutput(MDbgOutputConstants.StdOutput, "WARNING: " + e.Message + "\n\n");
            }
        }
Ejemplo n.º 14
0
        void OnProcessExit(object sender, CorProcessEventArgs e)
        {
            TargetEventArgs args = new TargetEventArgs(TargetEventType.TargetExited);

            // If the main thread stopped, terminate the debugger session
            if (e.Process.Id == process.Id)
            {
                lock (terminateLock) {
                    process = null;
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        // The Terminate call will fail if called in the event handler
                        dbg.Terminate();
                        dbg = null;
                        GC.Collect();
                    });
                }
            }

            OnTargetEvent(args);
        }
        private void RefreshProcesses()
        {
            listBoxProcesses.Items.Clear();

            CorPublish cp = null;

            int curPid = Process.GetCurrentProcess().Id;

            try
            {
                int count = 0;

                cp = new CorPublish();
                {
                    foreach (CorPublishProcess cpp in cp.EnumProcesses())
                    {
                        if (curPid != cpp.ProcessId) // let's hide our process
                        {
                            string version = CorDebugger.GetDebuggerVersionFromPid(cpp.ProcessId);
                            string s       = "[" + cpp.ProcessId + "] [ver=" + version + "] " + cpp.DisplayName;
                            listBoxProcesses.Items.Add(new Item(cpp.ProcessId, s));
                            count++;
                        }
                    }
                } // using

                if (count == 0)
                {
                    listBoxProcesses.Items.Add(new Item(0, "(No active processes)"));
                }
            }
            catch (Exception)
            {
                if (cp == null)
                {
                    listBoxProcesses.Items.Add(new Item(0, "(Can't enumerate processes"));
                }
            }
        }
Ejemplo n.º 16
0
        protected override void OnRun(DebuggerStartInfo startInfo)
        {
            // Create the debugger

            string dversion;

            try {
                dversion = CorDebugger.GetDebuggerVersionFromFile(startInfo.Command);
            }
            catch {
                dversion = CorDebugger.GetDefaultDebuggerVersion();
            }
            dbg = new CorDebugger(dversion);

            Dictionary <string, string> env = new Dictionary <string, string> ();

            foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
            {
                env[(string)de.Key] = (string)de.Value;
            }

            foreach (KeyValuePair <string, string> var in startInfo.EnvironmentVariables)
            {
                env[var.Key] = var.Value;
            }

            // The second parameter of CreateProcess is the command line, and it includes the application being launched
            string cmdLine = "\"" + startInfo.Command + "\" " + startInfo.Arguments;

            int flags = 0;

            if (!startInfo.UseExternalConsole)
            {
                flags  = 0x08000000;                /* CREATE_NO_WINDOW*/
                flags |= CorDebugger.CREATE_REDIRECT_STD;
            }

            process   = dbg.CreateProcess(startInfo.Command, cmdLine, startInfo.WorkingDirectory, env, flags);
            processId = process.Id;

            process.OnCreateProcess       += new CorProcessEventHandler(OnCreateProcess);
            process.OnCreateAppDomain     += new CorAppDomainEventHandler(OnCreateAppDomain);
            process.OnAssemblyLoad        += new CorAssemblyEventHandler(OnAssemblyLoad);
            process.OnAssemblyUnload      += new CorAssemblyEventHandler(OnAssemblyUnload);
            process.OnCreateThread        += new CorThreadEventHandler(OnCreateThread);
            process.OnThreadExit          += new CorThreadEventHandler(OnThreadExit);
            process.OnModuleLoad          += new CorModuleEventHandler(OnModuleLoad);
            process.OnModuleUnload        += new CorModuleEventHandler(OnModuleUnload);
            process.OnProcessExit         += new CorProcessEventHandler(OnProcessExit);
            process.OnUpdateModuleSymbols += new UpdateModuleSymbolsEventHandler(OnUpdateModuleSymbols);
            process.OnDebuggerError       += new DebuggerErrorEventHandler(OnDebuggerError);
            process.OnBreakpoint          += new BreakpointEventHandler(OnBreakpoint);
            process.OnStepComplete        += new StepCompleteEventHandler(OnStepComplete);
            process.OnBreak         += new CorThreadEventHandler(OnBreak);
            process.OnNameChange    += new CorThreadEventHandler(OnNameChange);
            process.OnEvalComplete  += new EvalEventHandler(OnEvalComplete);
            process.OnEvalException += new EvalEventHandler(OnEvalException);
            process.OnLogMessage    += new LogMessageEventHandler(OnLogMessage);
            process.OnStdOutput     += new CorTargetOutputEventHandler(OnStdOutput);
            process.OnException2    += new CorException2EventHandler(OnException2);

            process.Continue(false);

            OnStarted();
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Helper function that parses inputs to run and crun commands.
        /// </summary>
        /// <param name="arguments">Argument to the run and crun command</param>
        /// <param name="debugMode">Returns desired debugging mode. Returns internal
        /// default if not specified
        /// </param>
        /// <param name="debuggeeVersion">Returns the debugger interface version.
        ///    Is null if the version cannot be determined.
        /// </param>
        /// <param name="programToRun">Returns path of the program to execute.</param>
        /// <param name="programArguments">Returns arguments to pass to the program being
        /// run, including the binary name as the 0th argument</param>
        public static void PreParseRunArguments(string arguments, out DebugModeFlag debugMode,
                                                out string debuggeeVersion,
                                                out string programToRun,
                                                out string programArguments)
        {
            Debug.Assert(arguments != null);
            if (arguments == null)
            {
                throw new ArgumentException("Parameter cannot be null.", "arguments");
            }

            debugMode = DebugModeFlag.Debug;
            // Is this the mode we want to always start in?

            int start, end;

            start = end = 0;

            // those flags are necessary so that people can run any program under debugger.
            // e.g to run program named '-debug.exe', they can write 'run -debug -debug'
            //
            // One obvious issue here is that if the binary name is same as the flag, then
            // user need to pass the flag to the run command so that the program name is not
            // interpreted as a flag.
            //

            bool debugModeFlagSet = false;
            bool versionFlagSet   = false;

            debuggeeVersion = null;

            while (FindToken(arguments, ref start, ref end))
            {
                Debug.Assert(start <= end);

                switch (arguments.Substring(start, end - start))
                {
                case "-default":
                    if (debugModeFlagSet)
                    {
                        goto default;
                    }
                    debugMode        = DebugModeFlag.Default;
                    debugModeFlagSet = true;
                    break;

                case "-debug":
                case "-d":
                    if (debugModeFlagSet)
                    {
                        goto default;
                    }
                    debugMode        = DebugModeFlag.Debug;
                    debugModeFlagSet = true;
                    break;

                case "-optimize":
                case "-o":
                    if (debugModeFlagSet)
                    {
                        goto default;
                    }
                    debugMode        = DebugModeFlag.Optimized;
                    debugModeFlagSet = true;
                    break;

                case "-enc":
                    if (debugModeFlagSet)
                    {
                        goto default;
                    }
                    debugMode        = DebugModeFlag.Enc;
                    debugModeFlagSet = true;
                    break;

                case "-ver":
                    if (versionFlagSet)
                    {
                        goto default;
                    }

                    if (!FindToken(arguments, ref start, ref end))
                    {
                        throw new MDbgShellException("missing argument to -ver option");
                    }
                    debuggeeVersion = arguments.Substring(start, end - start);
                    versionFlagSet  = true;
                    break;

                default:
                    // this means we have found some different token.
                    // To keep comaptibility with cordbg, we assume that this is a program binary name.

                    // Expand environment variables on the binary name so that we can use env vars in
                    // the program path. Note that environment variables are not expanded in program
                    // arguments so that we can pass in original strings. Programs can expand the environment
                    // themselves if they wish so.
                    string prog = Environment.ExpandEnvironmentVariables(arguments.Substring(start, end - start));

                    // program may be quoted, remove surrounding quotes
                    // Note: ideally we'd have a general escapedPath format and escape/unescape methods to convert
                    // but this is good enough for our purposes here.
                    if (prog.Length >= 2 && prog.StartsWith("\"") && prog.EndsWith("\""))
                    {
                        prog = prog.Substring(1, prog.Length - 2);
                    }

                    // may have omitted .exe extension, add it if necessary
                    const string optExt = ".exe";
                    if (!prog.EndsWith(optExt, StringComparison.OrdinalIgnoreCase))
                    {
                        prog += optExt;
                    }

                    // We're left with the program binary path
                    programToRun = prog;

                    // Use everything unmodified (including the possibly quoted binary path) as the run arguments
                    programArguments = arguments.Substring(start);

                    if (debuggeeVersion == null)
                    {
                        // user didn't specify, we need to guess it.
                        try
                        {
                            debuggeeVersion = CorDebugger.GetDebuggerVersionFromFile(programToRun);
                        }
                        catch (COMException)
                        {
                            // we could not retrieve dee version.
                            debuggeeVersion = null;
                        }
                    }

                    // Rest of line processed, we're done.
                    return;
                }
            }

            // we didn't find any token -- no other binary specified than options
            programToRun     = null;
            programArguments = null;

            return;
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Given the full path to a binary, finds the CLR runtime version which
        /// it will bind to.
        /// </summary>
        /// <param name="filePath">The full path to a binary.</param>
        /// <returns>The version string that the binary will bind to; null if unknown.</returns>
        /// <remarks>If ICLRMetaHostPolicy can be asked, it is used. Otherwise
        /// fall back to mscoree!GetRequestedRuntimeVersion.</remarks>
        public static String GetDefaultRuntimeForFile(String filePath)
        {
            String version = null;

            CLRMetaHostPolicy policy;

            try
            {
                policy = new CLRMetaHostPolicy();
            }
            catch (NotImplementedException)
            {
                policy = null;
            }
            catch (System.EntryPointNotFoundException)
            {
                policy = null;
            }

            if (policy != null)
            {
                // v4 codepath
                StringBuilder  ver      = new StringBuilder();
                StringBuilder  imageVer = new StringBuilder();
                CLRRuntimeInfo rti      = null;

                String configPath = null;
                if (System.IO.File.Exists(filePath + ".config"))
                {
                    configPath = filePath + ".config";
                }

                try
                {
                    rti = policy.GetRequestedRuntime(CLRMetaHostPolicy.MetaHostPolicyFlags.metaHostPolicyHighCompat,
                                                     filePath,
                                                     configPath,
                                                     ref ver,
                                                     ref imageVer);
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                    Debug.Assert(rti == null);
                }

                if (rti != null)
                {
                    version = rti.GetVersionString();
                }
                else
                {
                    version = null;
                }
            }
            else
            {
                // v2 codepath
                try
                {
                    version = CorDebugger.GetDebuggerVersionFromFile(filePath);
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                    // we could not retrieve dee version.
                    // Leave version null;
                    Debug.Assert(version == null);
                }
            }

            return(version);
        }