MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Collections.Specialized;9using System.ComponentModel;10using System.Diagnostics;11using System.Diagnostics.CodeAnalysis;12using System.Globalization;13using System.IO;14using System.Management.Automation;15using System.Management.Automation.Runspaces;16using System.Net;17using System.Reflection;18using System.Resources;19using System.Security;20using System.Security.Principal;21using System.Text;22using System.Threading;23using System.Xml;24 25using Microsoft.PowerShell.Commands.Diagnostics.Common;26using Microsoft.PowerShell.Commands.GetCounter;27using Microsoft.Powershell.Commands.GetCounter.PdhNative;28 29namespace Microsoft.PowerShell.Commands30{31 ///32 /// Class that implements the Get-Counter cmdlet.33 ///34 [Cmdlet(VerbsData.Export, "Counter", DefaultParameterSetName = "ExportCounterSet", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=138337")]35 public sealed class ExportCounterCommand : PSCmdlet36 {37 //38 // Path parameter39 //40 [Parameter(41 Mandatory = true,42 Position = 0,43 ValueFromPipelineByPropertyName = true,44 HelpMessageBaseName = "GetEventResources")]45 [Alias("PSPath")]46 47 public string Path48 {49 get { return _path; }50 51 set { _path = value; }52 }53 54 private string _path;55 private string _resolvedPath;56 57 //58 // Format parameter.59 // Valid strings are "blg", "csv", "tsv" (case-insensitive).60 //61 [Parameter(62 Mandatory = false,63 ValueFromPipeline = false,64 ValueFromPipelineByPropertyName = false,65 HelpMessageBaseName = "GetEventResources")]66 [ValidateNotNull]67 [ValidateSet("blg", "csv", "tsv")]68 public string FileFormat69 {70 get { return _format; }71 72 set { _format = value; }73 }74 75 private string _format = "blg";76 77 //78 // MaxSize parameter79 // Maximum output file size, in megabytes.80 //81 [Parameter(82 HelpMessageBaseName = "GetEventResources")]83 public UInt32 MaxSize84 {85 get { return _maxSize; }86 87 set { _maxSize = value; }88 }89 90 private UInt32 _maxSize = 0;91 92 //93 // InputObject parameter94 //95 [Parameter(96 Mandatory = true,97 ValueFromPipeline = true,98 ValueFromPipelineByPropertyName = true,99 HelpMessageBaseName = "GetEventResources")]100 101 [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",102 Scope = "member",103 Target = "Microsoft.PowerShell.Commands.ExportCounterCommand.InputObject",104 Justification = "A PerformanceCounterSampleSet[] is required here because Powershell supports arrays natively.")]105 public PerformanceCounterSampleSet[] InputObject106 {107 get { return _counterSampleSets; }108 109 set { _counterSampleSets = value; }110 }111 112 private PerformanceCounterSampleSet[] _counterSampleSets = new PerformanceCounterSampleSet[0];113 114 //115 // Force switch116 //117 [Parameter(118 HelpMessageBaseName = "GetEventResources")]119 public SwitchParameter Force120 {121 get { return _force; }122 123 set { _force = value; }124 }125 126 private SwitchParameter _force;127 128 //129 // Circular switch130 //131 [Parameter(132 HelpMessageBaseName = "GetEventResources")]133 public SwitchParameter Circular134 {135 get { return _circular; }136 137 set { _circular = value; }138 }139 140 private SwitchParameter _circular;141 142 private ResourceManager _resourceMgr = null;143 144 private PdhHelper _pdhHelper = null;145 146 private bool _stopping = false;147 148 private bool _queryInitialized = false;149 150 private PdhLogFileType _outputFormat = PdhLogFileType.PDH_LOG_TYPE_BINARY;151 152 //153 // BeginProcessing() is invoked once per pipeline154 //155 protected override void BeginProcessing()156 {157 158#if CORECLR159 if (Platform.IsIoT)160 {161 // IoT does not have the '$env:windir\System32\pdh.dll' assembly which is required by this cmdlet.162 throw new PlatformNotSupportedException();163 }164 165 // PowerShell 7 requires at least Windows 7,166 // so no version test is needed167 _pdhHelper = new PdhHelper(false);168#else169 //170 // Determine the OS version: this cmdlet requires Windows 7171 // because it uses new Pdh functionality.172 //173 Version osVersion = System.Environment.OSVersion.Version;174 if (osVersion.Major < 6 ||175 (osVersion.Major == 6 && osVersion.Minor < 1))176 {177 string msg = _resourceMgr.GetString("ExportCtrWin7Required");178 Exception exc = new Exception(msg);179 ThrowTerminatingError(new ErrorRecord(exc, "ExportCtrWin7Required", ErrorCategory.NotImplemented, null));180 }181 182 _pdhHelper = new PdhHelper(osVersion.Major < 6);183#endif184 _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();185 186 //187 // Set output format (log file type)188 //189 SetOutputFormat();190 191 if (Circular.IsPresent && _maxSize == 0)192 {193 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterCircularNoMaxSize"));194 Exception exc = new Exception(msg);195 WriteError(new ErrorRecord(exc, "CounterCircularNoMaxSize", ErrorCategory.InvalidResult, null));196 }197 198 uint res = _pdhHelper.ConnectToDataSource();199 if (res != 0)200 {201 ReportPdhError(res, true);202 }203 204 res = _pdhHelper.OpenQuery();205 if (res != 0)206 {207 ReportPdhError(res, true);208 }209 }210 211 //212 // EndProcessing() is invoked once per pipeline213 //214 protected override void EndProcessing()215 {216 _pdhHelper.Dispose();217 }218 219 ///220 /// Handle Control-C221 ///222 protected override void StopProcessing()223 {224 _stopping = true;225 _pdhHelper.Dispose();226 }227 228 //229 // ProcessRecord() override.230 // This is the main entry point for the cmdlet.231 // When counter data comes from the pipeline, this gets invoked for each pipelined object.232 // When it's passed in as an argument, ProcessRecord() is called once for the entire _counterSampleSets array.233 //234 protected override void ProcessRecord()235 {236 Debug.Assert(_counterSampleSets.Length != 0 && _counterSampleSets[0] != null);237 238 ResolvePath();239 240 uint res = 0;241 242 if (!_queryInitialized)243 {244 if (_format.ToLowerInvariant().Equals("blg"))245 {246 res = _pdhHelper.AddRelogCounters(_counterSampleSets[0]);247 }248 else249 {250 res = _pdhHelper.AddRelogCountersPreservingPaths(_counterSampleSets[0]);251 }252 253 if (res != 0)254 {255 ReportPdhError(res, true);256 }257 258 res = _pdhHelper.OpenLogForWriting(_resolvedPath, _outputFormat, Force.IsPresent, _maxSize * 1024 * 1024, Circular.IsPresent, null);259 if (res == PdhResults.PDH_FILE_ALREADY_EXISTS)260 {261 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterFileExists"), _resolvedPath);262 Exception exc = new Exception(msg);263 ThrowTerminatingError(new ErrorRecord(exc, "CounterFileExists", ErrorCategory.InvalidResult, null));264 }265 else if (res == PdhResults.PDH_LOG_FILE_CREATE_ERROR)266 {267 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("FileCreateFailed"), _resolvedPath);268 Exception exc = new Exception(msg);269 ThrowTerminatingError(new ErrorRecord(exc, "FileCreateFailed", ErrorCategory.InvalidResult, null));270 }271 else if (res == PdhResults.PDH_LOG_FILE_OPEN_ERROR)272 {273 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("FileOpenFailed"), _resolvedPath);274 Exception exc = new Exception(msg);275 ThrowTerminatingError(new ErrorRecord(exc, "FileOpenFailed", ErrorCategory.InvalidResult, null));276 }277 else if (res != 0)278 {279 ReportPdhError(res, true);280 }281 282 _queryInitialized = true;283 }284 285 foreach (PerformanceCounterSampleSet set in _counterSampleSets)286 {287 _pdhHelper.ResetRelogValues();288 289 foreach (PerformanceCounterSample sample in set.CounterSamples)290 {291 bool bUnknownKey = false;292 res = _pdhHelper.SetCounterValue(sample, out bUnknownKey);293 if (bUnknownKey)294 {295 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterExportSampleNotInInitialSet"), sample.Path, _resolvedPath);296 Exception exc = new Exception(msg);297 WriteError(new ErrorRecord(exc, "CounterExportSampleNotInInitialSet", ErrorCategory.InvalidResult, null));298 }299 else if (res != 0)300 {301 ReportPdhError(res, true);302 }303 }304 305 res = _pdhHelper.WriteRelogSample(set.Timestamp);306 if (res != 0)307 {308 ReportPdhError(res, true);309 }310 311 if (_stopping)312 {313 break;314 }315 }316 }317 318 // Determines Log File Type based on FileFormat parameter319 //320 private void SetOutputFormat()321 {322 switch (_format.ToLowerInvariant())323 {324 case "csv":325 _outputFormat = PdhLogFileType.PDH_LOG_TYPE_CSV;326 break;327 case "tsv":328 _outputFormat = PdhLogFileType.PDH_LOG_TYPE_TSV;329 break;330 default: // By default file format is blg331 _outputFormat = PdhLogFileType.PDH_LOG_TYPE_BINARY;332 break;333 }334 }335 336 private void ResolvePath()337 {338 try339 {340 Collection<PathInfo> result = null;341 result = SessionState.Path.GetResolvedPSPathFromPSPath(_path);342 if (result.Count > 1)343 {344 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ExportDestPathAmbiguous"), _path);345 Exception exc = new Exception(msg);346 ThrowTerminatingError(new ErrorRecord(exc, "ExportDestPathAmbiguous", ErrorCategory.InvalidArgument, null));347 }348 349 foreach (PathInfo currentPath in result)350 {351 _resolvedPath = currentPath.ProviderPath;352 }353 }354 catch (ItemNotFoundException pathNotFound)355 {356 //357 // This is an expected condition - we will be creating a new file358 //359 _resolvedPath = pathNotFound.ItemName;360 }361 }362 363 private void ReportPdhError(uint res, bool bTerminate)364 {365 string msg;366 uint formatRes = CommonUtilities.FormatMessageFromModule(res, "pdh.dll", out msg);367 if (formatRes != 0)368 {369 msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("CounterApiError"), res);370 }371 372 Exception exc = new Exception(msg);373 if (bTerminate)374 {375 ThrowTerminatingError(new ErrorRecord(exc, "CounterApiError", ErrorCategory.InvalidResult, null));376 }377 else378 {379 WriteError(new ErrorRecord(exc, "CounterApiError", ErrorCategory.InvalidResult, null));380 }381 }382 }383}384 