PageRenderTime 805ms CodeModel.GetById 50ms RepoModel.GetById 23ms app.codeStats 1ms

/src/Microsoft.PowerShell.Commands.Diagnostics/NewWinEventCommand.cs

https://gitlab.com/unofficial-mirrors/PowerShell
C# | 352 lines | 294 code | 31 blank | 27 comment | 38 complexity | 63ea9d9b2f0361ec68dbd295d4bccdd6 MD5 | raw file
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License.
  3. using System;
  4. using System.Management.Automation;
  5. using System.Globalization;
  6. using System.Reflection;
  7. using System.Diagnostics.Eventing;
  8. using System.Diagnostics.Eventing.Reader;
  9. using System.Resources;
  10. using System.Diagnostics.CodeAnalysis;
  11. using System.Collections.Generic;
  12. using System.Xml;
  13. using System.IO;
  14. namespace Microsoft.PowerShell.Commands
  15. {
  16. ///
  17. /// Class that implements the New-WinEvent cmdlet.
  18. /// This cmdlet writes a new Etw event using the provider specified in parameter.
  19. ///
  20. [Cmdlet(VerbsCommon.New, "WinEvent", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=217469")]
  21. public sealed class NewWinEventCommand : PSCmdlet
  22. {
  23. private ProviderMetadata _providerMetadata;
  24. private EventDescriptor? _eventDescriptor;
  25. private const string TemplateTag = "template";
  26. private const string DataTag = "data";
  27. private ResourceManager _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();
  28. /// <summary>
  29. /// ProviderName
  30. /// </summary>
  31. [Parameter(
  32. Position = 0,
  33. Mandatory = true,
  34. ParameterSetName = ParameterAttribute.AllParameterSets)]
  35. public string ProviderName
  36. {
  37. get
  38. {
  39. return _providerName;
  40. }
  41. set
  42. {
  43. _providerName = value;
  44. }
  45. }
  46. private string _providerName;
  47. /// <summary>
  48. /// Id (EventId defined in manifest file)
  49. /// </summary>
  50. [Parameter(
  51. Position = 1,
  52. Mandatory = true,
  53. ParameterSetName = ParameterAttribute.AllParameterSets)]
  54. public int Id
  55. {
  56. get
  57. {
  58. return _id;
  59. }
  60. set
  61. {
  62. _id = value;
  63. _idSpecified = true;
  64. }
  65. }
  66. private int _id;
  67. private bool _idSpecified = false;
  68. /// <summary>
  69. /// Version (event version)
  70. /// </summary>
  71. [Parameter(
  72. Mandatory = false,
  73. ParameterSetName = ParameterAttribute.AllParameterSets)]
  74. public byte Version
  75. {
  76. get
  77. {
  78. return _version;
  79. }
  80. set
  81. {
  82. _version = value;
  83. _versionSpecified = true;
  84. }
  85. }
  86. private byte _version;
  87. private bool _versionSpecified = false;
  88. /// <summary>
  89. /// Event Payload
  90. /// </summary>
  91. [Parameter(
  92. Position = 2,
  93. Mandatory = false,
  94. ParameterSetName = ParameterAttribute.AllParameterSets),
  95. AllowEmptyCollection,
  96. SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",
  97. Target = "Microsoft.PowerShell.Commands",
  98. Justification = "A string[] is required here because that is the type Powershell supports")]
  99. public object[] Payload
  100. {
  101. get
  102. {
  103. return _payload;
  104. }
  105. set
  106. {
  107. _payload = value;
  108. }
  109. }
  110. private object[] _payload;
  111. /// <summary>
  112. /// BeginProcessing
  113. /// </summary>
  114. protected override void BeginProcessing()
  115. {
  116. LoadProvider();
  117. LoadEventDescriptor();
  118. base.BeginProcessing();
  119. }
  120. private void LoadProvider()
  121. {
  122. if (string.IsNullOrEmpty(_providerName))
  123. {
  124. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderNotSpecified")), "ProviderName");
  125. }
  126. using (EventLogSession session = new EventLogSession())
  127. {
  128. foreach (string providerName in session.GetProviderNames())
  129. {
  130. if (string.Equals(providerName, _providerName, StringComparison.OrdinalIgnoreCase))
  131. {
  132. try
  133. {
  134. _providerMetadata = new ProviderMetadata(providerName);
  135. }
  136. catch (EventLogException exc)
  137. {
  138. string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderMetadataUnavailable"), providerName, exc.Message);
  139. throw new Exception(msg, exc);
  140. }
  141. break;
  142. }
  143. }
  144. }
  145. if (_providerMetadata == null)
  146. {
  147. string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoProviderFound"), _providerName);
  148. throw new ArgumentException(msg);
  149. }
  150. }
  151. private void LoadEventDescriptor()
  152. {
  153. if (_idSpecified)
  154. {
  155. List<EventMetadata> matchedEvents = new List<EventMetadata>();
  156. foreach (EventMetadata emd in _providerMetadata.Events)
  157. {
  158. if (emd.Id == _id)
  159. {
  160. matchedEvents.Add(emd);
  161. }
  162. }
  163. if (matchedEvents.Count == 0)
  164. {
  165. string msg = string.Format(CultureInfo.InvariantCulture,
  166. _resourceMgr.GetString("IncorrectEventId"),
  167. _id,
  168. _providerName);
  169. throw new EventWriteException(msg);
  170. }
  171. EventMetadata matchedEvent = null;
  172. if (!_versionSpecified && matchedEvents.Count == 1)
  173. {
  174. matchedEvent = matchedEvents[0];
  175. }
  176. else
  177. {
  178. if (_versionSpecified)
  179. {
  180. foreach (EventMetadata emd in matchedEvents)
  181. {
  182. if (emd.Version == _version)
  183. {
  184. matchedEvent = emd;
  185. break;
  186. }
  187. }
  188. if (matchedEvent == null)
  189. {
  190. string msg = string.Format(CultureInfo.InvariantCulture,
  191. _resourceMgr.GetString("IncorrectEventVersion"),
  192. _version,
  193. _id,
  194. _providerName);
  195. throw new EventWriteException(msg);
  196. }
  197. }
  198. else
  199. {
  200. string msg = string.Format(CultureInfo.InvariantCulture,
  201. _resourceMgr.GetString("VersionNotSpecified"),
  202. _id,
  203. _providerName);
  204. throw new EventWriteException(msg);
  205. }
  206. }
  207. VerifyTemplate(matchedEvent);
  208. _eventDescriptor = CreateEventDescriptor(_providerMetadata, matchedEvent);
  209. }
  210. else
  211. {
  212. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("EventIdNotSpecified")), "Id");
  213. }
  214. }
  215. private bool VerifyTemplate(EventMetadata emd)
  216. {
  217. if (emd.Template != null)
  218. {
  219. XmlReaderSettings readerSettings = new XmlReaderSettings
  220. {
  221. CheckCharacters = false,
  222. IgnoreComments = true,
  223. IgnoreProcessingInstructions = true,
  224. MaxCharactersInDocument = 0, // no limit
  225. ConformanceLevel = ConformanceLevel.Fragment,
  226. #if !CORECLR
  227. XmlResolver = null,
  228. #endif
  229. };
  230. int definedParameterCount = 0;
  231. using (XmlReader reader = XmlReader.Create(new StringReader(emd.Template), readerSettings))
  232. {
  233. if (reader.ReadToFollowing(TemplateTag))
  234. {
  235. bool found = reader.ReadToDescendant(DataTag);
  236. while (found)
  237. {
  238. definedParameterCount++;
  239. found = reader.ReadToFollowing(DataTag);
  240. }
  241. }
  242. }
  243. if ((_payload == null && definedParameterCount != 0)
  244. || ((_payload != null) && _payload.Length != definedParameterCount))
  245. {
  246. string warning = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("PayloadMismatch"), _id, emd.Template);
  247. WriteWarning(warning);
  248. return false;
  249. }
  250. }
  251. return true;
  252. }
  253. private static EventDescriptor CreateEventDescriptor(ProviderMetadata providerMetaData, EventMetadata emd)
  254. {
  255. long keywords = 0;
  256. foreach (EventKeyword keyword in emd.Keywords)
  257. {
  258. keywords |= keyword.Value;
  259. }
  260. byte channel = 0;
  261. foreach (EventLogLink logLink in providerMetaData.LogLinks)
  262. {
  263. if (string.Equals(logLink.LogName, emd.LogLink.LogName, StringComparison.OrdinalIgnoreCase))
  264. break;
  265. channel++;
  266. }
  267. return new EventDescriptor(
  268. (int)emd.Id,
  269. emd.Version,
  270. channel,
  271. (byte)emd.Level.Value,
  272. (byte)emd.Opcode.Value,
  273. emd.Task.Value,
  274. keywords);
  275. }
  276. /// <summary>
  277. /// ProcessRecord
  278. /// </summary>
  279. protected override void ProcessRecord()
  280. {
  281. using (EventProvider provider = new EventProvider(_providerMetadata.Id))
  282. {
  283. EventDescriptor ed = _eventDescriptor.Value;
  284. if (_payload != null && _payload.Length > 0)
  285. {
  286. for (int i = 0; i < _payload.Length; i++)
  287. {
  288. if (_payload[i] == null)
  289. {
  290. _payload[i] = string.Empty;
  291. }
  292. }
  293. provider.WriteEvent(ref ed, _payload);
  294. }
  295. else
  296. {
  297. provider.WriteEvent(ref ed);
  298. }
  299. }
  300. base.ProcessRecord();
  301. }
  302. /// <summary>
  303. /// EndProcessing
  304. /// </summary>
  305. protected override void EndProcessing()
  306. {
  307. if (_providerMetadata != null)
  308. _providerMetadata.Dispose();
  309. base.EndProcessing();
  310. }
  311. }
  312. internal class EventWriteException : Exception
  313. {
  314. internal EventWriteException(string msg, Exception innerException)
  315. : base(msg, innerException)
  316. { }
  317. internal EventWriteException(string msg)
  318. : base(msg)
  319. { }
  320. }
  321. }