static ThreadInfo GetThreadInfo(Interop.Advapi32.PERF_OBJECT_TYPE type, IntPtr instancePtr, Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
        {
            ThreadInfo threadInfo = new ThreadInfo();

            for (int i = 0; i < counters.Length; i++)
            {
                Interop.Advapi32.PERF_COUNTER_DEFINITION counter = counters[i];
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset));
                switch ((ValueId)counter.CounterNameTitlePtr)
                {
                case ValueId.ProcessId:
                    threadInfo._processId = (int)value;
                    break;

                case ValueId.ThreadId:
                    threadInfo._threadId = (ulong)value;
                    break;

                case ValueId.BasePriority:
                    threadInfo._basePriority = (int)value;
                    break;

                case ValueId.CurrentPriority:
                    threadInfo._currentPriority = (int)value;
                    break;

                case ValueId.StartAddress:
                    threadInfo._startAddress = (IntPtr)value;
                    break;

                case ValueId.ThreadState:
                    threadInfo._threadState = (ThreadState)value;
                    break;

                case ValueId.ThreadWaitReason:
                    threadInfo._threadWaitReason = GetThreadWaitReason((int)value);
                    break;
                }
            }

            return(threadInfo);
        }
        static ProcessInfo GetProcessInfo(Interop.Advapi32.PERF_OBJECT_TYPE type, IntPtr instancePtr, Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
        {
            ProcessInfo processInfo = new ProcessInfo();

            for (int i = 0; i < counters.Length; i++)
            {
                Interop.Advapi32.PERF_COUNTER_DEFINITION counter = counters[i];
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset));
                switch ((ValueId)counter.CounterNameTitlePtr)
                {
                case ValueId.ProcessId:
                    processInfo.ProcessId = (int)value;
                    break;

                case ValueId.PoolPagedBytes:
                    processInfo.PoolPagedBytes = value;
                    break;

                case ValueId.PoolNonpagedBytes:
                    processInfo.PoolNonPagedBytes = value;
                    break;

                case ValueId.VirtualBytes:
                    processInfo.VirtualBytes = value;
                    break;

                case ValueId.VirtualBytesPeak:
                    processInfo.VirtualBytesPeak = value;
                    break;

                case ValueId.WorkingSetPeak:
                    processInfo.WorkingSetPeak = value;
                    break;

                case ValueId.WorkingSet:
                    processInfo.WorkingSet = value;
                    break;

                case ValueId.PageFileBytesPeak:
                    processInfo.PageFileBytesPeak = value;
                    break;

                case ValueId.PageFileBytes:
                    processInfo.PageFileBytes = value;
                    break;

                case ValueId.PrivateBytes:
                    processInfo.PrivateBytes = value;
                    break;

                case ValueId.BasePriority:
                    processInfo.BasePriority = (int)value;
                    break;

                case ValueId.HandleCount:
                    processInfo.HandleCount = (int)value;
                    break;
                }
            }
            return(processInfo);
        }
        static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library, int processIndex, int threadIndex, byte[] data)
        {
#if FEATURE_TRACESWITCH
            Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos()");
#endif
            Dictionary <int, ProcessInfo> processInfos = new Dictionary <int, ProcessInfo>();
            List <ThreadInfo>             threadInfos  = new List <ThreadInfo>();

            GCHandle dataHandle = new GCHandle();
            try
            {
                dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                IntPtr dataBlockPtr = dataHandle.AddrOfPinnedObject();
                Interop.Advapi32.PERF_DATA_BLOCK dataBlock = new Interop.Advapi32.PERF_DATA_BLOCK();
                Marshal.PtrToStructure(dataBlockPtr, dataBlock);
                IntPtr typePtr = (IntPtr)((long)dataBlockPtr + dataBlock.HeaderLength);
                Interop.Advapi32.PERF_INSTANCE_DEFINITION instance     = new Interop.Advapi32.PERF_INSTANCE_DEFINITION();
                Interop.Advapi32.PERF_COUNTER_BLOCK       counterBlock = new Interop.Advapi32.PERF_COUNTER_BLOCK();
                for (int i = 0; i < dataBlock.NumObjectTypes; i++)
                {
                    Interop.Advapi32.PERF_OBJECT_TYPE type = new Interop.Advapi32.PERF_OBJECT_TYPE();
                    Marshal.PtrToStructure(typePtr, type);
                    IntPtr instancePtr = (IntPtr)((long)typePtr + type.DefinitionLength);
                    IntPtr counterPtr  = (IntPtr)((long)typePtr + type.HeaderLength);
                    List <Interop.Advapi32.PERF_COUNTER_DEFINITION> counterList = new List <Interop.Advapi32.PERF_COUNTER_DEFINITION>();

                    for (int j = 0; j < type.NumCounters; j++)
                    {
                        Interop.Advapi32.PERF_COUNTER_DEFINITION counter = new Interop.Advapi32.PERF_COUNTER_DEFINITION();
                        Marshal.PtrToStructure(counterPtr, counter);
                        string counterName = library.GetCounterName(counter.CounterNameTitleIndex);

                        if (type.ObjectNameTitleIndex == processIndex)
                        {
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName);
                        }
                        else if (type.ObjectNameTitleIndex == threadIndex)
                        {
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName);
                        }
                        counterList.Add(counter);
                        counterPtr = (IntPtr)((long)counterPtr + counter.ByteLength);
                    }

                    Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters = counterList.ToArray();

                    for (int j = 0; j < type.NumInstances; j++)
                    {
                        Marshal.PtrToStructure(instancePtr, instance);
                        IntPtr namePtr      = (IntPtr)((long)instancePtr + instance.NameOffset);
                        string instanceName = Marshal.PtrToStringUni(namePtr);
                        if (instanceName.Equals("_Total"))
                        {
                            continue;
                        }
                        IntPtr counterBlockPtr = (IntPtr)((long)instancePtr + instance.ByteLength);
                        Marshal.PtrToStructure(counterBlockPtr, counterBlock);
                        if (type.ObjectNameTitleIndex == processIndex)
                        {
                            ProcessInfo processInfo = GetProcessInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (processInfo.ProcessId == 0 && string.Compare(instanceName, "Idle", StringComparison.OrdinalIgnoreCase) != 0)
                            {
                                // Sometimes we'll get a process structure that is not completely filled in.
                                // We can catch some of these by looking for non-"idle" processes that have id 0
                                // and ignoring those.
#if FEATURE_TRACESWITCH
                                Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos() - found a non-idle process with id 0; ignoring.");
#endif
                            }
                            else
                            {
                                if (processInfos.ContainsKey(processInfo.ProcessId))
                                {
                                    // We've found two entries in the perfcounters that claim to be the
                                    // same process.  We throw an exception.  Is this really going to be
                                    // helpful to the user?  Should we just ignore?
#if FEATURE_TRACESWITCH
                                    Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos() - found a duplicate process id");
#endif
                                }
                                else
                                {
                                    // the performance counters keep a 15 character prefix of the exe name, and then delete the ".exe",
                                    // if it's in the first 15.  The problem is that sometimes that will leave us with part of ".exe"
                                    // at the end.  If instanceName ends in ".", ".e", or ".ex" we remove it.
                                    string processName = instanceName;
                                    if (processName.Length == 15)
                                    {
                                        if (instanceName.EndsWith(".", StringComparison.Ordinal))
                                        {
                                            processName = instanceName.Substring(0, 14);
                                        }
                                        else if (instanceName.EndsWith(".e", StringComparison.Ordinal))
                                        {
                                            processName = instanceName.Substring(0, 13);
                                        }
                                        else if (instanceName.EndsWith(".ex", StringComparison.Ordinal))
                                        {
                                            processName = instanceName.Substring(0, 12);
                                        }
                                    }
                                    processInfo.ProcessName = processName;
                                    processInfos.Add(processInfo.ProcessId, processInfo);
                                }
                            }
                        }
                        else if (type.ObjectNameTitleIndex == threadIndex)
                        {
                            ThreadInfo threadInfo = GetThreadInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (threadInfo._threadId != 0)
                            {
                                threadInfos.Add(threadInfo);
                            }
                        }
                        instancePtr = (IntPtr)((long)instancePtr + instance.ByteLength + counterBlock.ByteLength);
                    }

                    typePtr = (IntPtr)((long)typePtr + type.TotalByteLength);
                }
            }
            finally
            {
                if (dataHandle.IsAllocated)
                {
                    dataHandle.Free();
                }
            }

            for (int i = 0; i < threadInfos.Count; i++)
            {
                ThreadInfo  threadInfo = (ThreadInfo)threadInfos[i];
                ProcessInfo processInfo;
                if (processInfos.TryGetValue(threadInfo._processId, out processInfo))
                {
                    processInfo._threadInfoList.Add(threadInfo);
                }
            }

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return(temp);
        }
Example #4
0
        static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library, int processIndex, int threadIndex, byte[] data)
        {
#if FEATURE_TRACESWITCH
            Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos()");
#endif
            Dictionary<int, ProcessInfo> processInfos = new Dictionary<int, ProcessInfo>();
            List<ThreadInfo> threadInfos = new List<ThreadInfo>();

            GCHandle dataHandle = new GCHandle();
            try
            {
                dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                IntPtr dataBlockPtr = dataHandle.AddrOfPinnedObject();
                Interop.Advapi32.PERF_DATA_BLOCK dataBlock = new Interop.Advapi32.PERF_DATA_BLOCK();
                Marshal.PtrToStructure(dataBlockPtr, dataBlock);
                IntPtr typePtr = (IntPtr)((long)dataBlockPtr + dataBlock.HeaderLength);
                Interop.Advapi32.PERF_INSTANCE_DEFINITION instance = new Interop.Advapi32.PERF_INSTANCE_DEFINITION();
                Interop.Advapi32.PERF_COUNTER_BLOCK counterBlock = new Interop.Advapi32.PERF_COUNTER_BLOCK();
                for (int i = 0; i < dataBlock.NumObjectTypes; i++)
                {
                    Interop.Advapi32.PERF_OBJECT_TYPE type = new Interop.Advapi32.PERF_OBJECT_TYPE();
                    Marshal.PtrToStructure(typePtr, type);
                    IntPtr instancePtr = (IntPtr)((long)typePtr + type.DefinitionLength);
                    IntPtr counterPtr = (IntPtr)((long)typePtr + type.HeaderLength);
                    List<Interop.Advapi32.PERF_COUNTER_DEFINITION> counterList = new List<Interop.Advapi32.PERF_COUNTER_DEFINITION>();

                    for (int j = 0; j < type.NumCounters; j++)
                    {
                        Interop.Advapi32.PERF_COUNTER_DEFINITION counter = new Interop.Advapi32.PERF_COUNTER_DEFINITION();
                        Marshal.PtrToStructure(counterPtr, counter);
                        string counterName = library.GetCounterName(counter.CounterNameTitleIndex);

                        if (type.ObjectNameTitleIndex == processIndex)
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName);
                        else if (type.ObjectNameTitleIndex == threadIndex)
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName);
                        counterList.Add(counter);
                        counterPtr = (IntPtr)((long)counterPtr + counter.ByteLength);
                    }

                    Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters = counterList.ToArray();

                    for (int j = 0; j < type.NumInstances; j++)
                    {
                        Marshal.PtrToStructure(instancePtr, instance);
                        IntPtr namePtr = (IntPtr)((long)instancePtr + instance.NameOffset);
                        string instanceName = Marshal.PtrToStringUni(namePtr);
                        if (instanceName.Equals("_Total")) continue;
                        IntPtr counterBlockPtr = (IntPtr)((long)instancePtr + instance.ByteLength);
                        Marshal.PtrToStructure(counterBlockPtr, counterBlock);
                        if (type.ObjectNameTitleIndex == processIndex)
                        {
                            ProcessInfo processInfo = GetProcessInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (processInfo.ProcessId == 0 && string.Compare(instanceName, "Idle", StringComparison.OrdinalIgnoreCase) != 0)
                            {
                                // Sometimes we'll get a process structure that is not completely filled in.
                                // We can catch some of these by looking for non-"idle" processes that have id 0
                                // and ignoring those.
#if FEATURE_TRACESWITCH
                                Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos() - found a non-idle process with id 0; ignoring.");
#endif
                            }
                            else
                            {
                                if (processInfos.ContainsKey(processInfo.ProcessId))
                                {
                                    // We've found two entries in the perfcounters that claim to be the
                                    // same process.  We throw an exception.  Is this really going to be
                                    // helpful to the user?  Should we just ignore?
#if FEATURE_TRACESWITCH
                                    Debug.WriteLineIf(Process._processTracing.TraceVerbose, "GetProcessInfos() - found a duplicate process id");
#endif
                                }
                                else
                                {
                                    // the performance counters keep a 15 character prefix of the exe name, and then delete the ".exe",
                                    // if it's in the first 15.  The problem is that sometimes that will leave us with part of ".exe"
                                    // at the end.  If instanceName ends in ".", ".e", or ".ex" we remove it.
                                    string processName = instanceName;
                                    if (processName.Length == 15)
                                    {
                                        if (instanceName.EndsWith(".", StringComparison.Ordinal)) processName = instanceName.Substring(0, 14);
                                        else if (instanceName.EndsWith(".e", StringComparison.Ordinal)) processName = instanceName.Substring(0, 13);
                                        else if (instanceName.EndsWith(".ex", StringComparison.Ordinal)) processName = instanceName.Substring(0, 12);
                                    }
                                    processInfo.ProcessName = processName;
                                    processInfos.Add(processInfo.ProcessId, processInfo);
                                }
                            }
                        }
                        else if (type.ObjectNameTitleIndex == threadIndex)
                        {
                            ThreadInfo threadInfo = GetThreadInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (threadInfo._threadId != 0) threadInfos.Add(threadInfo);
                        }
                        instancePtr = (IntPtr)((long)instancePtr + instance.ByteLength + counterBlock.ByteLength);
                    }

                    typePtr = (IntPtr)((long)typePtr + type.TotalByteLength);
                }
            }
            finally
            {
                if (dataHandle.IsAllocated) dataHandle.Free();
            }

            for (int i = 0; i < threadInfos.Count; i++)
            {
                ThreadInfo threadInfo = (ThreadInfo)threadInfos[i];
                ProcessInfo processInfo;
                if (processInfos.TryGetValue(threadInfo._processId, out processInfo))
                {
                    processInfo._threadInfoList.Add(threadInfo);
                }
            }

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return temp;
        }