MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#region Using directives5 6using System;7using System.Globalization;8using System.Management.Automation;9 10#endregion11 12namespace Microsoft.Management.Infrastructure.CimCmdlets13{14 #region AsyncResultType15 /// <summary>16 /// <para>17 /// Async result type18 /// </para>19 /// </summary>20 public enum AsyncResultType21 {22 Result,23 Exception,24 Completion25 }26 #endregion27 28 #region CimResultContext29 /// <summary>30 /// Cim Result Context.31 /// </summary>32 internal class CimResultContext33 {34 /// <summary>35 /// Initializes a new instance of the <see cref="CimResultContext"/> class.36 /// </summary>37 /// <param name="ErrorSource"></param>38 internal CimResultContext(object ErrorSource)39 {40 this.ErrorSource = ErrorSource;41 }42 43 /// <summary>44 /// ErrorSource property.45 /// </summary>46 internal object ErrorSource { get; }47 }48 #endregion49 50 #region AsyncResultEventArgsBase51 /// <summary>52 /// <para>53 /// Base class of async result event argument54 /// </para>55 /// </summary>56 internal abstract class AsyncResultEventArgsBase : EventArgs57 {58 /// <summary>59 /// Initializes a new instance of the <see cref="AsyncResultEventArgsBase"/> class.60 /// </summary>61 /// <param name="session"></param>62 /// <param name="observable"></param>63 /// <param name="resultType"></param>64 protected AsyncResultEventArgsBase(65 CimSession session,66 IObservable<object> observable,67 AsyncResultType resultType)68 {69 this.session = session;70 this.observable = observable;71 this.resultType = resultType;72 }73 74 /// <summary>75 /// Initializes a new instance of the <see cref="AsyncResultEventArgsBase"/> class.76 /// </summary>77 /// <param name="session"></param>78 /// <param name="observable"></param>79 /// <param name="resultType"></param>80 /// <param name="context"></param>81 protected AsyncResultEventArgsBase(82 CimSession session,83 IObservable<object> observable,84 AsyncResultType resultType,85 CimResultContext cimResultContext)86 {87 this.session = session;88 this.observable = observable;89 this.resultType = resultType;90 this.context = cimResultContext;91 }92 93 public readonly CimSession session;94 public readonly IObservable<object> observable;95 public readonly AsyncResultType resultType;96 97 // property ErrorSource98 public readonly CimResultContext context;99 }100 101 #endregion102 103 #region AsyncResult*Args104 /// <summary>105 /// <para>106 /// operation successfully completed event argument107 /// </para>108 /// </summary>109 internal class AsyncResultCompleteEventArgs : AsyncResultEventArgsBase110 {111 /// <summary>112 /// Initializes a new instance of the <see cref="AsyncResultCompleteEventArgs"/> class.113 /// </summary>114 /// <param name="session"><see cref="CimSession"/> object.</param>115 /// <param name="cancellationDisposable"></param>116 public AsyncResultCompleteEventArgs(117 CimSession session,118 IObservable<object> observable)119 : base(session, observable, AsyncResultType.Completion)120 {121 }122 }123 124 /// <summary>125 /// <para>126 /// async result argument with object127 /// </para>128 /// </summary>129 internal class AsyncResultObjectEventArgs : AsyncResultEventArgsBase130 {131 /// <summary>132 /// Initializes a new instance of the <see cref="AsyncResultObjectEventArgs"/> class.133 /// </summary>134 /// <param name="session"></param>135 /// <param name="observable"></param>136 /// <param name="resultObject"></param>137 public AsyncResultObjectEventArgs(138 CimSession session,139 IObservable<object> observable,140 object resultObject)141 : base(session, observable, AsyncResultType.Result)142 {143 this.resultObject = resultObject;144 }145 146 public readonly object resultObject;147 }148 149 /// <summary>150 /// <para>151 /// operation completed with exception event argument152 /// </para>153 /// </summary>154 internal class AsyncResultErrorEventArgs : AsyncResultEventArgsBase155 {156 /// <summary>157 /// Initializes a new instance of the <see cref="AsyncResultErrorEventArgs"/> class.158 /// </summary>159 /// <param name="session"></param>160 /// <param name="observable"></param>161 /// <param name="error"></param>162 public AsyncResultErrorEventArgs(163 CimSession session,164 IObservable<object> observable,165 Exception error)166 : base(session, observable, AsyncResultType.Exception)167 {168 this.error = error;169 }170 171 /// <summary>172 /// Initializes a new instance of the <see cref="AsyncResultErrorEventArgs"/> class.173 /// </summary>174 /// <param name="session"></param>175 /// <param name="observable"></param>176 /// <param name="error"></param>177 /// <param name="context"></param>178 public AsyncResultErrorEventArgs(179 CimSession session,180 IObservable<object> observable,181 Exception error,182 CimResultContext cimResultContext)183 : base(session, observable, AsyncResultType.Exception, cimResultContext)184 {185 this.error = error;186 }187 188 public readonly Exception error;189 }190 #endregion191 192 #region CimResultObserver193 /// <summary>194 /// <para>195 /// Observer to consume results from asynchronous operations, such as,196 /// EnumerateInstancesAsync operation of <see cref="CimSession"/> object.197 /// </para>198 /// <para>199 /// (See https://channel9.msdn.com/posts/J.Van.Gogh/Reactive-Extensions-API-in-depth-Contract/)200 /// for the IObserver/IObservable contact201 /// - the only possible sequence is OnNext* (OnCompleted|OnError)?202 /// - callbacks are serialized203 /// - Subscribe never throws204 /// </para>205 /// </summary>206 /// <typeparam name="T">object type</typeparam>207 internal class CimResultObserver<T> : IObserver<T>208 {209 /// <summary>210 /// Define an Event based on the NewActionHandler.211 /// </summary>212 public event EventHandler<AsyncResultEventArgsBase> OnNewResult;213 214 /// <summary>215 /// Initializes a new instance of the <see cref="CimResultObserver{T}"/> class.216 /// </summary>217 /// <param name="session"><see cref="CimSession"/> object that issued the operation.</param>218 /// <param name="observable">Operation that can be observed.</param>219 public CimResultObserver(CimSession session, IObservable<object> observable)220 {221 this.CurrentSession = session;222 this.observable = observable;223 }224 225 /// <summary>226 /// Initializes a new instance of the <see cref="CimResultObserver{T}"/> class.227 /// </summary>228 /// <param name="session"><see cref="CimSession"/> object that issued the operation.</param>229 /// <param name="observable">Operation that can be observed.</param>230 public CimResultObserver(CimSession session,231 IObservable<object> observable,232 CimResultContext cimResultContext)233 {234 this.CurrentSession = session;235 this.observable = observable;236 this.context = cimResultContext;237 }238 239 /// <summary>240 /// <para>241 /// Operation completed successfully242 /// </para>243 /// </summary>244 public virtual void OnCompleted()245 {246 // callbacks should never throw any exception to247 // protocol layer, otherwise the client process will be248 // terminated because of unhandled exception, same with249 // OnNext, OnError250 try251 {252 AsyncResultCompleteEventArgs completeArgs = new(253 this.CurrentSession, this.observable);254 this.OnNewResult(this, completeArgs);255 }256 catch (Exception ex)257 {258 this.OnError(ex);259 DebugHelper.WriteLogEx("{0}", 0, ex);260 }261 }262 263 /// <summary>264 /// <para>265 /// Operation completed with an error266 /// </para>267 /// </summary>268 /// <param name="error">Error object.</param>269 public virtual void OnError(Exception error)270 {271 try272 {273 AsyncResultErrorEventArgs errorArgs = new(274 this.CurrentSession, this.observable, error, this.context);275 this.OnNewResult(this, errorArgs);276 }277 catch (Exception ex)278 {279 // !!ignore the exception280 DebugHelper.WriteLogEx("{0}", 0, ex);281 }282 }283 284 /// <summary>285 /// Deliver the result value.286 /// </summary>287 /// <param name="value"></param>288 protected void OnNextCore(object value)289 {290 DebugHelper.WriteLogEx("value = {0}.", 1, value);291 try292 {293 AsyncResultObjectEventArgs resultArgs = new(294 this.CurrentSession, this.observable, value);295 this.OnNewResult(this, resultArgs);296 }297 catch (Exception ex)298 {299 this.OnError(ex);300 DebugHelper.WriteLogEx("{0}", 0, ex);301 }302 }303 304 /// <summary>305 /// <para>306 /// Operation got a new result object307 /// </para>308 /// </summary>309 /// <param name="value">Result object.</param>310 public virtual void OnNext(T value)311 {312 DebugHelper.WriteLogEx("value = {0}.", 1, value);313 // do not allow null value314 if (value == null)315 {316 return;317 }318 319 this.OnNextCore(value);320 }321 322 #region members323 324 /// <summary>325 /// Session object of the operation.326 /// </summary>327 protected CimSession CurrentSession { get; }328 329 /// <summary>330 /// Async operation that can be observed.331 /// </summary>332 private readonly IObservable<object> observable;333 334 /// <summary>335 /// <see cref="CimResultContext"/> object used during delivering result.336 /// </summary>337 private readonly CimResultContext context;338 #endregion339 }340 341 /// <summary>342 /// CimSubscriptionResultObserver class definition.343 /// </summary>344 internal class CimSubscriptionResultObserver : CimResultObserver<CimSubscriptionResult>345 {346 /// <summary>347 /// Initializes a new instance of the <see cref="CimSubscriptionResultObserver"/> class.348 /// </summary>349 /// <param name="session"></param>350 /// <param name="observable"></param>351 public CimSubscriptionResultObserver(CimSession session, IObservable<object> observable)352 : base(session, observable)353 {354 }355 356 /// <summary>357 /// Initializes a new instance of the <see cref="CimSubscriptionResultObserver"/> class.358 /// </summary>359 /// <param name="session"></param>360 /// <param name="observable"></param>361 public CimSubscriptionResultObserver(362 CimSession session,363 IObservable<object> observable,364 CimResultContext context)365 : base(session, observable, context)366 {367 }368 369 /// <summary>370 /// Override the OnNext method.371 /// </summary>372 /// <param name="value"></param>373 public override void OnNext(CimSubscriptionResult value)374 {375 DebugHelper.WriteLogEx();376 base.OnNextCore(value);377 }378 }379 380 /// <summary>381 /// CimMethodResultObserver class definition.382 /// </summary>383 internal class CimMethodResultObserver : CimResultObserver<CimMethodResultBase>384 {385 /// <summary>386 /// Initializes a new instance of the <see cref="CimMethodResultObserver"/> class.387 /// </summary>388 /// <param name="session"></param>389 /// <param name="observable"></param>390 public CimMethodResultObserver(CimSession session, IObservable<object> observable)391 : base(session, observable)392 {393 }394 395 /// <summary>396 /// Initializes a new instance of the <see cref="CimMethodResultObserver"/> class.397 /// </summary>398 /// <param name="session"></param>399 /// <param name="observable"></param>400 /// <param name="context"></param>401 public CimMethodResultObserver(402 CimSession session,403 IObservable<object> observable,404 CimResultContext context)405 : base(session, observable, context)406 {407 }408 409 /// <summary>410 /// Override the OnNext method.411 /// </summary>412 /// <param name="value"></param>413 public override void OnNext(CimMethodResultBase value)414 {415 DebugHelper.WriteLogEx();416 const string PSTypeCimMethodResult = @"Microsoft.Management.Infrastructure.CimMethodResult";417 const string PSTypeCimMethodStreamedResult = @"Microsoft.Management.Infrastructure.CimMethodStreamedResult";418 const string PSTypeCimMethodResultTemplate = @"{0}#{1}#{2}";419 420 string resultObjectPSType = null;421 PSObject resultObject = null;422 if (value is CimMethodResult methodResult)423 {424 resultObjectPSType = PSTypeCimMethodResult;425 resultObject = new PSObject();426 foreach (CimMethodParameter param in methodResult.OutParameters)427 {428 resultObject.Properties.Add(new PSNoteProperty(param.Name, param.Value));429 }430 }431 else432 {433 if (value is CimMethodStreamedResult methodStreamedResult)434 {435 resultObjectPSType = PSTypeCimMethodStreamedResult;436 resultObject = new PSObject();437 resultObject.Properties.Add(new PSNoteProperty(@"ParameterName", methodStreamedResult.ParameterName));438 resultObject.Properties.Add(new PSNoteProperty(@"ItemType", methodStreamedResult.ItemType));439 resultObject.Properties.Add(new PSNoteProperty(@"ItemValue", methodStreamedResult.ItemValue));440 }441 }442 443 if (resultObject != null)444 {445 resultObject.Properties.Add(new PSNoteProperty(@"PSComputerName", this.CurrentSession.ComputerName));446 resultObject.TypeNames.Insert(0, resultObjectPSType);447 resultObject.TypeNames.Insert(0, string.Format(CultureInfo.InvariantCulture, PSTypeCimMethodResultTemplate, resultObjectPSType, ClassName, MethodName));448 base.OnNextCore(resultObject);449 }450 }451 452 /// <summary>453 /// Methodname.454 /// </summary>455 internal string MethodName456 {457 get;458 set;459 }460 461 /// <summary>462 /// Classname.463 /// </summary>464 internal string ClassName465 {466 get;467 set;468 }469 }470 471 /// <summary>472 /// IgnoreResultObserver class definition.473 /// </summary>474 internal class IgnoreResultObserver : CimResultObserver<CimInstance>475 {476 /// <summary>477 /// Initializes a new instance of the <see cref="IgnoreResultObserver"/> class.478 /// </summary>479 /// <param name="session"></param>480 /// <param name="observable"></param>481 public IgnoreResultObserver(CimSession session, IObservable<object> observable)482 : base(session, observable)483 {484 }485 486 /// <summary>487 /// Override the OnNext method.488 /// </summary>489 /// <param name="value"></param>490 public override void OnNext(CimInstance value)491 {492 DebugHelper.WriteLogEx();493 }494 }495 #endregion496}497 