/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Management.Automation.Language;
using System.Runtime.Serialization;
#if !CORECLR
using System.Security.Permissions;
#else
// Use stub for SerializableAttribute, SecurityPermissionAttribute and ISerializable related types.
using Microsoft.PowerShell.CoreClr.Stubs;
#endif
namespace System.Management.Automation
{
///
/// RuntimeException is the base class for exceptions likely to occur
/// while a Monad command is running.
///
///
/// Monad scripts can trap RuntimeException using the
/// "trap (exceptionclass) {handler}" script construct.
///
/// Instances of this exception class are usually generated by the
/// Monad Engine. It is unusual for code outside the Monad Engine
/// to create an instance of this class.
///
[Serializable]
public class RuntimeException
: SystemException, IContainsErrorRecord
{
#region ctor
///
/// Initializes a new instance of the RuntimeException class.
///
/// constructed object
public RuntimeException()
: base()
{
}
#region Serialization
///
/// Initializes a new instance of the RuntimeException class
/// using data serialized via
///
///
/// serialization information
/// streaming context
/// constructed object
protected RuntimeException(SerializationInfo info,
StreamingContext context)
: base(info, context)
{
_errorId = info.GetString("ErrorId");
_errorCategory = (ErrorCategory)info.GetInt32("ErrorCategory");
}
///
/// Serializer for
///
/// serialization information
/// streaming context
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new PSArgumentNullException("info");
}
base.GetObjectData(info, context);
info.AddValue("ErrorId", _errorId);
info.AddValue("ErrorCategory", (Int32)_errorCategory);
}
#endregion Serialization
///
/// Initializes a new instance of the RuntimeException class.
///
///
/// constructed object
public RuntimeException(string message)
: base(message)
{
}
///
/// Initializes a new instance of the RuntimeException class.
///
///
///
/// constructed object
public RuntimeException(string message,
Exception innerException)
: base(message, innerException)
{
}
///
/// Initializes a new instance of the RuntimeException class
/// starting with an already populated error record.
///
///
///
///
/// constructed object
public RuntimeException(string message,
Exception innerException,
ErrorRecord errorRecord)
: base(message, innerException)
{
_errorRecord = errorRecord;
}
internal RuntimeException(ErrorCategory errorCategory,
InvocationInfo invocationInfo,
IScriptExtent errorPosition,
string errorIdAndResourceId,
string message,
Exception innerException)
: base(message, innerException)
{
SetErrorCategory(errorCategory);
SetErrorId(errorIdAndResourceId);
if ((errorPosition == null) && (invocationInfo != null))
{
errorPosition = invocationInfo.ScriptPosition;
}
if (invocationInfo == null) return;
_errorRecord = new ErrorRecord(
new ParentContainsErrorRecordException(this),
_errorId,
_errorCategory,
_targetObject);
_errorRecord.SetInvocationInfo(new InvocationInfo(invocationInfo.MyCommand, errorPosition));
}
#endregion ctor
#region ErrorRecord
// If RuntimeException subclasses need to do more than change
// the ErrorId, ErrorCategory and TargetObject, they can access
// the ErrorRecord property and make changes directly. However,
// not that calling SetErrorId, SetErrorCategory or SetTargetObject
// will clean the cached ErrorRecord and erase any other changes,
// so the ErrorId etc. should be set first.
///
/// Additional information about the error
///
///
///
/// Note that ErrorRecord.Exception is
/// .
///
public virtual ErrorRecord ErrorRecord
{
get
{
if (null == _errorRecord)
{
_errorRecord = new ErrorRecord(
new ParentContainsErrorRecordException(this),
_errorId,
_errorCategory,
_targetObject);
}
return _errorRecord;
}
}
private ErrorRecord _errorRecord;
private string _errorId = "RuntimeException";
private ErrorCategory _errorCategory = ErrorCategory.NotSpecified;
private object _targetObject = null;
///
/// Subclasses can use this method to set the ErrorId.
/// Note that this will clear the cached ErrorRecord, so be sure
/// to change this before writing to ErrorRecord.ErrorDetails
/// or the like.
///
/// per ErrorRecord constructors
internal void SetErrorId(string errorId)
{
if (_errorId != errorId)
{
_errorId = errorId;
_errorRecord = null;
}
}
///
/// Subclasses can use this method to set the ErrorCategory.
/// Note that this will clear the cached ErrorRecord, so be sure
/// to change this before writing to ErrorRecord.ErrorDetails
/// or the like.
///
///
/// per ErrorRecord.CategoryInfo.Category
///
internal void SetErrorCategory(ErrorCategory errorCategory)
{
if (_errorCategory != errorCategory)
{
_errorCategory = errorCategory;
_errorRecord = null;
}
}
///
/// Subclasses can use this method to set or update the TargetObject.
/// This convenience function doesn't clobber the error record if it
/// already exists...
///
///
/// per ErrorRecord.TargetObject
///
internal void SetTargetObject(object targetObject)
{
_targetObject = targetObject;
if (_errorRecord != null)
_errorRecord.SetTargetObject(targetObject);
}
#endregion ErrorRecord
#region Internal
internal static string RetrieveMessage(ErrorRecord errorRecord)
{
if (null == errorRecord)
return "";
if (null != errorRecord.ErrorDetails &&
!String.IsNullOrEmpty(errorRecord.ErrorDetails.Message))
{
return errorRecord.ErrorDetails.Message;
}
if (null == errorRecord.Exception)
return "";
return errorRecord.Exception.Message;
}
internal static string RetrieveMessage(Exception e)
{
if (null == e)
return "";
IContainsErrorRecord icer = e as IContainsErrorRecord;
if (null == icer)
return e.Message;
ErrorRecord er = icer.ErrorRecord;
if (null == er)
return e.Message;
ErrorDetails ed = er.ErrorDetails;
if (null == ed)
return e.Message;
string detailsMessage = ed.Message;
return (String.IsNullOrEmpty(detailsMessage)) ? e.Message : detailsMessage;
}
internal static Exception RetrieveException(ErrorRecord errorRecord)
{
if (null == errorRecord)
return null;
return errorRecord.Exception;
}
///
///
///
public bool WasThrownFromThrowStatement
{
get { return _thrownByThrowStatement; }
set
{
_thrownByThrowStatement = value;
if (_errorRecord != null)
{
RuntimeException exception = _errorRecord.Exception as RuntimeException;
if (exception != null)
{
exception.WasThrownFromThrowStatement = value;
}
}
}
}
private bool _thrownByThrowStatement;
///
/// fix for BUG: Windows Out Of Band Releases: 906263 and 906264
/// The interpreter prompt CommandBaseStrings:InquireHalt
/// should be suppressed when this flag is set. This will be set
/// when this prompt has already occurred and Break was chosen,
/// or for ActionPreferenceStopException in all cases.
///
internal bool SuppressPromptInInterpreter
{
get { return _suppressPromptInInterpreter; }
set { _suppressPromptInInterpreter = value; }
}
private bool _suppressPromptInInterpreter;
#endregion Internal
private Token _errorToken;
internal Token ErrorToken
{
get
{
return _errorToken;
}
set
{
_errorToken = value;
}
}
} // RuntimeException
} // System.Management.Automation