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.Diagnostics;8using System.Globalization;9using System.Management.Automation;10using Microsoft.Management.Infrastructure.Options;11 12#endregion13 14namespace Microsoft.Management.Infrastructure.CimCmdlets15{16 #region class ErrorToErrorRecord17 18 /// <summary>19 /// <para>20 /// Convert error or exception to <see cref="System.Management.Automation.ErrorRecord"/>21 /// </para>22 /// </summary>23 internal sealed class ErrorToErrorRecord24 {25 /// <summary>26 /// <para>27 /// Convert ErrorRecord from exception object, <see cref="Exception"/>28 /// can be either <see cref="CimException"/> or general <see cref="Exception"/>.29 /// </para>30 /// </summary>31 /// <param name="inner"></param>32 /// <param name="context">The context starting the operation, which generated the error.</param>33 /// <param name="cimResultContext">The CimResultContext used to provide ErrorSource, etc. info.</param>34 /// <returns></returns>35 internal static ErrorRecord ErrorRecordFromAnyException(36 InvocationContext context,37 Exception inner,38 CimResultContext cimResultContext)39 {40 Debug.Assert(inner != null, "Caller should verify inner != null");41 42 if (inner is CimException cimException)43 {44 return CreateFromCimException(context, cimException, cimResultContext);45 }46 47 if (inner is IContainsErrorRecord containsErrorRecord)48 {49 return InitializeErrorRecord(context,50 exception: inner,51 errorId: "CimCmdlet_" + containsErrorRecord.ErrorRecord.FullyQualifiedErrorId,52 errorCategory: containsErrorRecord.ErrorRecord.CategoryInfo.Category,53 cimResultContext: cimResultContext);54 }55 else56 {57 return InitializeErrorRecord(context,58 exception: inner,59 errorId: "CimCmdlet_" + inner.GetType().Name,60 errorCategory: ErrorCategory.NotSpecified,61 cimResultContext: cimResultContext);62 }63 }64 65 #region Helper functions66 /// <summary>67 /// Create <see cref="ErrorRecord"/> from <see cref="CimException"/> object.68 /// </summary>69 /// <param name="context"></param>70 /// <param name="cimException"></param>71 /// <param name="cimResultContext">The CimResultContext used to provide ErrorSource, etc. info.</param>72 /// <returns></returns>73 internal static ErrorRecord CreateFromCimException(74 InvocationContext context,75 CimException cimException,76 CimResultContext cimResultContext)77 {78 Debug.Assert(cimException != null, "Caller should verify cimException != null");79 80 return InitializeErrorRecord(context, cimException, cimResultContext);81 }82 83 /// <summary>84 /// Create <see cref="ErrorRecord"/> from <see cref="Exception"/> object.85 /// </summary>86 /// <param name="context"></param>87 /// <param name="exception"></param>88 /// <param name="errorId"></param>89 /// <param name="errorCategory"></param>90 /// <param name="cimResultContext">The CimResultContext used to provide ErrorSource, etc. info.</param>91 /// <returns></returns>92 internal static ErrorRecord InitializeErrorRecord(93 InvocationContext context,94 Exception exception,95 string errorId,96 ErrorCategory errorCategory,97 CimResultContext cimResultContext)98 {99 return InitializeErrorRecordCore(100 context,101 exception: exception,102 errorId: errorId,103 errorCategory: errorCategory,104 cimResultContext: cimResultContext);105 }106 107 /// <summary>108 /// Create <see cref="ErrorRecord"/> from <see cref="CimException"/> object.109 /// </summary>110 /// <param name="context"></param>111 /// <param name="cimException"></param>112 /// <param name="cimResultContext">The CimResultContext used to provide ErrorSource, etc. info.</param>113 /// <returns></returns>114 internal static ErrorRecord InitializeErrorRecord(115 InvocationContext context,116 CimException cimException,117 CimResultContext cimResultContext)118 {119 ErrorRecord errorRecord = InitializeErrorRecordCore(120 context,121 exception: cimException,122 errorId: cimException.MessageId ?? "MiClientApiError_" + cimException.NativeErrorCode,123 errorCategory: ConvertCimExceptionToErrorCategory(cimException),124 cimResultContext: cimResultContext);125 126 if (cimException.ErrorData != null)127 {128 errorRecord.CategoryInfo.TargetName = cimException.ErrorSource;129 }130 131 return errorRecord;132 }133 134 /// <summary>135 /// Create <see cref="ErrorRecord"/> from <see cref="Exception"/> object.136 /// </summary>137 /// <param name="context"></param>138 /// <param name="exception"></param>139 /// <param name="errorId"></param>140 /// <param name="errorCategory"></param>141 /// <param name="cimResultContext">The CimResultContext used to provide ErrorSource, etc. info.</param>142 /// <returns></returns>143 internal static ErrorRecord InitializeErrorRecordCore(144 InvocationContext context,145 Exception exception,146 string errorId,147 ErrorCategory errorCategory,148 CimResultContext cimResultContext)149 {150 object theTargetObject = null;151 if (cimResultContext != null)152 {153 theTargetObject = cimResultContext.ErrorSource;154 }155 156 if (theTargetObject == null)157 {158 if (context != null)159 {160 if (context.TargetCimInstance != null)161 {162 theTargetObject = context.TargetCimInstance;163 }164 }165 }166 167 ErrorRecord coreErrorRecord = new(168 exception: exception,169 errorId: errorId,170 errorCategory: errorCategory,171 targetObject: theTargetObject);172 173 if (context == null)174 {175 return coreErrorRecord;176 }177 178 System.Management.Automation.Remoting.OriginInfo originInfo = new(179 context.ComputerName,180 Guid.Empty);181 182 ErrorRecord errorRecord = new System.Management.Automation.Runspaces.RemotingErrorRecord(183 coreErrorRecord,184 originInfo);185 186 DebugHelper.WriteLogEx("Created RemotingErrorRecord.", 0);187 return errorRecord;188 }189 190 /// <summary>191 /// Convert <see cref="CimException"/> to <see cref="ErrorCategory"/>.192 /// </summary>193 /// <param name="cimException"></param>194 /// <returns></returns>195 internal static ErrorCategory ConvertCimExceptionToErrorCategory(CimException cimException)196 {197 ErrorCategory result = ErrorCategory.NotSpecified;198 199 if (cimException.ErrorData != null)200 {201 result = ConvertCimErrorToErrorCategory(cimException.ErrorData);202 }203 204 if (result == ErrorCategory.NotSpecified)205 {206 result = ConvertCimNativeErrorCodeToErrorCategory(cimException.NativeErrorCode);207 }208 209 return result;210 }211 212 /// <summary>213 /// Convert <see cref="NativeErrorCode"/> to <see cref="ErrorCategory"/>.214 /// </summary>215 /// <param name="nativeErrorCode"></param>216 /// <returns></returns>217 internal static ErrorCategory ConvertCimNativeErrorCodeToErrorCategory(NativeErrorCode nativeErrorCode)218 {219 switch (nativeErrorCode)220 {221 case NativeErrorCode.Failed:222 return ErrorCategory.NotSpecified;223 case NativeErrorCode.AccessDenied:224 return ErrorCategory.PermissionDenied;225 case NativeErrorCode.InvalidNamespace:226 return ErrorCategory.MetadataError;227 case NativeErrorCode.InvalidParameter:228 return ErrorCategory.InvalidArgument;229 case NativeErrorCode.InvalidClass:230 return ErrorCategory.MetadataError;231 case NativeErrorCode.NotFound:232 return ErrorCategory.ObjectNotFound;233 case NativeErrorCode.NotSupported:234 return ErrorCategory.NotImplemented;235 case NativeErrorCode.ClassHasChildren:236 return ErrorCategory.MetadataError;237 case NativeErrorCode.ClassHasInstances:238 return ErrorCategory.MetadataError;239 case NativeErrorCode.InvalidSuperClass:240 return ErrorCategory.MetadataError;241 case NativeErrorCode.AlreadyExists:242 return ErrorCategory.ResourceExists;243 case NativeErrorCode.NoSuchProperty:244 return ErrorCategory.MetadataError;245 case NativeErrorCode.TypeMismatch:246 return ErrorCategory.InvalidType;247 case NativeErrorCode.QueryLanguageNotSupported:248 return ErrorCategory.NotImplemented;249 case NativeErrorCode.InvalidQuery:250 return ErrorCategory.InvalidArgument;251 case NativeErrorCode.MethodNotAvailable:252 return ErrorCategory.MetadataError;253 case NativeErrorCode.MethodNotFound:254 return ErrorCategory.MetadataError;255 case NativeErrorCode.NamespaceNotEmpty:256 return ErrorCategory.MetadataError;257 case NativeErrorCode.InvalidEnumerationContext:258 return ErrorCategory.MetadataError;259 case NativeErrorCode.InvalidOperationTimeout:260 return ErrorCategory.InvalidArgument;261 case NativeErrorCode.PullHasBeenAbandoned:262 return ErrorCategory.OperationStopped;263 case NativeErrorCode.PullCannotBeAbandoned:264 return ErrorCategory.CloseError;265 case NativeErrorCode.FilteredEnumerationNotSupported:266 return ErrorCategory.NotImplemented;267 case NativeErrorCode.ContinuationOnErrorNotSupported:268 return ErrorCategory.NotImplemented;269 case NativeErrorCode.ServerLimitsExceeded:270 return ErrorCategory.ResourceBusy;271 case NativeErrorCode.ServerIsShuttingDown:272 return ErrorCategory.ResourceUnavailable;273 default:274 return ErrorCategory.NotSpecified;275 }276 }277 278 /// <summary>279 /// Convert <see cref="cimError"/> to <see cref="ErrorCategory"/>.280 /// </summary>281 /// <param name="cimError"></param>282 /// <returns></returns>283 internal static ErrorCategory ConvertCimErrorToErrorCategory(CimInstance cimError)284 {285 if (cimError == null)286 {287 return ErrorCategory.NotSpecified;288 }289 290 CimProperty errorCategoryProperty = cimError.CimInstanceProperties[@"Error_Category"];291 if (errorCategoryProperty == null)292 {293 return ErrorCategory.NotSpecified;294 }295 296 ErrorCategory errorCategoryValue;297 if (!LanguagePrimitives.TryConvertTo<ErrorCategory>(errorCategoryProperty.Value, CultureInfo.InvariantCulture, out errorCategoryValue))298 {299 return ErrorCategory.NotSpecified;300 }301 302 return errorCategoryValue;303 }304 305 #endregion306 }307 308 #endregion309 310 /// <summary>311 /// <para>312 /// Write error to pipeline313 /// </para>314 /// </summary>315 internal sealed class CimWriteError : CimSyncAction316 {317 /// <summary>318 /// Initializes a new instance of the <see cref="CimWriteError"/> class319 /// with the specified <see cref="CimInstance"/>.320 /// </summary>321 /// <param name="error"></param>322 public CimWriteError(CimInstance error, InvocationContext context)323 {324 this.Error = error;325 this.CimInvocationContext = context;326 }327 328 /// <summary>329 /// Initializes a new instance of the <see cref="CimWriteError"/> class330 /// with the specified <see cref="Exception"/>.331 /// </summary>332 /// <param name="exception"></param>333 public CimWriteError(Exception exception, InvocationContext context, CimResultContext cimResultContext)334 {335 this.Exception = exception;336 this.CimInvocationContext = context;337 this.ResultContext = cimResultContext;338 }339 340 /// <summary>341 /// <para>342 /// Write error to pipeline343 /// </para>344 /// </summary>345 /// <param name="cmdlet"></param>346 public override void Execute(CmdletOperationBase cmdlet)347 {348 Debug.Assert(cmdlet != null, "Caller should verify that cmdlet != null");349 try350 {351 Exception errorException = (Error != null) ? new CimException(Error) : this.Exception;352 353 // PS engine takes care of handling error action354 cmdlet.WriteError(ErrorToErrorRecord.ErrorRecordFromAnyException(this.CimInvocationContext, errorException, this.ResultContext));355 356 // if user wants to continue, we will get here357 this.responseType = CimResponseType.Yes;358 }359 catch360 {361 this.responseType = CimResponseType.NoToAll;362 throw;363 }364 finally365 {366 // unblocking the waiting thread367 this.OnComplete();368 }369 }370 371 #region members372 373 /// <summary>374 /// <para>375 /// Error instance376 /// </para>377 /// </summary>378 379 internal CimInstance Error { get; }380 381 /// <summary>382 /// <para>383 /// Exception object384 /// </para>385 /// </summary>386 internal Exception Exception { get; }387 388 internal InvocationContext CimInvocationContext { get; }389 390 internal CimResultContext ResultContext { get; }391 392 #endregion393 }394}395 