注释
.NET Framework 4 中的分析发生了重大更改。
当托管进程(应用程序或服务)启动时,它将加载公共语言运行时(CLR)。 初始化 CLR 时,它会评估以下两个环境变量,以确定进程是否应连接到探查器:
COR_ENABLE_PROFILING:仅当此环境变量存在且设置为 1 时,CLR 才会连接到探查器。
COR_PROFILER:如果COR_ENABLE_PROFILING检查通过,CLR 将连接到具有此 CLSID 或 ProgID 的探查器,该探查器必须以前存储在注册表中。 COR_PROFILER环境变量定义为字符串,如以下两个示例所示。
set COR_PROFILER={32E2F4DA-1BEA-47ea-88F9-C5DAF691C94A} set COR_PROFILER="MyProfiler"
若要分析 CLR 应用程序,必须在运行应用程序之前设置COR_ENABLE_PROFILING和COR_PROFILER环境变量。 还必须确保已注册探查器 DLL。
注释
从 .NET Framework 4 开始,探查器无需注册。
注释
若要在 .NET Framework 4 及更高版本中使用 .NET Framework 2.0、3.0 和 3.5 探查器,必须设置COMPLUS_ProfAPI_ProfilerCompatibilitySetting环境变量。
环境变量范围
如何设置COR_ENABLE_PROFILING和COR_PROFILER环境变量将确定其影响范围。 可通过以下方式之一设置这些变量:
如果在 ICorDebug::CreateProcess 调用中设置变量,它们将仅适用于当时运行的应用程序。 (它们也适用于继承环境的应用程序启动的其他应用程序。
如果在命令提示符窗口中设置变量,它们将应用于从该窗口启动的所有应用程序。
如果在用户级别设置变量,它们将应用于以文件资源管理器开头的所有应用程序。 设置变量后打开的命令提示符窗口将具有这些环境设置,从该窗口开始的任何应用程序也是如此。 若要在用户级别设置环境变量,请右键单击 “我的计算机”,单击“ 属性”,单击“ 高级 ”选项卡,单击“ 环境变量”,然后将变量添加到 “用户变量 ”列表中。
如果在计算机级别设置变量,它们将应用于在该计算机上启动的所有应用程序。 在该计算机上打开的命令提示符窗口将具有这些环境设置,从该窗口启动的任何应用程序也是如此。 这意味着该计算机上的每个托管进程都将从探查器开始。 若要在计算机级别设置环境变量,请右键单击“ 我的计算机”,单击“ 属性”,单击“ 高级 ”选项卡,单击“ 环境变量”,将变量添加到 “系统变量 ”列表中,然后重新启动计算机。 重启后,变量将适用于系统范围。
如果要分析 Windows 服务,则必须在设置环境变量并注册探查器 DLL 后重新启动计算机。 有关这些注意事项的详细信息,请参阅 分析 Windows 服务部分。
其他注意事项
探查器类实现 ICorProfilerCallback 和 ICorProfilerCallback2 接口。 在 .NET Framework 版本 2.0 中,探查器必须实现
ICorProfilerCallback2。 如果未加载,ICorProfilerCallback2则不会加载。在给定环境中,只有一个探查器可以一次分析进程。 可以在不同的环境中注册两个不同的探查器,但每个探查器必须分析单独的进程。 探查器必须作为进程内 COM 服务器 DLL 实现,该 DLL 映射到所分析进程的同一地址空间。 这意味着探查器在进程内运行。 .NET Framework 不支持任何其他类型的 COM 服务器。 例如,如果探查器想要从远程计算机监视应用程序,则必须在每台计算机上实现收集器代理。 这些代理将批处理结果并将其传达给中央数据收集计算机。
由于探查器是进程内实例化的 COM 对象,因此每个被分析的应用程序都将有自己的探查器副本。 因此,单个探查器实例不必处理来自多个应用程序的数据。 但是,必须向探查器的日志记录代码添加逻辑,以防止日志文件从其他分析的应用程序覆盖。
初始化探查器
当两个环境变量检查通过时,CLR 会以与 COM CoCreateInstance 函数类似的方式创建探查器的实例。 不会通过直接调用 CoCreateInstance加载探查器。 因此,避免调用 CoInitialize需要设置线程模型。 然后,CLR 在探查器中调用 ICorProfilerCallback::Initialize 方法。 此方法的签名如下所示。
HRESULT Initialize(IUnknown *pICorProfilerInfoUnk)
探查器必须查询 pICorProfilerInfoUnkICorProfilerInfo 或 ICorProfilerInfo2 接口指针,并保存它,以便在分析期间稍后可以请求更多信息。
设置事件通知
然后,探查器调用 ICorProfilerInfo::SetEventMask 方法,以指定它感兴趣的通知类别。 例如,如果探查器只对函数输入和离开通知和垃圾回收通知感兴趣,则指定以下内容。
ICorProfilerInfo* pInfo;
pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo, (void**)&pInfo);
pInfo->SetEventMask(COR_PRF_MONITOR_ENTERLEAVE | COR_PRF_MONITOR_GC)
通过以这种方式设置通知掩码,探查器可以限制接收的通知。 此方法可帮助用户构建简单或特殊用途探查器。 它还会减少 CPU 时间,这会浪费发送探查器只会忽略的通知。
某些探查器事件是不可变的。 这意味着,在回调中 ICorProfilerCallback::Initialize 设置这些事件后,它们将无法关闭,并且无法打开新事件。 尝试更改不可变事件将导致 ICorProfilerInfo::SetEventMask 返回失败的 HRESULT。
分析 Windows 服务
分析 Windows 服务类似于分析公共语言运行时应用程序。 这两个分析作都通过环境变量启用。 由于作系统启动时会启动 Windows 服务,因此本主题中前面讨论的环境变量必须已存在,并设置为系统启动前所需的值。 此外,必须在系统上注册分析 DLL。
设置COR_ENABLE_PROFILING并COR_PROFILER环境变量并注册探查器 DLL 后,应重启目标计算机,以便 Windows 服务能够检测这些更改。
请注意,这些更改将在系统范围内启用分析。 若要防止随后运行的每个托管应用程序被分析,应在重启目标计算机后删除系统环境变量。
此方法还会导致分析每个 CLR 过程。 探查器应将逻辑添加到其 ICorProfilerCallback::Initialize 回调,以检测当前进程是否感兴趣。 如果不是,探查器可以在不执行初始化的情况下失败回调。