// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #region Using directives using System; using System.Diagnostics; using System.Globalization; using System.Management.Automation; using Microsoft.Management.Infrastructure.Options; #endregion namespace Microsoft.Management.Infrastructure.CimCmdlets { #region class ErrorToErrorRecord /// /// /// Convert error or exception to /// /// internal sealed class ErrorToErrorRecord { /// /// /// Convert ErrorRecord from exception object, /// can be either or general . /// /// /// /// The context starting the operation, which generated the error. /// The CimResultContext used to provide ErrorSource, etc. info. /// internal static ErrorRecord ErrorRecordFromAnyException( InvocationContext context, Exception inner, CimResultContext cimResultContext) { Debug.Assert(inner != null, "Caller should verify inner != null"); CimException cimException = inner as CimException; if (cimException != null) { return CreateFromCimException(context, cimException, cimResultContext); } var containsErrorRecord = inner as IContainsErrorRecord; if (containsErrorRecord != null) { return InitializeErrorRecord(context, exception: inner, errorId: "CimCmdlet_" + containsErrorRecord.ErrorRecord.FullyQualifiedErrorId, errorCategory: containsErrorRecord.ErrorRecord.CategoryInfo.Category, cimResultContext: cimResultContext); } else { return InitializeErrorRecord(context, exception: inner, errorId: "CimCmdlet_" + inner.GetType().Name, errorCategory: ErrorCategory.NotSpecified, cimResultContext: cimResultContext); } } #region Helper functions /// /// Create from object. /// /// /// /// The CimResultContext used to provide ErrorSource, etc. info. /// internal static ErrorRecord CreateFromCimException( InvocationContext context, CimException cimException, CimResultContext cimResultContext) { Debug.Assert(cimException != null, "Caller should verify cimException != null"); return InitializeErrorRecord(context, cimException, cimResultContext); } /// /// Create from object. /// /// /// /// /// /// The CimResultContext used to provide ErrorSource, etc. info. /// internal static ErrorRecord InitializeErrorRecord( InvocationContext context, Exception exception, string errorId, ErrorCategory errorCategory, CimResultContext cimResultContext) { return InitializeErrorRecordCore( context, exception: exception, errorId: errorId, errorCategory: errorCategory, cimResultContext: cimResultContext); } /// /// Create from object. /// /// /// /// The CimResultContext used to provide ErrorSource, etc. info. /// internal static ErrorRecord InitializeErrorRecord( InvocationContext context, CimException cimException, CimResultContext cimResultContext) { ErrorRecord errorRecord = InitializeErrorRecordCore( context, exception: cimException, errorId: cimException.MessageId ?? "MiClientApiError_" + cimException.NativeErrorCode, errorCategory: ConvertCimExceptionToErrorCategory(cimException), cimResultContext: cimResultContext); if (cimException.ErrorData != null) { errorRecord.CategoryInfo.TargetName = cimException.ErrorSource; } return errorRecord; } /// /// Create from object. /// /// /// /// /// /// The CimResultContext used to provide ErrorSource, etc. info. /// internal static ErrorRecord InitializeErrorRecordCore( InvocationContext context, Exception exception, string errorId, ErrorCategory errorCategory, CimResultContext cimResultContext) { object theTargetObject = null; if (cimResultContext != null) { theTargetObject = cimResultContext.ErrorSource; } if (theTargetObject == null) { if (context != null) { if (context.TargetCimInstance != null) { theTargetObject = context.TargetCimInstance; } } } ErrorRecord coreErrorRecord = new ErrorRecord( exception: exception, errorId: errorId, errorCategory: errorCategory, targetObject: theTargetObject); if (context == null) { return coreErrorRecord; } System.Management.Automation.Remoting.OriginInfo originInfo = new System.Management.Automation.Remoting.OriginInfo( context.ComputerName, Guid.Empty); ErrorRecord errorRecord = new System.Management.Automation.Runspaces.RemotingErrorRecord( coreErrorRecord, originInfo); DebugHelper.WriteLogEx("Created RemotingErrorRecord.", 0); return errorRecord; } /// /// Convert to . /// /// /// internal static ErrorCategory ConvertCimExceptionToErrorCategory(CimException cimException) { ErrorCategory result = ErrorCategory.NotSpecified; if (cimException.ErrorData != null) { result = ConvertCimErrorToErrorCategory(cimException.ErrorData); } if (result == ErrorCategory.NotSpecified) { result = ConvertCimNativeErrorCodeToErrorCategory(cimException.NativeErrorCode); } return result; } /// /// Convert to . /// /// /// internal static ErrorCategory ConvertCimNativeErrorCodeToErrorCategory(NativeErrorCode nativeErrorCode) { switch (nativeErrorCode) { case NativeErrorCode.Failed: return ErrorCategory.NotSpecified; case NativeErrorCode.AccessDenied: return ErrorCategory.PermissionDenied; case NativeErrorCode.InvalidNamespace: return ErrorCategory.MetadataError; case NativeErrorCode.InvalidParameter: return ErrorCategory.InvalidArgument; case NativeErrorCode.InvalidClass: return ErrorCategory.MetadataError; case NativeErrorCode.NotFound: return ErrorCategory.ObjectNotFound; case NativeErrorCode.NotSupported: return ErrorCategory.NotImplemented; case NativeErrorCode.ClassHasChildren: return ErrorCategory.MetadataError; case NativeErrorCode.ClassHasInstances: return ErrorCategory.MetadataError; case NativeErrorCode.InvalidSuperClass: return ErrorCategory.MetadataError; case NativeErrorCode.AlreadyExists: return ErrorCategory.ResourceExists; case NativeErrorCode.NoSuchProperty: return ErrorCategory.MetadataError; case NativeErrorCode.TypeMismatch: return ErrorCategory.InvalidType; case NativeErrorCode.QueryLanguageNotSupported: return ErrorCategory.NotImplemented; case NativeErrorCode.InvalidQuery: return ErrorCategory.InvalidArgument; case NativeErrorCode.MethodNotAvailable: return ErrorCategory.MetadataError; case NativeErrorCode.MethodNotFound: return ErrorCategory.MetadataError; case NativeErrorCode.NamespaceNotEmpty: return ErrorCategory.MetadataError; case NativeErrorCode.InvalidEnumerationContext: return ErrorCategory.MetadataError; case NativeErrorCode.InvalidOperationTimeout: return ErrorCategory.InvalidArgument; case NativeErrorCode.PullHasBeenAbandoned: return ErrorCategory.OperationStopped; case NativeErrorCode.PullCannotBeAbandoned: return ErrorCategory.CloseError; case NativeErrorCode.FilteredEnumerationNotSupported: return ErrorCategory.NotImplemented; case NativeErrorCode.ContinuationOnErrorNotSupported: return ErrorCategory.NotImplemented; case NativeErrorCode.ServerLimitsExceeded: return ErrorCategory.ResourceBusy; case NativeErrorCode.ServerIsShuttingDown: return ErrorCategory.ResourceUnavailable; default: return ErrorCategory.NotSpecified; } } /// /// Convert to . /// /// /// internal static ErrorCategory ConvertCimErrorToErrorCategory(CimInstance cimError) { if (cimError == null) { return ErrorCategory.NotSpecified; } CimProperty errorCategoryProperty = cimError.CimInstanceProperties[@"Error_Category"]; if (errorCategoryProperty == null) { return ErrorCategory.NotSpecified; } ErrorCategory errorCategoryValue; if (!LanguagePrimitives.TryConvertTo(errorCategoryProperty.Value, CultureInfo.InvariantCulture, out errorCategoryValue)) { return ErrorCategory.NotSpecified; } return errorCategoryValue; } #endregion } #endregion /// /// /// Write error to pipeline /// /// internal sealed class CimWriteError : CimSyncAction { /// /// Constructor with an error. /// /// public CimWriteError(CimInstance error, InvocationContext context) { this.error = error; this.invocationContext = context; } /// /// Construct with an exception object. /// /// public CimWriteError(Exception exception, InvocationContext context, CimResultContext cimResultContext) { this.exception = exception; this.invocationContext = context; this.cimResultContext = cimResultContext; } /// /// /// Write error to pipeline /// /// /// public override void Execute(CmdletOperationBase cmdlet) { Debug.Assert(cmdlet != null, "Caller should verify that cmdlet != null"); try { Exception errorException = (error != null) ? new CimException(error) : this.Exception; // PS engine takes care of handling error action cmdlet.WriteError(ErrorToErrorRecord.ErrorRecordFromAnyException(this.invocationContext, errorException, this.cimResultContext)); // if user wants to continue, we will get here this.responseType = CimResponseType.Yes; } catch { this.responseType = CimResponseType.NoToAll; throw; } finally { // unblocking the waiting thread this.OnComplete(); } } #region members /// /// /// Error instance /// /// private CimInstance error; internal CimInstance Error { get { return error; } } /// /// /// Exception object /// /// internal Exception Exception { get { return exception; } } private Exception exception; /// /// /// object that contains /// the information while issuing the current operation /// /// private InvocationContext invocationContext; internal InvocationContext CimInvocationContext { get { return invocationContext; } } /// /// /// private CimResultContext cimResultContext; internal CimResultContext ResultContext { get { return cimResultContext; } } #endregion } }