bin/projects/dbatools/dbatools/dbaSystem/DbatoolsException.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System;
using System.Collections;
using System.Collections.Generic;
using System.Management.Automation;
 
namespace Sqlcollaborative.Dbatools.dbaSystem
{
    /// <summary>
    /// Wrapper class that can emulate any exception for purpose of serialization without blowing up the storage space consumed
    /// </summary>
    [Serializable]
    public class DbatoolsException
    {
        private Exception _Exception;
        /// <summary>
        /// Returns the original exception object that we interpreted. This is on purpose not a property, as we want to avoid messing with serialization size.
        /// </summary>
        /// <returns>The original exception that got thrown</returns>
        public Exception GetException()
        {
            return _Exception;
        }
 
        #region Properties & Fields
        #region Wrapper around 'official' properties
        /// <summary>
        /// The actual Exception Message
        /// </summary>
        public string Message;
 
        /// <summary>
        /// The original source of the Exception
        /// </summary>
        public string Source;
 
        /// <summary>
        /// Where on the callstack did the exception occur?
        /// </summary>
        public string StackTrace;
 
        /// <summary>
        /// What was the target site on the code that caused it. This property has been altered to avoid export issues, if a string representation is not sufficient, access the original exception using GetException()
        /// </summary>
        public string TargetSite;
 
        /// <summary>
        /// The HResult of the exception. Useful in debugging native code errors.
        /// </summary>
        public int HResult;
 
        /// <summary>
        /// Link to a proper help article.
        /// </summary>
        public string HelpLink;
 
        /// <summary>
        /// Additional data that has been appended
        /// </summary>
        public IDictionary Data;
 
        /// <summary>
        /// The inner exception in a chain of exceptions.
        /// </summary>
        public DbatoolsException InnerException;
        #endregion Wrapper around 'official' properties
 
        #region Custom properties for exception abstraction
        /// <summary>
        /// The full namespace name of the exception that has been wrapped.
        /// </summary>
        public string ExceptionTypeName;
 
        /// <summary>
        /// Contains additional properties other exceptions might contain.
        /// </summary>
        public Hashtable ExceptionData = new Hashtable();
        #endregion Custom properties for exception abstraction
 
        #region ErrorRecord Data
        /// <summary>
        /// The category of the error
        /// </summary>
        public ErrorCategoryInfo CategoryInfo;
 
        /// <summary>
        /// The details on the error
        /// </summary>
        public ErrorDetails ErrorDetails;
 
        /// <summary>
        /// The specific error identity, used to identify the target
        /// </summary>
        public string FullyQualifiedErrorId;
 
        /// <summary>
        /// The details of how this was called.
        /// </summary>
        public object InvocationInfo;
 
        /// <summary>
        /// The script's stacktrace
        /// </summary>
        public string ScriptStackTrace;
 
        /// <summary>
        /// The object being processed
        /// </summary>
        public object TargetObject;
 
        /// <summary>
        /// The name of the function throwing the error
        /// </summary>
        public string FunctionName;
 
        /// <summary>
        /// When was the error thrown
        /// </summary>
        public DateTime Timestamp;
 
        /// <summary>
        /// The runspace the error occured on.
        /// </summary>
        public Guid Runspace;
        #endregion ErrRecord Data
        #endregion Properties & Fields
 
        #region Constructors
        /// <summary>
        /// Creates an empty exception object. Mostly for serialization support
        /// </summary>
        public DbatoolsException()
        {
 
        }
 
        /// <summary>
        /// Creates an exception based on an original exception object
        /// </summary>
        /// <param name="Except">The exception to wrap around</param>
        public DbatoolsException(Exception Except)
        {
            _Exception = Except;
 
            Message = Except.Message;
            Source = Except.Source;
            StackTrace = Except.StackTrace;
            try { TargetSite = Except.TargetSite.ToString(); }
            catch { }
            HResult = Except.HResult;
            HelpLink = Except.HelpLink;
            Data = Except.Data;
            if (Except.InnerException != null) { InnerException = new DbatoolsException(Except.InnerException); }
 
            ExceptionTypeName = Except.GetType().FullName;
 
            PSObject tempObject = new PSObject(Except);
            List<string> defaultPropertyNames = new List<string>();
            defaultPropertyNames.Add("Data");
            defaultPropertyNames.Add("HelpLink");
            defaultPropertyNames.Add("HResult");
            defaultPropertyNames.Add("InnerException");
            defaultPropertyNames.Add("Message");
            defaultPropertyNames.Add("Source");
            defaultPropertyNames.Add("StackTrace");
            defaultPropertyNames.Add("TargetSite");
 
            foreach (PSPropertyInfo member in tempObject.Properties)
            {
                if (!defaultPropertyNames.Contains(member.Name))
                    ExceptionData[member.Name] = member.Value;
            }
        }
 
        /// <summary>
        /// Creates a rich information exception object based on a full error record as recorded by PowerShell
        /// </summary>
        /// <param name="Record">The error record to copy from</param>
        public DbatoolsException(ErrorRecord Record)
            : this(Record.Exception)
        {
            CategoryInfo = Record.CategoryInfo;
            ErrorDetails = Record.ErrorDetails;
            FullyQualifiedErrorId = Record.FullyQualifiedErrorId;
            InvocationInfo = Record.InvocationInfo;
            ScriptStackTrace = Record.ScriptStackTrace;
            TargetObject = Record.TargetObject;
        }
 
        /// <summary>
        /// Creates a new exception object with rich meta information from the Dbatools runtime.
        /// </summary>
        /// <param name="Except">The exception thrown</param>
        /// <param name="FunctionName">The name of the function in which the error occured</param>
        /// <param name="Timestamp">When did the error occur</param>
        /// <param name="Message">The message to add to the exception</param>
        /// <param name="Runspace">The ID of the runspace from which the exception was thrown. Useful in multi-runspace scenarios.</param>
        public DbatoolsException(Exception Except, string FunctionName, DateTime Timestamp, string Message, Guid Runspace)
            : this(Except)
        {
            this.Runspace = Runspace;
            this.FunctionName = FunctionName;
            this.Timestamp = Timestamp;
            this.Message = Message;
        }
 
        /// <summary>
        /// Creates a new exception object with rich meta information from the Dbatools runtime.
        /// </summary>
        /// <param name="Record">The error record written</param>
        /// <param name="FunctionName">The name of the function in which the error occured</param>
        /// <param name="Timestamp">When did the error occur</param>
        /// <param name="Message">The message to add to the exception</param>
        /// <param name="Runspace">The ID of the runspace from which the exception was thrown. Useful in multi-runspace scenarios.</param>
        public DbatoolsException(ErrorRecord Record, string FunctionName, DateTime Timestamp, string Message, Guid Runspace)
            : this(Record)
        {
            this.Runspace = Runspace;
            this.FunctionName = FunctionName;
            this.Timestamp = Timestamp;
            this.Message = Message;
        }
        #endregion Constructors
 
        /// <summary>
        /// Returns a string representation of the exception.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Message;
        }
    }
}