Implement performance-counter cmdlets for Windows CoreCLR

Code changes per PR code review - 3
This commit is contained in:
Jeff Bienstadt
2016-12-13 11:00:22 -08:00
committed by Mike Richmond
parent e07e1b596d
commit da04f2b1a8
12 changed files with 754 additions and 93 deletions
@@ -1,16 +1,22 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Resources;
using System.Reflection;
#if CORECLR
using System.ComponentModel;
#else
using System.Threading;
#endif
namespace Microsoft.PowerShell.Commands.Diagnostics.Common
{
internal static class CommonUtilities
{
#if !CORECLR
//
// StringArrayToString helper converts a string array into a comma-separated string.
// Note this has only limited use, individual strings cannot have commas.
@@ -29,6 +35,34 @@ namespace Microsoft.PowerShell.Commands.Diagnostics.Common
return ret;
}
#if CORECLR
private const string LibraryLoadDllName = "api-ms-win-core-libraryloader-l1-2-0.dll";
private const string LocalizationDllName = "api-ms-win-core-localization-l1-2-1.dll";
private const string SysInfoDllName = "api-ms-win-core-sysinfo-l1-2-1.dll";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct OSVERSIONINFOEX
{
public int OSVersionInfoSize;
public int MajorVersion;
public int MinorVersion;
public int BuildNumber;
public int PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string CSDVersion;
public ushort ServicePackMajor;
public ushort ServicePackMinor;
public short SuiteMask;
public byte ProductType;
public byte Reserved;
}
[DllImport(SysInfoDllName, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool GetVersionEx(ref OSVERSIONINFOEX osVerEx);
#else
private const string LibraryLoadDllName = "kernel32.dll";
private const string LocalizationDllName = "kernel32.dll";
#endif
private const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
private const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
@@ -36,25 +70,25 @@ namespace Microsoft.PowerShell.Commands.Diagnostics.Common
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private const uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(LocalizationDllName, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
uint dwMessageId, uint dwLanguageId,
[MarshalAs(UnmanagedType.LPWStr)]
StringBuilder lpBuffer,
uint nSize, IntPtr Arguments);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(LibraryLoadDllName, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibraryEx(
[MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
IntPtr hFile,
uint dwFlags
);
[DllImport("kernel32.dll")]
[DllImport(LibraryLoadDllName)]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll", EntryPoint = "GetUserDefaultLangID", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[DllImport(LocalizationDllName, EntryPoint = "GetUserDefaultLangID", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
private static extern ushort GetUserDefaultLangID();
@@ -111,7 +145,6 @@ namespace Microsoft.PowerShell.Commands.Diagnostics.Common
}
return formatError;
}
#endif
public static ResourceManager GetResourceManager()
{
@@ -0,0 +1,252 @@
#if CORECLR
using System.ComponentModel;
using Microsoft.PowerShell.CoreClr.Stubs;
namespace System.Diagnostics
{
/// <summary>
/// Indicates whether the performance counter category can have multiple instances.
/// </summary>
/// <filterpriority>1</filterpriority>
public enum PerformanceCounterCategoryType
{
/// <summary>
/// The instance functionality for the performance counter category is unknown.
/// </summary>
Unknown = -1,
/// <summary>
/// The performance counter category can have only a single instance.
/// </summary>
SingleInstance,
/// <summary>
/// The performance counter category can have multiple instances.
/// </summary>
MultiInstance
}
/// <summary>
/// Specifies the formula used to calculate the <see cref="M:System.Diagnostics.PerformanceCounter.NextValue" />
/// method for a <see cref="T:System.Diagnostics.PerformanceCounter" /> instance.
/// </summary>
/// <filterpriority>2</filterpriority>
public enum PerformanceCounterType
{
/// <summary>
/// An instantaneous counter that shows the most recently observed value.
/// Used, for example, to maintain a simple count of items or operations.
/// </summary>
NumberOfItems32 = 65536,
/// <summary>
/// An instantaneous counter that shows the most recently observed value.
/// Used, for example, to maintain a simple count of a very large number
/// of items or operations. It is the same as NumberOfItems32 except that
/// it uses larger fields to accommodate larger values.
/// </summary>
NumberOfItems64 = 65792,
/// <summary>
/// An instantaneous counter that shows the most recently observed value
/// in hexadecimal format. Used, for example, to maintain a simple count
/// of items or operations.</summary>
NumberOfItemsHEX32 = 0,
/// <summary>
/// An instantaneous counter that shows the most recently observed value.
/// Used, for example, to maintain a simple count of a very large number
/// of items or operations. It is the same as NumberOfItemsHEX32 except
/// that it uses larger fields to accommodate larger values.
/// </summary>
NumberOfItemsHEX64 = 256,
/// <summary>
/// A difference counter that shows the average number of operations completed
/// during each second of the sample interval. Counters of this type measure
/// time in ticks of the system clock.</summary>
RateOfCountsPerSecond32 = 272696320,
/// <summary>
/// A difference counter that shows the average number of operations completed
/// during each second of the sample interval. Counters of this type measure
/// time in ticks of the system clock. This counter type is the same as the
/// RateOfCountsPerSecond32 type, but it uses larger fields to accommodate
/// larger values to track a high-volume number of items or operations per
/// second, such as a byte-transmission rate.
/// </summary>
RateOfCountsPerSecond64 = 272696576,
/// <summary>
/// An average counter designed to monitor the average length of a queue
/// to a resource over time. It shows the difference between the queue
/// lengths observed during the last two sample intervals divided by the
/// duration of the interval. This type of counter is typically used to
/// track the number of items that are queued or waiting.
/// </summary>
CountPerTimeInterval32 = 4523008,
/// <summary>
/// An average counter that monitors the average length of a queue to a
/// resource over time. Counters of this type display the difference
/// between the queue lengths observed during the last two sample intervals,
/// divided by the duration of the interval. This counter type is the same
/// as CountPerTimeInterval32 except that it uses larger fields to
/// accommodate larger values. This type of counter is typically used
/// to track a high-volume or very large number of items that are queued or waiting.
/// </summary>
CountPerTimeInterval64 = 4523264,
/// <summary>
/// An instantaneous percentage counter that shows the ratio of a subset
/// to its set as a percentage. For example, it compares the number of bytes
/// in use on a disk to the total number of bytes on the disk.
/// Counters of this type display the current percentage only, not an average
/// over time.
/// </summary>
RawFraction = 537003008,
/// <summary>
/// A base counter that stores the denominator of a counter that presents a
/// general arithmetic fraction. Check that this value is greater than zero
/// before using it as the denominator in a RawFraction value calculation.
/// </summary>
RawBase = 1073939459,
/// <summary>
/// An average counter that measures the time it takes, on average, to
/// complete a process or operation. Counters of this type display a
/// ratio of the total elapsed time of the sample interval to the number
/// of processes or operations completed during that time. This counter
/// type measures time in ticks of the system clock.
/// </summary>
AverageTimer32 = 805438464,
/// <summary>
/// A base counter that is used in the calculation of time or count averages,
/// such as AverageTimer32 and AverageCount64. Stores the denominator for
/// calculating a counter to present "time per operation" or "count per operation".
/// </summary>
AverageBase = 1073939458,
/// <summary>
/// An average counter that shows how many items are processed, on average,
/// during an operation. Counters of this type display a ratio of the items
/// processed to the number of operations completed. The ratio is calculated
/// by comparing the number of items processed during the last interval to
/// the number of operations completed during the last interval.
/// </summary>
AverageCount64 = 1073874176,
/// <summary>
/// A percentage counter that shows the average ratio of hits to all
/// operations during the last two sample intervals.
/// </summary>
SampleFraction = 549585920,
/// <summary>
/// An average counter that shows the average number of operations completed
/// in one second. When a counter of this type samples the data, each sampling
/// interrupt returns one or zero. The counter data is the number of ones that
/// were sampled. It measures time in units of ticks of the system performance timer.
/// </summary>
SampleCounter = 4260864,
/// <summary>
/// A base counter that stores the number of sampling interrupts taken
/// and is used as a denominator in the sampling fraction. The sampling
/// fraction is the number of samples that were 1 (or true) for a sample
/// interrupt. Check that this value is greater than zero before using
/// it as the denominator in a calculation of SampleFraction.
/// </summary>
SampleBase = 1073939457,
/// <summary>
/// A percentage counter that shows the average time that a component is
/// active as a percentage of the total sample time.
/// </summary>
CounterTimer = 541132032,
/// <summary>
/// A percentage counter that displays the average percentage of active
/// time observed during sample interval. The value of these counters is
/// calculated by monitoring the percentage of time that the service was
/// inactive and then subtracting that value from 100 percent.
/// </summary>
CounterTimerInverse = 557909248,
/// <summary>A percentage counter that shows the active time of a component
/// as a percentage of the total elapsed time of the sample interval.
/// It measures time in units of 100 nanoseconds (ns). Counters of this
/// type are designed to measure the activity of one component at a time.
/// </summary>
Timer100Ns = 542180608,
/// <summary>
/// A percentage counter that shows the average percentage of active time
/// observed during the sample interval.
/// </summary>
Timer100NsInverse = 558957824,
/// <summary>
/// A difference timer that shows the total time between when the component
/// or process started and the time when this value is calculated.
/// </summary>
ElapsedTime = 807666944,
/// <summary>
/// A percentage counter that displays the active time of one or more
/// components as a percentage of the total time of the sample interval.
/// Because the numerator records the active time of components operating
/// simultaneously, the resulting percentage can exceed 100 percent.
/// </summary>
CounterMultiTimer = 574686464,
/// <summary>
/// A percentage counter that shows the active time of one or more components
/// as a percentage of the total time of the sample interval. It derives
/// the active time by measuring the time that the components were not
/// active and subtracting the result from 100 percent by the number of
/// objects monitored.
/// </summary>
CounterMultiTimerInverse = 591463680,
/// <summary>
/// A percentage counter that shows the active time of one or more components
/// as a percentage of the total time of the sample interval. It measures
/// time in 100 nanosecond (ns) units.</summary>
CounterMultiTimer100Ns = 575735040,
/// <summary>
/// A percentage counter that shows the active time of one or more components
/// as a percentage of the total time of the sample interval. Counters of
/// this type measure time in 100 nanosecond (ns) units. They derive the
/// active time by measuring the time that the components were not active
/// and subtracting the result from multiplying 100 percent by the number
/// of objects monitored.</summary>
CounterMultiTimer100NsInverse = 592512256,
/// <summary>
/// A base counter that indicates the number of items sampled. It is used
/// as the denominator in the calculations to get an average among the
/// items sampled when taking timings of multiple, but similar items.
/// Used with CounterMultiTimer, CounterMultiTimerInverse, CounterMultiTimer100Ns,
/// and CounterMultiTimer100NsInverse.</summary>
CounterMultiBase = 1107494144,
/// <summary>
/// A difference counter that shows the change in the measured attribute
/// between the two most recent sample intervals.
/// </summary>
CounterDelta32 = 4195328,
/// <summary>
/// A difference counter that shows the change in the measured attribute
/// between the two most recent sample intervals. It is the same as the
/// CounterDelta32 counter type except that is uses larger fields to
/// accomodate larger values.</summary>
CounterDelta64 = 4195584
}
}
#endif
@@ -1,6 +1,6 @@
//
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
//
using System;
@@ -30,7 +30,7 @@ using Microsoft.PowerShell.Commands.Diagnostics.Common;
namespace Microsoft.PowerShell.Commands
{
///
///
/// Class that implements the Get-Counter cmdlet.
///
[Cmdlet(VerbsData.Export, "Counter", DefaultParameterSetName = "ExportCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=138337")]
@@ -38,7 +38,7 @@ namespace Microsoft.PowerShell.Commands
{
//
// Path parameter
//
//
[Parameter(
Mandatory = true,
Position = 0,
@@ -58,7 +58,7 @@ namespace Microsoft.PowerShell.Commands
//
// Format parameter.
// Valid strings are "blg", "csv", "tsv" (case-insensitive).
//
//
[Parameter(
Mandatory = false,
ValueFromPipeline = false,
@@ -77,7 +77,7 @@ namespace Microsoft.PowerShell.Commands
//
// MaxSize parameter
// Maximum output file size, in megabytes.
//
//
[Parameter(
HelpMessageBaseName = "GetEventResources")]
public UInt32 MaxSize
@@ -90,7 +90,7 @@ namespace Microsoft.PowerShell.Commands
//
// InputObject parameter
//
//
[Parameter(
Mandatory = true,
ValueFromPipeline = true,
@@ -152,23 +152,30 @@ namespace Microsoft.PowerShell.Commands
{
_resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();
#if CORECLR
// PowerShell Core requires at least Windows 7,
// so no version test is needed
_pdhHelper = new PdhHelper(false);
#else
//
// Determine the OS version: this cmdlet requires Windows 7
// because it uses new Pdh functionality.
//
if (System.Environment.OSVersion.Version.Major < 6 ||
(System.Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor < 1))
Version osVersion = System.Environment.OSVersion.Version;
if (osVersion.Major < 6 ||
(osVersion.Major == 6 && osVersion.Minor < 1))
{
string msg = _resourceMgr.GetString("ExportCtrWin7Required");
Exception exc = new Exception(msg);
ThrowTerminatingError(new ErrorRecord(exc, "ExportCtrWin7Required", ErrorCategory.NotImplemented, null));
}
_pdhHelper = new PdhHelper(System.Environment.OSVersion.Version.Major < 6);
_pdhHelper = new PdhHelper(osVersion.Major < 6);
#endif
//
// Validate the Format and CounterSamples arguments
//
//
ValidateFormat();
if (Circular.IsPresent && _maxSize == 0)
@@ -200,9 +207,9 @@ namespace Microsoft.PowerShell.Commands
}
///
///
/// Handle Control-C
///
///
protected override void StopProcessing()
{
_stopping = true;
@@ -214,7 +221,7 @@ namespace Microsoft.PowerShell.Commands
// This is the main entry point for the cmdlet.
// When counter data comes from the pipeline, this gets invoked for each pipelined object.
// When it's passed in as an argument, ProcessRecord() is called once for the entire _counterSampleSets array.
//
//
protected override void ProcessRecord()
{
Debug.Assert(_counterSampleSets.Length != 0 && _counterSampleSets[0] != null);
@@ -225,7 +232,7 @@ namespace Microsoft.PowerShell.Commands
if (!_queryInitialized)
{
if (_format.ToLower(CultureInfo.InvariantCulture).Equals("blg"))
if (_format.ToLowerInvariant().Equals("blg"))
{
res = _pdhHelper.AddRelogCounters(_counterSampleSets[0]);
}
@@ -303,7 +310,7 @@ namespace Microsoft.PowerShell.Commands
//
private void ValidateFormat()
{
switch (_format.ToLower(CultureInfo.InvariantCulture))
switch (_format.ToLowerInvariant())
{
case "blg":
_outputFormat = PdhLogFileType.PDH_LOG_TYPE_BINARY;
@@ -1,6 +1,6 @@
//
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
//
using System;
@@ -30,15 +30,15 @@ using Microsoft.PowerShell.Commands.Diagnostics.Common;
namespace Microsoft.PowerShell.Commands
{
///
///
/// Class that implements the Get-Counter cmdlet.
///
///
[Cmdlet(VerbsCommon.Get, "Counter", DefaultParameterSetName = "GetCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=138335")]
public sealed class GetCounterCommand : PSCmdlet
{
//
// ListSet parameter
//
//
[Parameter(
Position = 0,
Mandatory = true,
@@ -62,7 +62,7 @@ namespace Microsoft.PowerShell.Commands
//
// Counter parameter
//
//
[Parameter(
Position = 0,
ParameterSetName = "GetCounterSet",
@@ -175,8 +175,8 @@ namespace Microsoft.PowerShell.Commands
private EventWaitHandle _cancelEventArrived = new EventWaitHandle(false, EventResetMode.ManualReset);
// Culture identifier(s)
private const int FrenchCultureId = 0x040C;
// Culture identifier(s)
private const string FrenchCultureId = "fr-FR";
// The localized Pdh resource strings might use Unicode characters that are different from
// what the user can type with the keyboard to represent a special character.
//
@@ -184,8 +184,8 @@ namespace Microsoft.PowerShell.Commands
// in the resource strings.
//
// With this dictionary, we can add special mapping if we find other special cases in the future.
private readonly Dictionary<int, List<Tuple<char, char>>> _cultureAndSpecialCharacterMap =
new Dictionary<int, List<Tuple<char, char>>>()
private readonly Dictionary<string, List<Tuple<char, char>>> _cultureAndSpecialCharacterMap =
new Dictionary<string, List<Tuple<char, char>>>()
{
{
FrenchCultureId, new List<Tuple<char, char>>()
@@ -207,7 +207,14 @@ namespace Microsoft.PowerShell.Commands
{
_resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();
#if CORECLR
// PowerShell Core requires at least Windows 7,
// so no version test is needed
_pdhHelper = new PdhHelper(false);
#else
_pdhHelper = new PdhHelper(System.Environment.OSVersion.Version.Major < 6);
#endif
uint res = _pdhHelper.ConnectToDataSource();
if (res != 0)
{
@@ -237,9 +244,9 @@ namespace Microsoft.PowerShell.Commands
}
//
//
// Handle Control-C
//
//
protected override void StopProcessing()
{
_cancelEventArrived.Set();
@@ -249,7 +256,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessRecord() override.
// This is the main entry point for the cmdlet.
//
//
protected override void ProcessRecord()
{
try
@@ -286,7 +293,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessListSet() does the work to process ListSet parameter set.
//
//
private void ProcessListSet()
{
if (_computerName.Length == 0)
@@ -317,11 +324,11 @@ namespace Microsoft.PowerShell.Commands
return;
}
CultureInfo culture = Thread.CurrentThread.CurrentUICulture;
CultureInfo culture = GetCurrentCulture();
List<Tuple<char, char>> characterReplacementList = null;
StringCollection validPaths = new StringCollection();
_cultureAndSpecialCharacterMap.TryGetValue(culture.LCID, out characterReplacementList);
_cultureAndSpecialCharacterMap.TryGetValue(culture.Name, out characterReplacementList);
foreach (string pattern in _listSet)
{
@@ -417,23 +424,23 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessGetCounter()
// Does the work to process GetCounterSet parameter set.
//
//
private void ProcessGetCounter()
{
// 1. Combine machine names with paths, if needed, to construct full paths
// 2. Translate default paths into current locale
// 3. Expand wildcards and validate the paths and write errors for any invalid paths
// 4. OpenQuery/ AddCounters
// 5. Skip the first reading
// 5. Skip the first reading
CultureInfo culture = Thread.CurrentThread.CurrentUICulture;
CultureInfo culture = GetCurrentCulture();
List<Tuple<char, char>> characterReplacementList = null;
List<string> paths = CombineMachinesAndCounterPaths();
uint res = 0;
if (!_defaultCounters)
{
_cultureAndSpecialCharacterMap.TryGetValue(culture.LCID, out characterReplacementList);
_cultureAndSpecialCharacterMap.TryGetValue(culture.Name, out characterReplacementList);
}
@@ -552,7 +559,12 @@ namespace Microsoft.PowerShell.Commands
break;
}
#if CORECLR
// CoreCLR has no overload of WaitOne with (interval, exitContext)
bool cancelled = _cancelEventArrived.WaitOne((int)_sampleInterval * 1000);
#else
bool cancelled = _cancelEventArrived.WaitOne((int)_sampleInterval * 1000, true);
#endif
if (cancelled)
{
break;
@@ -584,7 +596,7 @@ namespace Microsoft.PowerShell.Commands
// CombineMachinesAndCounterPaths() helper.
// For paths that do not contain machine names, creates a path for each machine in machineNames.
// Paths already containing a machine name will be preserved.
//
//
private List<string> CombineMachinesAndCounterPaths()
{
List<string> retColl = new List<string>();
@@ -622,9 +634,9 @@ namespace Microsoft.PowerShell.Commands
//
// WriteSampleSetObject() helper.
// In addition to writing the PerformanceCounterSampleSet object,
// In addition to writing the PerformanceCounterSampleSet object,
// it writes a single error if one of the samples has an invalid (non-zero) status.
//
//
private void WriteSampleSetObject(PerformanceCounterSampleSet set)
{
foreach (PerformanceCounterSample sample in set.CounterSamples)
@@ -639,6 +651,15 @@ namespace Microsoft.PowerShell.Commands
}
WriteObject(set);
}
private static CultureInfo GetCurrentCulture()
{
#if CORECLR
return CultureInfo.CurrentCulture;
#else
return Thread.CurrentThread.CurrentUICulture;
#endif
}
}
}
@@ -1,6 +1,6 @@
//
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
//
using System;
@@ -30,7 +30,7 @@ using Microsoft.PowerShell.Commands.Diagnostics.Common;
namespace Microsoft.PowerShell.Commands
{
///
///
/// Class that implements the Get-Counter cmdlet.
///
[Cmdlet(VerbsData.Import, "Counter", DefaultParameterSetName = "GetCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=138338")]
@@ -38,7 +38,7 @@ namespace Microsoft.PowerShell.Commands
{
//
// Path parameter
//
//
[Parameter(
Position = 0,
Mandatory = true,
@@ -65,7 +65,7 @@ namespace Microsoft.PowerShell.Commands
//
// ListSet parameter
//
//
[Parameter(
Mandatory = true,
ParameterSetName = "ListSetSet",
@@ -119,7 +119,7 @@ namespace Microsoft.PowerShell.Commands
//
// Counter parameter
//
//
[Parameter(
Mandatory = false,
ParameterSetName = "GetCounterSet",
@@ -189,7 +189,13 @@ namespace Microsoft.PowerShell.Commands
protected override void BeginProcessing()
{
_resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();
#if CORECLR
// PowerShell Core requires at least Windows 7,
// so no version test is needed
_pdhHelper = new PdhHelper(false);
#else
_pdhHelper = new PdhHelper(System.Environment.OSVersion.Version.Major < 6);
#endif
}
//
@@ -199,7 +205,7 @@ namespace Microsoft.PowerShell.Commands
{
//
// Resolve and validate the Path argument: present for all parametersets.
//
//
if (!ResolveFilePaths())
{
return;
@@ -229,9 +235,9 @@ namespace Microsoft.PowerShell.Commands
}
//
//
// Handle Control-C
//
//
protected override void StopProcessing()
{
_stopping = true;
@@ -242,7 +248,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessRecord() override.
// This is the main entry point for the cmdlet.
//
//
protected override void ProcessRecord()
{
AccumulatePipelineFileNames();
@@ -251,7 +257,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessSummary().
// Does the work to process Summary parameter set.
//
//
private void ProcessSummary()
{
uint res = _pdhHelper.ConnectToDataSource(_resolvedPaths);
@@ -276,7 +282,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessListSet().
// Does the work to process ListSet parameter set.
//
//
private void ProcessListSet()
{
uint res = _pdhHelper.ConnectToDataSource(_resolvedPaths);
@@ -373,7 +379,7 @@ namespace Microsoft.PowerShell.Commands
//
// ProcessGetCounter()
// Does the work to process GetCounterSet parameter set.
//
//
private void ProcessGetCounter()
{
// Validate StartTime-EndTime, if present
@@ -556,7 +562,7 @@ namespace Microsoft.PowerShell.Commands
// Returns a string collection of resolved file paths.
// Writes non-terminating errors for invalid paths
// and returns an empty collection.
//
//
private bool ResolveFilePaths()
{
StringCollection retColl = new StringCollection();
@@ -607,7 +613,7 @@ namespace Microsoft.PowerShell.Commands
continue;
}
_resolvedPaths.Add(pi.ProviderPath.ToLower(CultureInfo.InvariantCulture));
_resolvedPaths.Add(pi.ProviderPath.ToLowerInvariant());
}
}
@@ -635,9 +641,9 @@ namespace Microsoft.PowerShell.Commands
//
// WriteSampleSetObject() helper.
// In addition to writing the PerformanceCounterSampleSet object,
// In addition to writing the PerformanceCounterSampleSet object,
// it writes a single error if one of the samples has an invalid (non-zero) status.
// The only exception is the first set, where we allow for the formatted value to be 0 -
// The only exception is the first set, where we allow for the formatted value to be 0 -
// this is expected for CSV and TSV files.
private void WriteSampleSetObject(PerformanceCounterSampleSet set, bool firstSet)
@@ -976,7 +976,7 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
// Marshal.PtrToStructure will allocate managed memory for the object,
// so the unmanaged ptr can be freed safely
//
pCounterPathElements = (PDH_COUNTER_PATH_ELEMENTS)Marshal.PtrToStructure(structPtr, typeof(PDH_COUNTER_PATH_ELEMENTS));
pCounterPathElements = Marshal.PtrToStructure<PDH_COUNTER_PATH_ELEMENTS>(structPtr);
}
}
finally
@@ -1011,12 +1011,12 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
}
// Check if the path is local and assert if not:
string machineNameMassaged = pathElts.MachineName.ToLower(CultureInfo.InvariantCulture);
string machineNameMassaged = pathElts.MachineName.ToLowerInvariant();
machineNameMassaged = machineNameMassaged.TrimStart('\\');
Debug.Assert(machineNameMassaged == System.Environment.MachineName.ToLower(CultureInfo.InvariantCulture));
Debug.Assert(machineNameMassaged == System.Environment.MachineName.ToLowerInvariant());
string lowerEngCtrName = pathElts.CounterName.ToLower(CultureInfo.InvariantCulture);
string lowerEngObjectName = pathElts.ObjectName.ToLower(CultureInfo.InvariantCulture);
string lowerEngCtrName = pathElts.CounterName.ToLowerInvariant();
string lowerEngObjectName = pathElts.ObjectName.ToLowerInvariant();
// Get the registry index
RegistryKey rootKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009");
@@ -1029,7 +1029,7 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
for (uint enumIndex = 1; enumIndex < regCounters.Length; enumIndex++)
{
string regString = regCounters[enumIndex];
if (regString.ToLower(CultureInfo.InvariantCulture) == lowerEngCtrName)
if (regString.ToLowerInvariant() == lowerEngCtrName)
{
try
{
@@ -1040,7 +1040,7 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
return (uint)PdhResults.PDH_INVALID_PATH;
}
}
else if (regString.ToLower(CultureInfo.InvariantCulture) == lowerEngObjectName)
else if (regString.ToLowerInvariant() == lowerEngObjectName)
{
try
{
@@ -1195,12 +1195,12 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
res = ParsePath(counterPath, ref pathElts);
if (res == 0 && pathElts.InstanceName != null)
{
chi.InstanceName = pathElts.InstanceName.ToLower(CultureInfo.InvariantCulture);
chi.InstanceName = pathElts.InstanceName.ToLowerInvariant();
}
if (!_consumerPathToHandleAndInstanceMap.ContainsKey(counterPath.ToLower(CultureInfo.InvariantCulture)))
if (!_consumerPathToHandleAndInstanceMap.ContainsKey(counterPath.ToLowerInvariant()))
{
_consumerPathToHandleAndInstanceMap.Add(counterPath.ToLower(CultureInfo.InvariantCulture), chi);
_consumerPathToHandleAndInstanceMap.Add(counterPath.ToLowerInvariant(), chi);
}
bAtLeastOneAdded = true;
@@ -1236,9 +1236,9 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
continue;
}
string lowerCaseMachine = pathElts.MachineName.ToLower(CultureInfo.InvariantCulture);
string lowerCaseObject = pathElts.ObjectName.ToLower(CultureInfo.InvariantCulture);
string lowerCaseCounter = pathElts.CounterName.ToLower(CultureInfo.InvariantCulture);
string lowerCaseMachine = pathElts.MachineName.ToLowerInvariant();
string lowerCaseObject = pathElts.ObjectName.ToLowerInvariant();
string lowerCaseCounter = pathElts.CounterName.ToLowerInvariant();
string lcPathMinusInstance = @"\\" + lowerCaseMachine + @"\" + lowerCaseObject + @"\" + lowerCaseCounter;
@@ -1311,12 +1311,12 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
if (pathElts.InstanceName != null)
{
chi.InstanceName = pathElts.InstanceName.ToLower(CultureInfo.InvariantCulture);
chi.InstanceName = pathElts.InstanceName.ToLowerInvariant();
}
if (!_reloggerPathToHandleAndInstanceMap.ContainsKey(sample.Path.ToLower(CultureInfo.InvariantCulture)))
if (!_reloggerPathToHandleAndInstanceMap.ContainsKey(sample.Path.ToLowerInvariant()))
{
_reloggerPathToHandleAndInstanceMap.Add(sample.Path.ToLower(CultureInfo.InvariantCulture), chi);
_reloggerPathToHandleAndInstanceMap.Add(sample.Path.ToLowerInvariant(), chi);
//Console.WriteLine ("added map path:" + sample.Path );
}
}
@@ -1370,12 +1370,12 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
chi.hCounter = counterHandle;
if (pathElts.InstanceName != null)
{
chi.InstanceName = pathElts.InstanceName.ToLower(CultureInfo.InvariantCulture);
chi.InstanceName = pathElts.InstanceName.ToLowerInvariant();
}
if (!_reloggerPathToHandleAndInstanceMap.ContainsKey(sample.Path.ToLower(CultureInfo.InvariantCulture)))
if (!_reloggerPathToHandleAndInstanceMap.ContainsKey(sample.Path.ToLowerInvariant()))
{
_reloggerPathToHandleAndInstanceMap.Add(sample.Path.ToLower(CultureInfo.InvariantCulture), chi);
_reloggerPathToHandleAndInstanceMap.Add(sample.Path.ToLowerInvariant(), chi);
}
}
@@ -1756,7 +1756,7 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
bUnknownPath = false;
string lcPath = sample.Path.ToLower(CultureInfo.InvariantCulture);
string lcPath = sample.Path.ToLowerInvariant();
if (!_reloggerPathToHandleAndInstanceMap.ContainsKey(lcPath))
{
@@ -4,7 +4,10 @@
using System;
using System.Runtime.InteropServices;
#if !CORECLR
using System.Runtime.ConstrainedExecution;
#endif
namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
{
@@ -21,7 +24,9 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
}
#if !CORECLR // ReliabilityContract not supported on CoreCLR
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
protected override bool ReleaseHandle()
{
return (PdhHelper.PdhCloseLog(handle, 0) == 0);
@@ -44,7 +49,9 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
}
#if !CORECLR // ReliabilityContract not supported on CoreCLR
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
protected override bool ReleaseHandle()
{
return (PdhHelper.PdhCloseQuery(handle) == 0);
@@ -64,7 +71,9 @@ namespace Microsoft.Powershell.Commands.GetCounter.PdhNative
}
#if !CORECLR // ReliabilityContract not supported on CoreCLR
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
protected override bool ReleaseHandle()
{
return (PdhHelper.PdhCloseLog(handle, 0) == 0);
@@ -45,16 +45,7 @@
"define": [ "CORECLR" ],
"compile": {
"excludeFiles": [
"PdhSafeHandle.cs",
"GetEventSnapin.cs",
"CounterSample.cs",
"CounterSet.cs",
"PdhHelper.cs",
"ExportCounterCommand.cs",
"GetCounterCommand.cs",
"ImportCounterCommand.cs",
"CounterFileInfo.cs",
"gen/GetEventResources.cs"
]
}
@@ -64,7 +55,10 @@
"net451": {
"buildOptions": {
"compile": {
"excludeFiles": [ "gen/GetEventResources.cs" ]
"excludeFiles": [
"CoreCLR/Stubs.cs",
"gen/GetEventResources.cs"
]
},
"debugType": "full"
}
@@ -0,0 +1,79 @@
<Configuration>
<!-- ################ VIEW DEFINITIONS ################ -->
<ViewDefinitions>
<View>
<Name>Counter</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSampleSet</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Timestamp</Label>
<Width>25</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>CounterSamples</Label>
<Alignment>left</Alignment>
<Width>100</Width>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Timestamp</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Readings</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>Counter</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.GetCounter.CounterFileInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>30</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Width>30</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Width>30</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>OldestRecord</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>NewestRecord</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>SampleCount</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<ViewDefinitions>
<View>
<Name>Default</Name>
<ViewSelectedBy>
<TypeName>System.Diagnostics.Eventing.Reader.EventLogRecord</TypeName>
</ViewSelectedBy>
<GroupBy>
<PropertyName>ProviderName</PropertyName>
<Label>ProviderName</Label>
</GroupBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>25</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>8</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Width>16</Width>
</TableColumnHeader>
<TableColumnHeader>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>TimeCreated</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Id</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>LevelDisplayName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Message</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>Default</Name>
<ViewSelectedBy>
<TypeName>System.Diagnostics.Eventing.Reader.EventLogConfiguration</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>LogMode</Label>
<Width>9</Width>
</TableColumnHeader>
<TableColumnHeader>
<Label>MaximumSizeInBytes</Label>
<Width>18</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>RecordCount</Label>
<Width>11</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>LogMode</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>MaximumSizeInBytes</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>RecordCount</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>LogName</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>Default</Name>
<ViewSelectedBy>
<TypeName>System.Diagnostics.Eventing.Reader.ProviderMetadata</TypeName>
</ViewSelectedBy>
<ListControl>
<ListEntries>
<ListEntry>
<ListItems>
<ListItem>
<PropertyName>Name</PropertyName>
</ListItem>
<ListItem>
<PropertyName>LogLinks</PropertyName>
</ListItem>
<ListItem>
<PropertyName>Opcodes</PropertyName>
</ListItem>
<ListItem>
<PropertyName>Tasks</PropertyName>
</ListItem>
</ListItems>
</ListEntry>
</ListEntries>
</ListControl>
</View>
</ViewDefinitions>
</Configuration>
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- *******************************************************************
These sample files contain formatting information used by the Windows
PowerShell engine. Do not edit or change the contents of this file
directly. Please see the Windows PowerShell documentation or type
Get-Help Update-TypeData for more information.
Copyright (c) Microsoft Corporation. All rights reserved.
THIS SAMPLE CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
OF ANY KIND,WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE. IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE
OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE AND INFORMATION
REMAINS WITH THE USER.
******************************************************************** -->
<Types>
<Type>
<Name>System.Diagnostics.Eventing.Reader.EventLogConfiguration</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>LogName</Name>
<Name>MaximumSizeInBytes</Name>
<Name>RecordCount</Name>
<Name>LogMode</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
<Type>
<Name>System.Diagnostics.Eventing.Reader.EventLogRecord</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>TimeCreated</Name>
<Name>ProviderName</Name>
<Name>Id</Name>
<Name>Message</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
<Type>
<Name>System.Diagnostics.Eventing.Reader.ProviderMetadata</Name>
<Members>
<AliasProperty>
<Name>ProviderName</Name>
<ReferencedMemberName>Name</ReferencedMemberName>
</AliasProperty>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>Name</Name>
<Name>LogLinks</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
<Type>
<Name>Microsoft.PowerShell.Commands.GetCounter.CounterSet</Name>
<Members>
<AliasProperty>
<Name>Counter</Name>
<ReferencedMemberName>Paths</ReferencedMemberName>
</AliasProperty>
</Members>
</Type>
<Type>
<Name>Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>Path</Name>
<Name>InstanceName</Name>
<Name>CookedValue</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
<Type>
<Name>Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSampleSet</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>Timestamp</Name>
<Name>Readings</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
<Type>
<Name>Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSampleSet</Name>
<Members>
<ScriptProperty>
<Name>Readings</Name>
<GetScriptBlock>
$strPaths = ""
foreach ($ctr in $this.CounterSamples)
{
$strPaths += ($ctr.Path + " :" + "`n")
$strPaths += ($ctr.CookedValue.ToString() + "`n`n")
}
return $strPaths
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
</Types>
@@ -5,9 +5,9 @@ CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CmdletsToExport="Get-WinEvent", "New-WinEvent"
CmdletsToExport="Get-WinEvent", "New-WinEvent", "Get-Counter", "Import-Counter", "Export-Counter"
NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll"
TypesToProcess="..\..\GetEvent.types.ps1xml"
FormatsToProcess="..\..\Event.format.ps1xml"
TypesToProcess="GetEvent.types.ps1xml"
FormatsToProcess="Event.format.ps1xml", "Diagnostics.format.ps1xml"
HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390783'
}
}