Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Monitoring / system / Diagnosticts / PerformanceCounterLib.cs / 1407647 / PerformanceCounterLib.cs
namespace System.Diagnostics { using System.Runtime.InteropServices; using System.Globalization; using System.Security.Permissions; using System.Security; using System.Text; using System.Threading; using System.Reflection; using System.Collections; using System.ComponentModel; using System.Collections.Specialized; using Microsoft.Win32; using System.IO; using System.Runtime.Serialization; using System.Runtime.Versioning; internal class PerformanceCounterLib { internal const string PerfShimName = "netfxperf.dll"; internal const string OpenEntryPoint = "OpenPerformanceData"; internal const string CollectEntryPoint = "CollectPerformanceData"; internal const string CloseEntryPoint = "ClosePerformanceData"; internal const string SingleInstanceName = "systemdiagnosticsperfcounterlibsingleinstance"; private const string PerflibPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"; internal const string ServicePath = "SYSTEM\\CurrentControlSet\\Services"; private const string categorySymbolPrefix = "OBJECT_"; private const string conterSymbolPrefix = "DEVICE_COUNTER_"; private const string helpSufix = "_HELP"; private const string nameSufix = "_NAME"; private const string textDefinition = "[text]"; private const string infoDefinition = "[info]"; private const string languageDefinition = "[languages]"; private const string objectDefinition = "[objects]"; private const string driverNameKeyword = "drivername"; private const string symbolFileKeyword = "symbolfile"; private const string defineKeyword = "#define"; private const string languageKeyword = "language"; private const string DllName = "netfxperf.dll"; private const int EnglishLCID = 0x009; private static string computerName; private static string iniFilePath; private static string symbolFilePath; private PerformanceMonitor performanceMonitor; private string machineName; private string perfLcid; private Hashtable customCategoryTable; private static Hashtable libraryTable; private Hashtable categoryTable; private Hashtable nameTable; private Hashtable helpTable; private readonly object CategoryTableLock = new Object(); private readonly object NameTableLock = new Object(); private readonly object HelpTableLock = new Object(); private static Object s_InternalSyncObject; private static Object InternalSyncObject { get { if (s_InternalSyncObject == null) { Object o = new Object(); Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } return s_InternalSyncObject; } } internal PerformanceCounterLib(string machineName, string lcid) { this.machineName = machineName; this.perfLcid = lcid; } ///internal static string ComputerName { get { if (computerName == null) { lock (InternalSyncObject) { if (computerName == null) { StringBuilder sb = new StringBuilder(256); SafeNativeMethods.GetComputerName(sb, new int[] {sb.Capacity}); computerName = sb.ToString(); } } } return computerName; } } private unsafe Hashtable CategoryTable { get { if (this.categoryTable == null) { lock (this.CategoryTableLock) { if (this.categoryTable == null) { byte[] perfData = GetPerformanceData("Global"); fixed (byte* perfDataPtr = perfData) { IntPtr dataRef = new IntPtr( (void*) perfDataPtr); NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK(); Marshal.PtrToStructure(dataRef, dataBlock); dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength); int categoryNumber = dataBlock.NumObjectTypes; // on some machines MSMQ claims to have 4 categories, even though it only has 2. // This causes us to walk past the end of our data, potentially crashing or reading // data we shouldn't. We use endPerfData to make sure we don't go past the end // of the perf data. (ASURT 137097) long endPerfData = (long)(new IntPtr((void*)perfDataPtr)) + dataBlock.TotalByteLength; Hashtable tempCategoryTable = new Hashtable(categoryNumber, StringComparer.OrdinalIgnoreCase); for (int index = 0; index < categoryNumber && ((long) dataRef < endPerfData); index++) { NativeMethods.PERF_OBJECT_TYPE perfObject = new NativeMethods.PERF_OBJECT_TYPE(); Marshal.PtrToStructure(dataRef, perfObject); CategoryEntry newCategoryEntry = new CategoryEntry(perfObject); IntPtr nextRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength); dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength); int index3 = 0; int previousCounterIndex = -1; //Need to filter out counters that are repeated, some providers might //return several adyacent copies of the same counter. for (int index2 = 0; index2 < newCategoryEntry.CounterIndexes.Length; ++ index2) { NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); Marshal.PtrToStructure(dataRef, perfCounter); if (perfCounter.CounterNameTitleIndex != previousCounterIndex) { newCategoryEntry.CounterIndexes[index3] = perfCounter.CounterNameTitleIndex; newCategoryEntry.HelpIndexes[index3] = perfCounter.CounterHelpTitleIndex; previousCounterIndex = perfCounter.CounterNameTitleIndex; ++ index3; } dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength); } //Lets adjust the entry counter arrays in case there were repeated copies if (index3 < newCategoryEntry.CounterIndexes.Length) { int[] adjustedCounterIndexes = new int[index3]; int[] adjustedHelpIndexes = new int[index3]; Array.Copy(newCategoryEntry.CounterIndexes, adjustedCounterIndexes, index3); Array.Copy(newCategoryEntry.HelpIndexes, adjustedHelpIndexes, index3); newCategoryEntry.CounterIndexes = adjustedCounterIndexes; newCategoryEntry.HelpIndexes = adjustedHelpIndexes; } string categoryName = (string)this.NameTable[newCategoryEntry.NameIndex]; if (categoryName != null) tempCategoryTable[categoryName] = newCategoryEntry; dataRef = nextRef; } this.categoryTable = tempCategoryTable; } } } } return this.categoryTable; } } internal Hashtable HelpTable { get { if (this.helpTable == null) { lock(this.HelpTableLock) { if (this.helpTable == null) this.helpTable = GetStringTable(true); } } return this.helpTable; } } // Returns a temp file name private static string IniFilePath { [ResourceExposure(ResourceScope.AppDomain)] [ResourceConsumption(ResourceScope.AppDomain)] get { if (iniFilePath == null) { lock (InternalSyncObject) { if (iniFilePath == null) { // Need to assert Environment permissions here // the environment check is not exposed as a public // method EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted); environmentPermission.Assert(); try { iniFilePath = Path.GetTempFileName(); } finally { EnvironmentPermission.RevertAssert(); } } } } return iniFilePath; } } internal Hashtable NameTable { get { if (this.nameTable == null) { lock(this.NameTableLock) { if (this.nameTable == null) this.nameTable = GetStringTable(false); } } return this.nameTable; } } // Returns a temp file name private static string SymbolFilePath { [ResourceExposure(ResourceScope.AppDomain)] [ResourceConsumption(ResourceScope.AppDomain | ResourceScope.Machine)] get { if (symbolFilePath == null) { lock (InternalSyncObject) { if (symbolFilePath == null) { string tempPath; EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted); environmentPermission.Assert(); tempPath = Path.GetTempPath(); EnvironmentPermission.RevertAssert(); // We need both FileIOPermission EvironmentPermission PermissionSet ps = new PermissionSet(PermissionState.None); ps.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted)); ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Write, tempPath)); ps.Assert(); try { symbolFilePath = Path.GetTempFileName(); } finally { PermissionSet.RevertAssert(); } } } } return symbolFilePath; } } internal static bool CategoryExists(string machine, string category) { PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); if (library.CategoryExists(category)) return true; if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); if (library.CategoryExists(category)) return true; culture = culture.Parent; } } return false; } internal bool CategoryExists(string category) { return CategoryTable.ContainsKey(category); } internal static void CloseAllLibraries() { if (libraryTable != null) { foreach (PerformanceCounterLib library in libraryTable.Values) library.Close(); libraryTable = null; } } internal static void CloseAllTables() { if (libraryTable != null) { foreach (PerformanceCounterLib library in libraryTable.Values) library.CloseTables(); } } internal void CloseTables() { this.nameTable = null; this.helpTable = null; this.categoryTable = null; this.customCategoryTable = null; } internal void Close() { if (this.performanceMonitor != null) { this.performanceMonitor.Close(); this.performanceMonitor = null; } CloseTables(); } internal static bool CounterExists(string machine, string category, string counter) { PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); bool categoryExists = false; bool counterExists = library.CounterExists(category, counter, ref categoryExists); if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); counterExists = library.CounterExists(category, counter, ref categoryExists); if (counterExists) break; culture = culture.Parent; } } if (!categoryExists) { // Consider adding diagnostic logic here, may be we can dump the nameTable... throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); } return counterExists; } private bool CounterExists(string category, string counter, ref bool categoryExists) { categoryExists = false; if (!CategoryTable.ContainsKey(category)) return false; else categoryExists = true; CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { int counterIndex = entry.CounterIndexes[index]; string counterName = (string)this.NameTable[counterIndex]; if (counterName == null) counterName = String.Empty; if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) return true; } return false; } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void CreateIniFile(string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string[] languageIds) { //SECREVIEW: PerformanceCounterPermission must have been demanded before FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted); permission.Assert(); try { StreamWriter iniWriter = new StreamWriter(IniFilePath, false, Encoding.Unicode); try { //NT4 won't be able to parse Unicode ini files without this //extra white space. iniWriter.WriteLine(""); iniWriter.WriteLine(infoDefinition); iniWriter.Write(driverNameKeyword); iniWriter.Write("="); iniWriter.WriteLine(categoryName); iniWriter.Write(symbolFileKeyword); iniWriter.Write("="); iniWriter.WriteLine(Path.GetFileName(SymbolFilePath)); iniWriter.WriteLine(""); iniWriter.WriteLine(languageDefinition); foreach (string languageId in languageIds) { iniWriter.Write(languageId); iniWriter.Write("="); iniWriter.Write(languageKeyword); iniWriter.WriteLine(languageId); } iniWriter.WriteLine(""); iniWriter.WriteLine(objectDefinition); foreach (string languageId in languageIds) { iniWriter.Write(categorySymbolPrefix); iniWriter.Write("1_"); iniWriter.Write(languageId); iniWriter.Write(nameSufix); iniWriter.Write("="); iniWriter.WriteLine(categoryName); } iniWriter.WriteLine(""); iniWriter.WriteLine(textDefinition); foreach (string languageId in languageIds) { iniWriter.Write(categorySymbolPrefix); iniWriter.Write("1_"); iniWriter.Write(languageId); iniWriter.Write(nameSufix); iniWriter.Write("="); iniWriter.WriteLine(categoryName); iniWriter.Write(categorySymbolPrefix); iniWriter.Write("1_"); iniWriter.Write(languageId); iniWriter.Write(helpSufix); iniWriter.Write("="); if (categoryHelp == null || categoryHelp == String.Empty) iniWriter.WriteLine(SR.GetString(SR.HelpNotAvailable)); else iniWriter.WriteLine(categoryHelp); int counterIndex = 0; foreach (CounterCreationData counterData in creationData) { ++counterIndex; iniWriter.WriteLine(""); iniWriter.Write(conterSymbolPrefix); iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture)); iniWriter.Write("_"); iniWriter.Write(languageId); iniWriter.Write(nameSufix); iniWriter.Write("="); iniWriter.WriteLine(counterData.CounterName); iniWriter.Write(conterSymbolPrefix); iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture)); iniWriter.Write("_"); iniWriter.Write(languageId); iniWriter.Write(helpSufix); iniWriter.Write("="); Debug.Assert(!String.IsNullOrEmpty(counterData.CounterHelp), "CounterHelp should have been fixed up by the caller"); iniWriter.WriteLine(counterData.CounterHelp); } } iniWriter.WriteLine(""); } finally { iniWriter.Close(); } } finally { FileIOPermission.RevertAssert(); } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void CreateRegistryEntry(string categoryName, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection creationData, ref bool iniRegistered) { RegistryKey serviceParentKey = null; RegistryKey serviceKey = null; RegistryKey linkageKey = null; //SECREVIEW: Whoever is able to call this function, must already // have demmanded PerformanceCounterPermission // we can therefore assert the RegistryPermission. RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted); registryPermission.Assert(); try { serviceParentKey = Registry.LocalMachine.OpenSubKey(ServicePath, true); serviceKey = serviceParentKey.OpenSubKey(categoryName + "\\Performance", true); if (serviceKey == null) serviceKey = serviceParentKey.CreateSubKey(categoryName + "\\Performance"); serviceKey.SetValue("Open","OpenPerformanceData"); serviceKey.SetValue("Collect", "CollectPerformanceData"); serviceKey.SetValue("Close","ClosePerformanceData"); serviceKey.SetValue("Library", DllName); serviceKey.SetValue("IsMultiInstance", (int) categoryType, RegistryValueKind.DWord); serviceKey.SetValue("CategoryOptions", 0x3, RegistryValueKind.DWord); string [] counters = new string[creationData.Count]; string [] counterTypes = new string[creationData.Count]; for (int i = 0; i < creationData.Count; i++) { counters[i] = creationData[i].CounterName; counterTypes[i] = ((int) creationData[i].CounterType).ToString(CultureInfo.InvariantCulture); } linkageKey = serviceParentKey.OpenSubKey(categoryName + "\\Linkage" , true); if (linkageKey == null) linkageKey = serviceParentKey.CreateSubKey(categoryName + "\\Linkage" ); linkageKey.SetValue("Export", new string[]{categoryName}); serviceKey.SetValue("Counter Types", (object) counterTypes); serviceKey.SetValue("Counter Names", (object) counters); object firstID = serviceKey.GetValue("First Counter"); if (firstID != null) iniRegistered = true; else iniRegistered = false; } finally { if (serviceKey != null) serviceKey.Close(); if (linkageKey != null) linkageKey.Close(); if (serviceParentKey != null) serviceParentKey.Close(); RegistryPermission.RevertAssert(); } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void CreateSymbolFile(CounterCreationDataCollection creationData) { //SECREVIEW: PerformanceCounterPermission must have been demanded before FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted); permission.Assert(); try { StreamWriter symbolWriter = new StreamWriter(SymbolFilePath); try { symbolWriter.Write(defineKeyword); symbolWriter.Write(" "); symbolWriter.Write(categorySymbolPrefix); symbolWriter.WriteLine("1 0;"); for (int counterIndex = 1; counterIndex <= creationData.Count; ++ counterIndex) { symbolWriter.Write(defineKeyword); symbolWriter.Write(" "); symbolWriter.Write(conterSymbolPrefix); symbolWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture)); symbolWriter.Write(" "); symbolWriter.Write((counterIndex * 2).ToString(CultureInfo.InvariantCulture)); symbolWriter.WriteLine(";"); } symbolWriter.WriteLine(""); } finally { symbolWriter.Close(); } } finally { FileIOPermission.RevertAssert(); } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void DeleteRegistryEntry(string categoryName) { RegistryKey serviceKey = null; //SECREVIEW: Whoever is able to call this function, must already // have demmanded PerformanceCounterPermission // we can therefore assert the RegistryPermission. RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted); registryPermission.Assert(); try { serviceKey = Registry.LocalMachine.OpenSubKey(ServicePath, true); bool deleteCategoryKey = false; using (RegistryKey categoryKey = serviceKey.OpenSubKey(categoryName, true)) { if (categoryKey != null) { if (categoryKey.GetValueNames().Length == 0) { deleteCategoryKey = true; } else { categoryKey.DeleteSubKeyTree("Linkage"); categoryKey.DeleteSubKeyTree("Performance"); } } } if (deleteCategoryKey) serviceKey.DeleteSubKeyTree(categoryName); } finally { if (serviceKey != null) serviceKey.Close(); RegistryPermission.RevertAssert(); } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void DeleteTemporaryFiles() { try { File.Delete(IniFilePath); } catch { } try { File.Delete(SymbolFilePath); } catch { } } // Ensures that the customCategoryTable is initialized and decides whether the category passed in // 1) is a custom category // 2) is a multi instance custom category // The return value is whether the category is a custom category or not. [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] internal bool FindCustomCategory(string category, out PerformanceCounterCategoryType categoryType) { RegistryKey key = null; RegistryKey baseKey = null; categoryType = PerformanceCounterCategoryType.Unknown; if (this.customCategoryTable == null) { Interlocked.CompareExchange(ref this.customCategoryTable, new Hashtable(StringComparer.OrdinalIgnoreCase), null); } if (this.customCategoryTable.ContainsKey(category)) { categoryType= (PerformanceCounterCategoryType) this.customCategoryTable[category]; return true; } else { //SECREVIEW: Whoever is able to call this function, must already // have demanded PerformanceCounterPermission // we can therefore assert the RegistryPermission. PermissionSet ps = new PermissionSet(PermissionState.None); ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); ps.Assert(); try { string keyPath = ServicePath + "\\" + category + "\\Performance"; if (machineName == "." || String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) { key = Registry.LocalMachine.OpenSubKey(keyPath); } else { baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "\\\\" + this.machineName); if (baseKey != null) { try { key = baseKey.OpenSubKey(keyPath); } catch (SecurityException) { // we may not have permission to read the registry key on the remote machine. The security exception // is thrown when RegOpenKeyEx returns ERROR_ACCESS_DENIED or ERROR_BAD_IMPERSONATION_LEVEL // // In this case we return an 'Unknown' category type and 'false' to indicate the category is *not* custom. // categoryType = PerformanceCounterCategoryType.Unknown; this.customCategoryTable[category] = categoryType; return false; } } } if (key != null) { object systemDllName = key.GetValue("Library"); if (systemDllName != null && systemDllName is string && String.Compare((string)systemDllName, PerformanceCounterLib.PerfShimName, StringComparison.OrdinalIgnoreCase) == 0) { object isMultiInstanceObject = key.GetValue("IsMultiInstance"); if (isMultiInstanceObject != null) { categoryType = (PerformanceCounterCategoryType) isMultiInstanceObject; if (categoryType < PerformanceCounterCategoryType.Unknown || categoryType > PerformanceCounterCategoryType.MultiInstance) categoryType = PerformanceCounterCategoryType.Unknown; } else categoryType = PerformanceCounterCategoryType.Unknown; object objectID = key.GetValue("First Counter"); if (objectID != null) { int firstID = (int)objectID; this.customCategoryTable[category] = categoryType; return true; } } } } finally { if (key != null) key.Close(); if (baseKey != null) baseKey.Close(); PermissionSet.RevertAssert(); } } return false; } internal static string[] GetCategories(string machineName) { PerformanceCounterLib library; CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machineName, culture); string[] categories = library.GetCategories(); if (categories.Length != 0 ) return categories; culture = culture.Parent; } library = GetPerformanceCounterLib(machineName, new CultureInfo(EnglishLCID)); return library.GetCategories(); } internal string[] GetCategories() { ICollection keys = CategoryTable.Keys; string[] categories = new string[keys.Count]; keys.CopyTo(categories, 0); return categories; } internal static string GetCategoryHelp(string machine, string category) { PerformanceCounterLib library; string help; //First check the current culture for the category. This will allow //PerformanceCounterCategory.CategoryHelp to return localized strings. if(CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); help = library.GetCategoryHelp(category); if (help != null) return help; culture = culture.Parent; } } //We did not find the category walking up the culture hierarchy. Try looking // for the category in the default culture English. library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); help = library.GetCategoryHelp(category); if (help == null) throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); return help; } private string GetCategoryHelp(string category) { CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; if (entry == null) return null; return (string)this.HelpTable[entry.HelpIndex]; } internal static CategorySample GetCategorySample(string machine, string category) { PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); CategorySample sample = library.GetCategorySample(category); if (sample == null && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); sample = library.GetCategorySample(category); if (sample != null) return sample; culture = culture.Parent; } } if (sample == null) throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); return sample; } private CategorySample GetCategorySample(string category) { CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; if (entry == null) return null; CategorySample sample = null; byte[] dataRef = GetPerformanceData(entry.NameIndex.ToString(CultureInfo.InvariantCulture)); if (dataRef == null) throw new InvalidOperationException(SR.GetString(SR.CantReadCategory, category)); sample = new CategorySample(dataRef, entry, this); return sample; } internal static string[] GetCounters(string machine, string category) { PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); bool categoryExists = false; string[] counters = library.GetCounters(category, ref categoryExists); if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); counters = library.GetCounters(category, ref categoryExists); if (categoryExists) return counters; culture = culture.Parent; } } if (!categoryExists) throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); return counters; } private string[] GetCounters(string category, ref bool categoryExists) { categoryExists = false; CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; if (entry == null) return null; else categoryExists = true; int index2 = 0; string[] counters = new string[entry.CounterIndexes.Length]; for (int index = 0; index < counters.Length; ++ index) { int counterIndex = entry.CounterIndexes[index]; string counterName = (string)this.NameTable[counterIndex]; if (counterName != null && counterName != String.Empty) { counters[index2] = counterName; ++index2; } } //Lets adjust the array in case there were null entries if (index2 < counters.Length) { string[] adjustedCounters = new string[index2]; Array.Copy(counters, adjustedCounters, index2); counters = adjustedCounters; } return counters; } internal static string GetCounterHelp(string machine, string category, string counter) { PerformanceCounterLib library; bool categoryExists = false; string help; //First check the current culture for the counter. This will allow //PerformanceCounter.CounterHelp to return localized strings. if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); help = library.GetCounterHelp(category, counter, ref categoryExists); if (categoryExists) return help; culture = culture.Parent; } } //We did not find the counter walking up the culture hierarchy. Try looking // for the counter in the default culture English. library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); help = library.GetCounterHelp(category, counter, ref categoryExists); if (!categoryExists) throw new InvalidOperationException(SR.GetString(SR.MissingCategoryDetail, category)); return help; } private string GetCounterHelp(string category, string counter, ref bool categoryExists) { categoryExists = false; CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; if (entry == null) return null; else categoryExists = true; int helpIndex = -1; for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { int counterIndex = entry.CounterIndexes[index]; string counterName = (string)this.NameTable[counterIndex]; if (counterName == null) counterName = String.Empty; if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) { helpIndex = entry.HelpIndexes[index]; break; } } if (helpIndex == -1) throw new InvalidOperationException(SR.GetString(SR.MissingCounter, counter)); string help = (string)this.HelpTable[helpIndex]; if (help == null) return String.Empty; else return help; } internal string GetCounterName(int index) { if (this.NameTable.ContainsKey(index)) return (string)this.NameTable[index]; return ""; } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static string[] GetLanguageIds() { RegistryKey libraryParentKey = null; string[] ids = new string[0]; new RegistryPermission(PermissionState.Unrestricted).Assert(); try { libraryParentKey = Registry.LocalMachine.OpenSubKey(PerflibPath); if (libraryParentKey != null) ids = libraryParentKey.GetSubKeyNames(); } finally { if (libraryParentKey != null) libraryParentKey.Close(); RegistryPermission.RevertAssert(); } return ids; } internal static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture) { SharedUtils.CheckEnvironment(); string lcidString = culture.LCID.ToString("X3", CultureInfo.InvariantCulture); if (machineName.CompareTo(".") == 0) machineName = ComputerName.ToLower(CultureInfo.InvariantCulture); else machineName = machineName.ToLower(CultureInfo.InvariantCulture); if (PerformanceCounterLib.libraryTable == null) { lock (InternalSyncObject) { if (PerformanceCounterLib.libraryTable == null) PerformanceCounterLib.libraryTable = new Hashtable(); } } string libraryKey = machineName + ":" + lcidString; if (PerformanceCounterLib.libraryTable.Contains(libraryKey)) return (PerformanceCounterLib)PerformanceCounterLib.libraryTable[libraryKey]; else { PerformanceCounterLib library = new PerformanceCounterLib(machineName, lcidString); PerformanceCounterLib.libraryTable[libraryKey] = library; return library; } } internal byte[] GetPerformanceData(string item) { if (this.performanceMonitor == null) { lock (InternalSyncObject) { if (this.performanceMonitor == null) this.performanceMonitor = new PerformanceMonitor(this.machineName); } } return this.performanceMonitor.GetData(item); } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private Hashtable GetStringTable(bool isHelp) { Hashtable stringTable; RegistryKey libraryKey; PermissionSet ps = new PermissionSet(PermissionState.None); ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); ps.Assert(); if (String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) libraryKey = Registry.PerformanceData; else { libraryKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, this.machineName); } try { string[] names = null; int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins int waitSleep = 0; // In some stress situations, querying counter values from // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009 // often returns null/empty data back. We should build fault-tolerance logic to // make it more reliable because getting null back once doesn't necessarily mean // that the data is corrupted, most of the time we would get the data just fine // in subsequent tries. while (waitRetries > 0) { try { if (!isHelp) names = (string[])libraryKey.GetValue("Counter " + perfLcid); else names = (string[])libraryKey.GetValue("Explain " + perfLcid); if ((names == null) || (names.Length == 0)) { --waitRetries; if (waitSleep == 0) waitSleep = 10; else { System.Threading.Thread.Sleep(waitSleep); waitSleep *= 2; } } else break; } catch (IOException) { // RegistryKey throws if it can't find the value. We want to return an empty table // and throw a different exception higher up the stack. names = null; break; } catch (InvalidCastException) { // Unable to cast object of type 'System.Byte[]' to type 'System.String[]'. // this happens when the registry data store is corrupt and the type is not even REG_MULTI_SZ names = null; break; } } if (names == null) stringTable = new Hashtable(); else { stringTable = new Hashtable(names.Length/2); for (int index = 0; index < (names.Length/2); ++ index) { string nameString = names[(index *2) + 1]; if (nameString == null) nameString = String.Empty; int key; if (!Int32.TryParse(names[index * 2], NumberStyles.Integer, CultureInfo.InvariantCulture, out key)) { if (isHelp) { // Category Help Table throw new InvalidOperationException(SR.GetString(SR.CategoryHelpCorrupt, names[index * 2])); } else { // Counter Name Table throw new InvalidOperationException(SR.GetString(SR.CounterNameCorrupt, names[index * 2])); } } stringTable[key] = nameString; } } } finally { libraryKey.Close(); } return stringTable; } internal static bool IsCustomCategory(string machine, string category) { PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); if (library.IsCustomCategory(category)) return true; if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); if (library.IsCustomCategory(category)) return true; culture = culture.Parent; } } return false; } internal static bool IsBaseCounter(int type) { return (type == NativeMethods.PERF_AVERAGE_BASE || type == NativeMethods.PERF_COUNTER_MULTI_BASE || type == NativeMethods.PERF_RAW_BASE || type == NativeMethods.PERF_LARGE_RAW_BASE || type == NativeMethods.PERF_SAMPLE_BASE); } private bool IsCustomCategory(string category) { PerformanceCounterCategoryType categoryType; return FindCustomCategory(category, out categoryType); } internal static PerformanceCounterCategoryType GetCategoryType(string machine, string category) { PerformanceCounterCategoryType categoryType = PerformanceCounterCategoryType.Unknown; PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); if (!library.FindCustomCategory(category, out categoryType)) { if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) { library = GetPerformanceCounterLib(machine, culture); if (library.FindCustomCategory(category, out categoryType)) return categoryType; culture = culture.Parent; } } } return categoryType; } /* // Creates a category with an ini file supplied by the user. Currently this is not available. internal static void RegisterCategory(string machineName, string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string localizedIniFilePath) { bool iniRegistered = false; CreateRegistryEntry(machineName, categoryName, creationData, ref iniRegistered); if (!iniRegistered) RegisterFiles(machineName, localizedIniFilePath, false); CloseAllTables(); } */ [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal static void RegisterCategory(string categoryName, PerformanceCounterCategoryType categoryType, string categoryHelp, CounterCreationDataCollection creationData) { try { bool iniRegistered = false; CreateRegistryEntry(categoryName, categoryType, creationData, ref iniRegistered); if (!iniRegistered) { string[] languageIds = GetLanguageIds(); CreateIniFile(categoryName, categoryHelp, creationData, languageIds); CreateSymbolFile(creationData); RegisterFiles(IniFilePath, false); } CloseAllTables(); CloseAllLibraries(); } finally { DeleteTemporaryFiles(); } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static void RegisterFiles(string arg0, bool unregister) { Process p; ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.UseShellExecute = false; processStartInfo.CreateNoWindow = true; processStartInfo.ErrorDialog = false; processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; processStartInfo.WorkingDirectory = Environment.SystemDirectory; if (unregister) processStartInfo.FileName = Environment.SystemDirectory + "\\unlodctr.exe"; else processStartInfo.FileName = Environment.SystemDirectory + "\\lodctr.exe"; int res = 0; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); try { processStartInfo.Arguments = "\"" + arg0 + "\""; p = Process.Start(processStartInfo); p.WaitForExit(); res = p.ExitCode; } finally { SecurityPermission.RevertAssert(); } if (res == NativeMethods.ERROR_ACCESS_DENIED) { throw new UnauthorizedAccessException(SR.GetString(SR.CantChangeCategoryRegistration, arg0)); } // Look at Q269225, unlodctr might return 2 when WMI is not installed. if (unregister && res == 2) res = 0; if (res != 0) throw SharedUtils.CreateSafeWin32Exception(res); } internal static void UnregisterCategory(string categoryName) { RegisterFiles(categoryName, true); DeleteRegistryEntry(categoryName); CloseAllTables(); CloseAllLibraries(); } } internal class PerformanceMonitor { private RegistryKey perfDataKey = null; private string machineName; internal PerformanceMonitor(string machineName) { this.machineName = machineName; Init(); } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void Init() { try { if (machineName != "." && String.Compare(machineName, PerformanceCounterLib.ComputerName, StringComparison.OrdinalIgnoreCase) != 0) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); perfDataKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, machineName); } else perfDataKey = Registry.PerformanceData; } catch (UnauthorizedAccessException) { // we need to do this for compatibility with v1.1 and v1.0. throw new Win32Exception(NativeMethods.ERROR_ACCESS_DENIED); } catch (IOException e) { // we need to do this for compatibility with v1.1 and v1.0. throw new Win32Exception(Marshal.GetHRForException(e)); } } internal void Close() { if( perfDataKey != null) perfDataKey.Close(); perfDataKey = null; } // Win32 RegQueryValueEx for perf data could deadlock (for a Mutex) up to 2mins in some // scenarios before they detect it and exit gracefully. In the mean time, ERROR_BUSY, // ERROR_NOT_READY etc can be seen by other concurrent calls (which is the reason for the // wait loop and switch case below). We want to wait most certainly more than a 2min window. // The curent wait time of up to 10mins takes care of the known stress deadlock issues. In most // cases we wouldn't wait for more than 2mins anyways but in worst cases how much ever time // we wait may not be sufficient if the Win32 code keeps running into this deadlock again // and again. A condition very rare but possible in theory. We would get back to the user // in this case with InvalidOperationException after the wait time expires. internal byte[] GetData(string item) { int waitRetries = 17; //2^16*10ms == approximately 10mins int waitSleep = 0; byte[] data = null; int error = 0; // no need to revert here since we'll fall off the end of the method new RegistryPermission(PermissionState.Unrestricted).Assert(); while (waitRetries > 0) { try { data = (byte[]) perfDataKey.GetValue(item); return data; } catch (IOException e) { error = Marshal.GetHRForException(e); switch (error) { case NativeMethods.RPC_S_CALL_FAILED: case NativeMethods.ERROR_INVALID_HANDLE: case NativeMethods.RPC_S_SERVER_UNAVAILABLE: Init(); goto case NativeMethods.WAIT_TIMEOUT; case NativeMethods.WAIT_TIMEOUT: case NativeMethods.ERROR_NOT_READY: case NativeMethods.ERROR_LOCK_FAILED: case NativeMethods.ERROR_BUSY: --waitRetries; if (waitSleep == 0) { waitSleep = 10; } else { System.Threading.Thread.Sleep(waitSleep); waitSleep *= 2; } break; default: throw SharedUtils.CreateSafeWin32Exception(error); } } catch (InvalidCastException e) { throw new InvalidOperationException(SR.GetString(SR.CounterDataCorrupt, perfDataKey.ToString()), e); } } throw SharedUtils.CreateSafeWin32Exception(error); } } internal class CategoryEntry { internal int NameIndex; internal int HelpIndex; internal int[] CounterIndexes; internal int[] HelpIndexes; internal CategoryEntry(NativeMethods.PERF_OBJECT_TYPE perfObject) { this.NameIndex = perfObject.ObjectNameTitleIndex; this.HelpIndex = perfObject.ObjectHelpTitleIndex; this.CounterIndexes = new int[perfObject.NumCounters]; this.HelpIndexes = new int[perfObject.NumCounters]; } } internal class CategorySample { internal readonly long SystemFrequency; internal readonly long TimeStamp; internal readonly long TimeStamp100nSec; internal readonly long CounterFrequency; internal readonly long CounterTimeStamp; internal Hashtable CounterTable; internal Hashtable InstanceNameTable; internal bool IsMultiInstance; private CategoryEntry entry; private PerformanceCounterLib library; internal unsafe CategorySample(byte[] data, CategoryEntry entry, PerformanceCounterLib library) { this.entry = entry; this.library = library; int categoryIndex = entry.NameIndex; NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK(); fixed (byte* dataPtr = data) { IntPtr dataRef = new IntPtr((void*) dataPtr); Marshal.PtrToStructure(dataRef, dataBlock); this.SystemFrequency = dataBlock.PerfFreq; this.TimeStamp = dataBlock.PerfTime; this.TimeStamp100nSec = dataBlock.PerfTime100nSec; dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength); int numPerfObjects = dataBlock.NumObjectTypes; if (numPerfObjects == 0) { this.CounterTable = new Hashtable(); this.InstanceNameTable = new Hashtable(StringComparer.OrdinalIgnoreCase); return; } //Need to find the right category, GetPerformanceData might return //several of them. NativeMethods.PERF_OBJECT_TYPE perfObject = null; bool foundCategory = false; for (int index = 0; index < numPerfObjects; index++) { perfObject = new NativeMethods.PERF_OBJECT_TYPE(); Marshal.PtrToStructure(dataRef, perfObject); if (perfObject.ObjectNameTitleIndex == categoryIndex) { foundCategory = true; break; } dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength); } if (!foundCategory) throw new InvalidOperationException(SR.GetString(SR.CantReadCategoryIndex, categoryIndex.ToString(CultureInfo.CurrentCulture))); this.CounterFrequency = perfObject.PerfFreq; this.CounterTimeStamp = perfObject.PerfTime; int counterNumber = perfObject.NumCounters; int instanceNumber = perfObject.NumInstances; if (instanceNumber == -1) IsMultiInstance = false; else IsMultiInstance = true; // Move pointer forward to end of PERF_OBJECT_TYPE dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength); CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; this.CounterTable = new Hashtable(counterNumber); for (int index = 0; index < samples.Length; ++ index) { NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); Marshal.PtrToStructure(dataRef, perfCounter); samples[index] = new CounterDefinitionSample(perfCounter, this, instanceNumber); dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength); int currentSampleType = samples[index].CounterType; if (!PerformanceCounterLib.IsBaseCounter(currentSampleType)) { // We'll put only non-base counters in the table. if (currentSampleType != NativeMethods.PERF_COUNTER_NODATA) this.CounterTable[samples[index].NameIndex] = samples[index]; } else { // it's a base counter, try to hook it up to the main counter. Debug.Assert(index > 0, "Index > 0 because base counters should never be at index 0"); if (index > 0) samples[index-1].BaseCounterDefinitionSample = samples[index]; } } // now set up the InstanceNameTable. if (!IsMultiInstance) { this.InstanceNameTable = new Hashtable(1, StringComparer.OrdinalIgnoreCase); this.InstanceNameTable[PerformanceCounterLib.SingleInstanceName] = 0; for (int index = 0; index < samples.Length; ++ index) { samples[index].SetInstanceValue(0, dataRef); } } else { string[] parentInstanceNames = null; this.InstanceNameTable = new Hashtable(instanceNumber, StringComparer.OrdinalIgnoreCase); for (int i = 0; i < instanceNumber; i++) { NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION(); Marshal.PtrToStructure(dataRef, perfInstance); if (perfInstance.ParentObjectTitleIndex > 0 && parentInstanceNames == null) parentInstanceNames = GetInstanceNamesFromIndex(perfInstance.ParentObjectTitleIndex); string instanceName; if (parentInstanceNames != null && perfInstance.ParentObjectInstance >= 0 && perfInstance.ParentObjectInstance < parentInstanceNames.Length - 1) instanceName = parentInstanceNames[perfInstance.ParentObjectInstance] + "/" + Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset)); else instanceName = Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset)); //In some cases instance names are not unique (Process), same as perfmon //generate a unique name. string newInstanceName = instanceName; int newInstanceNumber = 1; while (true) { if (!this.InstanceNameTable.ContainsKey(newInstanceName)) { this.InstanceNameTable[newInstanceName] = i; break; } else { newInstanceName = instanceName + "#" + newInstanceNumber.ToString(CultureInfo.InvariantCulture); ++ newInstanceNumber; } } dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength); for (int index = 0; index < samples.Length; ++ index) samples[index].SetInstanceValue(i, dataRef); dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef)); } } } } internal unsafe string[] GetInstanceNamesFromIndex(int categoryIndex) { byte[] data = library.GetPerformanceData(categoryIndex.ToString(CultureInfo.InvariantCulture)); fixed (byte* dataPtr = data) { IntPtr dataRef = new IntPtr((void*) dataPtr); NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK(); Marshal.PtrToStructure(dataRef, dataBlock); dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength); int numPerfObjects = dataBlock.NumObjectTypes; NativeMethods.PERF_OBJECT_TYPE perfObject = null; bool foundCategory = false; for (int index = 0; index < numPerfObjects; index++) { perfObject = new NativeMethods.PERF_OBJECT_TYPE(); Marshal.PtrToStructure(dataRef, perfObject); if (perfObject.ObjectNameTitleIndex == categoryIndex) { foundCategory = true; break; } dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength); } if (!foundCategory) return new string[0]; int counterNumber = perfObject.NumCounters; int instanceNumber = perfObject.NumInstances; dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength); if (instanceNumber == -1) return new string[0]; CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; for (int index = 0; index < samples.Length; ++ index) { NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); Marshal.PtrToStructure(dataRef, perfCounter); dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength); } string[] instanceNames = new string[instanceNumber]; for (int i = 0; i < instanceNumber; i++) { NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION(); Marshal.PtrToStructure(dataRef, perfInstance); instanceNames[i] = Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset)); dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength); dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef)); } return instanceNames; } } internal CounterDefinitionSample GetCounterDefinitionSample(string counter) { for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { int counterIndex = entry.CounterIndexes[index]; string counterName = (string)this.library.NameTable[counterIndex]; if (counterName != null) { if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) { CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex]; if (sample == null) { //This is a base counter and has not been added to the table foreach (CounterDefinitionSample multiSample in this.CounterTable.Values) { if (multiSample.BaseCounterDefinitionSample != null && multiSample.BaseCounterDefinitionSample.NameIndex == counterIndex) return multiSample.BaseCounterDefinitionSample; } throw new InvalidOperationException(SR.GetString(SR.CounterLayout)); } return sample; } } } throw new InvalidOperationException(SR.GetString(SR.CantReadCounter, counter)); } internal InstanceDataCollectionCollection ReadCategory() { #pragma warning disable 618 InstanceDataCollectionCollection data = new InstanceDataCollectionCollection(); #pragma warning restore 618 for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { int counterIndex = entry.CounterIndexes[index]; string name = (string)library.NameTable[counterIndex]; if (name != null && name != String.Empty) { CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex]; if (sample != null) //If the current index refers to a counter base, //the sample will be null data.Add(name, sample.ReadInstanceData(name)); } } return data; } } internal class CounterDefinitionSample { internal readonly int NameIndex; internal readonly int CounterType; internal CounterDefinitionSample BaseCounterDefinitionSample; private readonly int size; private readonly int offset; private long[] instanceValues; private CategorySample categorySample; internal CounterDefinitionSample(NativeMethods.PERF_COUNTER_DEFINITION perfCounter, CategorySample categorySample, int instanceNumber) { this.NameIndex = perfCounter.CounterNameTitleIndex; this.CounterType = perfCounter.CounterType; this.offset = perfCounter.CounterOffset; this.size = perfCounter.CounterSize; if (instanceNumber == -1) { this.instanceValues = new long[1]; } else this.instanceValues = new long[instanceNumber]; this.categorySample = categorySample; } private long ReadValue(IntPtr pointer) { if (this.size == 4) { return (long)(uint)Marshal.ReadInt32((IntPtr)((long)pointer + this.offset)); } else if (this.size == 8) { return (long)Marshal.ReadInt64((IntPtr)((long)pointer + this.offset)); } return -1; } internal CounterSample GetInstanceValue(string instanceName) { if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) { // Our native dll truncates instance names to 128 characters. If we can't find the instance // with the full name, try truncating to 128 characters. if (instanceName.Length > SharedPerformanceCounter.InstanceNameMaxLength) instanceName = instanceName.Substring(0, SharedPerformanceCounter.InstanceNameMaxLength); if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) throw new InvalidOperationException(SR.GetString(SR.CantReadInstance, instanceName)); } int index = (int)categorySample.InstanceNameTable[instanceName]; long rawValue = this.instanceValues[index]; long baseValue = 0; if (this.BaseCounterDefinitionSample != null) { CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample; int baseIndex = (int)baseCategorySample.InstanceNameTable[instanceName]; baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex]; } return new CounterSample(rawValue, baseValue, categorySample.CounterFrequency, categorySample.SystemFrequency, categorySample.TimeStamp, categorySample.TimeStamp100nSec, (PerformanceCounterType)this.CounterType, categorySample.CounterTimeStamp); } internal InstanceDataCollection ReadInstanceData(string counterName) { #pragma warning disable 618 InstanceDataCollection data = new InstanceDataCollection(counterName); #pragma warning restore 618 string[] keys = new string[categorySample.InstanceNameTable.Count]; categorySample.InstanceNameTable.Keys.CopyTo(keys, 0); int[] indexes = new int[categorySample.InstanceNameTable.Count]; categorySample.InstanceNameTable.Values.CopyTo(indexes, 0); for (int index = 0; index < keys.Length; ++ index) { long baseValue = 0; if (this.BaseCounterDefinitionSample != null) { CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample; int baseIndex = (int)baseCategorySample.InstanceNameTable[keys[index]]; baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex]; } CounterSample sample = new CounterSample(this.instanceValues[indexes[index]], baseValue, categorySample.CounterFrequency, categorySample.SystemFrequency, categorySample.TimeStamp, categorySample.TimeStamp100nSec, (PerformanceCounterType)this.CounterType, categorySample.CounterTimeStamp); data.Add(keys[index], new InstanceData(keys[index], sample)); } return data; } internal CounterSample GetSingleValue() { long rawValue = this.instanceValues[0]; long baseValue = 0; if (this.BaseCounterDefinitionSample != null) baseValue = this.BaseCounterDefinitionSample.instanceValues[0]; return new CounterSample(rawValue, baseValue, categorySample.CounterFrequency, categorySample.SystemFrequency, categorySample.TimeStamp, categorySample.TimeStamp100nSec, (PerformanceCounterType)this.CounterType, categorySample.CounterTimeStamp); } internal void SetInstanceValue(int index, IntPtr dataRef) { long rawValue = ReadValue(dataRef); this.instanceValues[index] = rawValue; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- relpropertyhelper.cs
- SqlDesignerDataSourceView.cs
- StringUtil.cs
- FileDialog.cs
- PackageStore.cs
- ContextMenu.cs
- BaseResourcesBuildProvider.cs
- DispatcherHooks.cs
- UpdateException.cs
- UnmanagedHandle.cs
- contentDescriptor.cs
- CryptoApi.cs
- SchemaElement.cs
- MarkupObject.cs
- CallId.cs
- ManipulationInertiaStartingEventArgs.cs
- contentDescriptor.cs
- ScrollData.cs
- DispatcherObject.cs
- PerformanceCounter.cs
- TextLine.cs
- CodeAssignStatement.cs
- Errors.cs
- Triplet.cs
- SearchExpression.cs
- StyleSelector.cs
- WsatConfiguration.cs
- TextFormatter.cs
- StringReader.cs
- InputScope.cs
- ExpandedWrapper.cs
- SelectedGridItemChangedEvent.cs
- DataSourceCache.cs
- Table.cs
- ImageAttributes.cs
- BrowserDefinitionCollection.cs
- ToolStripPanelCell.cs
- OleDbSchemaGuid.cs
- WindowsServiceCredential.cs
- StylusShape.cs
- AnimationException.cs
- EntityContainerAssociationSet.cs
- Cursors.cs
- SharedStream.cs
- CompilationUnit.cs
- SystemInfo.cs
- PackWebRequestFactory.cs
- Style.cs
- ProxyWebPart.cs
- GZipDecoder.cs
- CalendarDay.cs
- webeventbuffer.cs
- SynchronizationLockException.cs
- InitiatorSessionSymmetricMessageSecurityProtocol.cs
- LocatorBase.cs
- ClientTargetCollection.cs
- ScriptResourceAttribute.cs
- SerializerWriterEventHandlers.cs
- DocumentOrderComparer.cs
- FrameworkElementFactoryMarkupObject.cs
- UrlMappingsModule.cs
- LocalizableAttribute.cs
- DataTablePropertyDescriptor.cs
- OracleParameterCollection.cs
- EventLogHandle.cs
- ActivityValidator.cs
- BufferModeSettings.cs
- SqlInternalConnection.cs
- RegexCapture.cs
- XmlSchemaNotation.cs
- BamlResourceDeserializer.cs
- DataBoundControlParameterTarget.cs
- EntityTypeEmitter.cs
- ObjectHandle.cs
- Pkcs9Attribute.cs
- ActivityPropertyReference.cs
- ToolStripProgressBar.cs
- OdbcConnectionPoolProviderInfo.cs
- LayoutTable.cs
- VisualSerializer.cs
- GetResponse.cs
- BooleanConverter.cs
- EntityDataReader.cs
- XmlKeywords.cs
- CustomAttributeSerializer.cs
- ServicePoint.cs
- XamlNamespaceHelper.cs
- XmlElementList.cs
- UniqueIdentifierService.cs
- RequiredAttributeAttribute.cs
- RenderCapability.cs
- CachedRequestParams.cs
- RegexInterpreter.cs
- BitmapInitialize.cs
- PointF.cs
- Interlocked.cs
- Root.cs
- ModelPerspective.cs
- DateTimeFormat.cs
- DataFieldCollectionEditor.cs