mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
321 lines
11 KiB
C#
321 lines
11 KiB
C#
/********************************************************************++
|
|
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
|
|
{
|
|
/// <summary>
|
|
/// RuntimeException is the base class for exceptions likely to occur
|
|
/// while a Monad command is running.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// 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.
|
|
/// </remarks>
|
|
[Serializable]
|
|
public class RuntimeException
|
|
: SystemException, IContainsErrorRecord
|
|
{
|
|
#region ctor
|
|
/// <summary>
|
|
/// Initializes a new instance of the RuntimeException class.
|
|
/// </summary>
|
|
/// <returns> constructed object </returns>
|
|
public RuntimeException()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
#region Serialization
|
|
/// <summary>
|
|
/// Initializes a new instance of the RuntimeException class
|
|
/// using data serialized via
|
|
/// <see cref="ISerializable"/>
|
|
/// </summary>
|
|
/// <param name="info"> serialization information </param>
|
|
/// <param name="context"> streaming context </param>
|
|
/// <returns> constructed object </returns>
|
|
protected RuntimeException(SerializationInfo info,
|
|
StreamingContext context)
|
|
: base(info, context)
|
|
{
|
|
_errorId = info.GetString("ErrorId");
|
|
_errorCategory = (ErrorCategory)info.GetInt32("ErrorCategory");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializer for <see cref="ISerializable"/>
|
|
/// </summary>
|
|
/// <param name="info"> serialization information </param>
|
|
/// <param name="context"> streaming context </param>
|
|
[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
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the RuntimeException class.
|
|
/// </summary>
|
|
/// <param name="message"> </param>
|
|
/// <returns> constructed object </returns>
|
|
public RuntimeException(string message)
|
|
: base(message)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the RuntimeException class.
|
|
/// </summary>
|
|
/// <param name="message"> </param>
|
|
/// <param name="innerException"> </param>
|
|
/// <returns> constructed object </returns>
|
|
public RuntimeException(string message,
|
|
Exception innerException)
|
|
: base(message, innerException)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the RuntimeException class
|
|
/// starting with an already populated error record.
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
/// <param name="innerException"></param>
|
|
/// <param name="errorRecord"></param>
|
|
/// <returns> constructed object </returns>
|
|
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.
|
|
/// <summary>
|
|
/// Additional information about the error
|
|
/// </summary>
|
|
/// <value></value>
|
|
/// <remarks>
|
|
/// Note that ErrorRecord.Exception is
|
|
/// <see cref="System.Management.Automation.ParentContainsErrorRecordException"/>.
|
|
/// </remarks>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="errorId">per ErrorRecord constructors</param>
|
|
internal void SetErrorId(string errorId)
|
|
{
|
|
if (_errorId != errorId)
|
|
{
|
|
_errorId = errorId;
|
|
_errorRecord = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="errorCategory">
|
|
/// per ErrorRecord.CategoryInfo.Category
|
|
/// </param>
|
|
internal void SetErrorCategory(ErrorCategory errorCategory)
|
|
{
|
|
if (_errorCategory != errorCategory)
|
|
{
|
|
_errorCategory = errorCategory;
|
|
_errorRecord = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Subclasses can use this method to set or update the TargetObject.
|
|
/// This convenience function doesn't clobber the error record if it
|
|
/// already exists...
|
|
/// </summary>
|
|
/// <param name="targetObject">
|
|
/// per ErrorRecord.TargetObject
|
|
/// </param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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
|