/// <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(); }
/// <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); } } }
public static void ProcessEnumCmd(string arguments) { WriteOutput("Active processes on current machine:"); foreach (Process p in Process.GetProcesses()) { if (Process.GetCurrentProcess().Id == p.Id) // let's hide our process { continue; } //list the loaded runtimes in each process, if the ClrMetaHost APIs are available CLRMetaHost mh = null; try { mh = new CLRMetaHost(); } catch (System.EntryPointNotFoundException) { // Intentionally ignore failure to find GetCLRMetaHost(). // Downlevel we don't have one. continue; } IEnumerable<CLRRuntimeInfo> runtimes = null; try { runtimes = mh.EnumerateLoadedRuntimes(p.Id); } catch (System.ComponentModel.Win32Exception e) { if ((e.NativeErrorCode != 0x0) && // The operation completed successfully. (e.NativeErrorCode != 0x3f0) && // An attempt was made to reference a token that does not exist. (e.NativeErrorCode != 0x5) && // Access is denied. (e.NativeErrorCode != 0x57) && // The parameter is incorrect. (e.NativeErrorCode != 0x514) && // Not all privileges or groups referenced are assigned to the caller. (e.NativeErrorCode != 0x12)) // There are no more files. { // Unknown/unexpected failures should be reported to the user for diagnosis. WriteOutput("Error retrieving loaded runtime information for PID " + p.Id + ", error " + e.ErrorCode + " (" + e.NativeErrorCode + ") '" + e.Message + "'"); } // If we failed, don't try to print out any info. if ((e.NativeErrorCode != 0x0) || (runtimes == null)) { continue; } } catch (System.Runtime.InteropServices.COMException e) { if (e.ErrorCode != (int)HResult.E_PARTIAL_COPY) // Only part of a ReadProcessMemory or WriteProcessMemory request was completed. { // Unknown/unexpected failures should be reported to the user for diagnosis. WriteOutput("Error retrieving loaded runtime information for PID " + p.Id + ", error " + e.ErrorCode + "\n" + e.ToString()); } continue; } //if there are no runtimes in the target process, don't print it out if (!runtimes.GetEnumerator().MoveNext()) { continue; } WriteOutput("(PID: " + p.Id + ") " + p.MainModule.FileName); foreach (CLRRuntimeInfo rti in runtimes) { WriteOutput("\t" + rti.GetVersionString()); } } }
/// <摘要> ///获得所有托管进程 /// </摘要> public static List<ManagedProcess> GetManagedProcesses() { List<ManagedProcess> managedProcesses = new List<ManagedProcess>(); // CLR宿主包含一个ICLRMetaHost接口,提供了一个方法,可以列举指定进程加载的所有运行时 CLRMetaHost host = new CLRMetaHost(); var processes = System.Diagnostics.Process.GetProcesses(); foreach (System.Diagnostics.Process diagnosticsProcess in processes) { try { // 列举指定进程加载的所有运行时 var runtimes = host.EnumerateLoadedRuntimes(diagnosticsProcess.Id); // 如果进程加载了CLR,则被认定为托管进程 if (runtimes != null && runtimes.Count() > 0) { managedProcesses.Add(new ManagedProcess(diagnosticsProcess)); } } // 当文件无法找到或操作被拒绝时,EnumerateLoadedRuntimes方法会抛出Win32Exception异常 // 例如:目标进程是系统进程或系统闲置进程 catch (Win32Exception) { } // 在x86平台上创建的程序试图在64位操作系统上执行64位进程时, // EnumerateLoadedRuntimes方法会抛出COMException异常 catch (COMException) { } // 再次抛出其他异常 catch { throw; } } return managedProcesses; }