public int ProvideLibrary(string fileName, int timestamp, int sizeOfImage, out IntPtr hModule) { CLRMetaHost mh = new CLRMetaHost(); foreach (CLRRuntimeInfo rti in mh.EnumerateInstalledRuntimes()) { string libPath = Path.Combine(rti.GetRuntimeDirectory(), fileName); if (DoesFileMatch(libPath, timestamp, sizeOfImage)) { hModule = LoadLibrary(libPath); if (hModule != IntPtr.Zero) { UpdateLastLoaded(fileName, libPath); return 0; } else { return -1; } } } // not found hModule = IntPtr.Zero; return -1; }
/// <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(); }
//////////////////////////////////////////////////////////////////////////////// // // CorDebugger private implement part // //////////////////////////////////////////////////////////////////////////////// // called by constructors during initialization private void InitFromVersion(string debuggerVersion) { if (debuggerVersion.StartsWith("v1")) { // ICorDebug before V2 did not cooperate well with COM-intop. MDbg's managed // wrappers over ICorDebug only work on V2 and beyond. throw new ArgumentException("Can't debug a version 1 CLR process (\"" + debuggerVersion + "\"). Run application in a version 2 CLR, or use a version 1 debugger instead."); } bool fUseV2 = false; ICorDebug rawDebuggingAPI = null; try { CLRMetaHost mh = new CLRMetaHost(); CLRRuntimeInfo rti = mh.GetRuntime(debuggerVersion); rawDebuggingAPI = rti.GetLegacyICorDebugInterface(); } catch (NotImplementedException) { fUseV2 = true; } catch (EntryPointNotFoundException) { fUseV2 = true; } if (fUseV2) { // fallback to v2 method try { rawDebuggingAPI = NativeMethods.CreateDebuggingInterfaceFromVersion((int)CorDebuggerVersion.Whidbey, debuggerVersion); } catch (ArgumentException) { // This can commonly happen if: // 1) the debuggee is missing a config file // 2) the debuggee has a config file for a not-installed CLR. // // Give a more descriptive error. // We explicitly don't pass the inner exception because: // - it's uninteresting. It's really just from a pinvoke and so there are no // extra managed frames. // - MDbg's error reporting will call Exception.GetBaseException() and so just // grab the inner exception. throw new ArgumentException("Failed to create debugging services for version '" + debuggerVersion + "'"); } } Debug.Assert(rawDebuggingAPI != null); InitFromICorDebug(rawDebuggingAPI); }
/// <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; }