here is the error I am getting :
System.ExecutionEngineException was unhandled
HResult=-2146233082
Message=Exception of type 'System.ExecutionEngineException' was thrown.
InnerException:
code Update:
here is my code
void WriteGraph(int[] vData)
{
string tempWrite = "";
try
{
for (int y = 0; y < vData.Length;)
{
for (int i = 0; i < 20; i++)
{
tempWrite = tempWrite + vData[i] + ",";
y++;
}
File.AppendAllText(name2, tempWrite);
}
File.AppendAllText(name2, Environment.NewLine);
}
catch ( Exception e)
{
AppendTextBox(e.Message.ToString());
}
}
it fails at tempWrite = tempWrite + vData[i] + ",".
not that is in a loop so it does write some values to the file.
I open the file in Excel and it goes from A to LW
before it died ...
the question is why ?
here is the loop :
void PlotSpectrum(int []vData)
{
ArrayList listDataSource = new ArrayList();
// Populate the list with records.
for (int i = 0; i < vData.Length; i++)
{
WriteGraph(Convert.ToString(vData[i]));
listDataSource.Add(new Graph_Class(i, vData[i]));
}
// Bind the chart to the list.
ChartControl myChart = chartControl1;
myChart.DataSource = listDataSource;
// Create a series, and add it to the chart.
Series series1 = new Series("Spectrum", ViewType.Line);
myChart.Series.Add(series1);
// Adjust the series data members.
series1.ArgumentDataMember = "X";
series1.ValueDataMembers.AddRange(new string[] { "Y" });
// Access the view-type-specific options of the series.
((LineSeriesView)series1.View).ColorEach = true;
series1.LegendTextPattern = "{A}";
try
{
//myChart.Update();
// myChart.Refresh();
}catch(Exception err)
{
AppendTextBox(err.Message.ToString());
print("Error in Graph: ", DateTime.Now.ToString(), err.Message.ToString());
}
}
The same thing is happening for me, but it only throws this exception when a yarn rebuild finishes (front-end is React). I am using IIS Express to run locally. I wonder if it doesn't like that the files are changing while the app is running.
This seems to fix it:
Go to Tools, Options, Projects and Solutions, Web Projects; and check "Use the 64 bit version of IIS Express for web sites and projects".
In my case this happened in Service Fabric startup before it has a chance to begin running. The exception shows up in the Event Viewer rather than VS.
This problem happens because something failed before throw ExecutionEngineException.
I faced this issue (typing Japanese characters in TextBox on WPF app), I solved activating Common Language Runtime Exceptions in Exceptions Settings in VS
and checking the values of each runtime exception(before get crash) and I found a null value in one of the variables in a previous method but the crash was thrown many seconds after that.
You can find a deep explanation here: Why this code throws System.ExecutionEngineException
Related
I am having trouble understanding stack traces in .net 4. I get different line numbers for identical code running in Console application or web service hosted on IIS 7.5 (both use .net 4).
Console application:
static void Main(string[] args)
{
try
{
var test = new List<int>() { 1, 2, 3 };
foreach (var root in test)
{
throw new Exception("foobar");
}
}
catch(Exception e)
{
throw;
}
}
When inspecting stack trace line number of "e" inside catch block, I get "8", which is what I excepted (the line of throw new Exception("foobar"))
Web service
[WebMethod]
public void Test()
{
try
{
var test = new List<int>() { 1, 2, 3 };
foreach (var root in test)
{
throw new Exception("foobar");
}
}
catch (Exception e)
{
throw;
}
}
This is where things get weird - when inspecting stack trace line number, I get "7", which is the start of foreach block. Same happens with classical for, but if statement for example work OK.
Any ideas?
EDIT:
Regarding answer from Machine Learning about misalignment between the ide or the runtime line and the pdb. If I add nonsensical lines before exception and some after, I still get similar behaviour. Example:
[WebMethod]
public string Test()
{
try
{
var test = new List<int>() { 1, 2, 3 };
var a = 1;
var b = 2;
var c = 3;
foreach (var root in test)
{
var d = 4;
var e = 5;
var f = 6;
throw new Exception("foobar" + (new System.Diagnostics.StackFrame(0, true)).GetFileLineNumber());
var g = 7;
}
return null;
}
catch (Exception e)
{
return e.Message + e.StackTrace;
}
}
Here e.StackTrace reports line "12" (foreach line) and e.Message reports line "17" which is correct.
This is the result of how exceptions are handled on Windows. Rethrowing the exception thrown within the same method means you lose information about the original exception, because the exceptions are method scoped [1]. Sadly, .NET inherited this limitation, since the only alternative was to implement exceptions without relying on the existing infrastructure.
If I recall correctly, this is fixed in 64-bit code - make sure your console application runs as 64-bit, and it should work as expected. This is most likely the reason why everything works fine in your test application, but not on your IIS (where the code is most likely running as 32-bit, and possibly with debug=false). EDIT: This actually doesn't seem to be the case. While bitness is involved, it most likely has to do with the optimizations the JITters do - a foreach on 64-bit reports the exception on the foreach line, while replacing the foreach with a using, GetEnumerator etc., or changing the bitness to 32-bit will report the exception on the rethrow.
If you want to avoid this problem in all code, make sure you never rethrow exceptions that were originally thrown in the same method. Extracting the throw new ... into a separate method (and ensuring it isn't inlined, which happens automatically when there's a throw on the current MS runtime AFAIK) should work fine. Don't forget that a foreach also contains an imlicit using, i.e. a finally clause.
[1] Needless to say, this is a bit of an oversimplification. The underlying (native) Structured Exception Handling only holds a single exception per stack frame - it can't keep track of both the original throw and the rethrow. You'll find plenty of information on how SEH works with a simple Google search if you're interested to go deeper :)
I am trying to localize my program but I would like error messages that are sent to the developers to appear in English. I haven't been able to find a way to make this happen since it seems that if the UI culture is set to another language when an error is thrown, it is thrown in that language. Since I did not write this program myself, and it is quite large, I think it would be impractical to go create new try catch blocks to try and set the culture back to english whenever an error occurs or might possibly occur. Currently the CurrentCulture and DefaultThreadCurrentCulture are always set to be English throughout the entire application, while the CurrentUICulture is set to the end user's language.
As I workaround, I currently have a function that has been iterating through a list of errors (using System.Resources.ResourceSets (which I assume are Windows errors, but I also need a way to find the .NET errors so I can iterate through those). It string replaces matching errors in other languages and replaces them with their English equivalents to build a large message of errors to be sent to the developers whenever the application crashes. Really, I don't have much to translate as most of the message is a server stack trace and showing where the exception was thrown. The biggest problem is translating the Inner Exception message and sometimes the main exception message since sometimes the errors thrown don't appear in the ResourceSet and sometimes use formatting items like '{0}'.
Here is the code I have so far to translate the remaining errors. I'm still working on adding regex patterns to translate errors that use things like '{0}', so if anyone has suggestions for that or better ways to do this I'd appreciate suggestions.
public static string TranslateExceptionMessageTest(string exmsg, Exception e, CultureInfo currentui)
{
CultureInfo test = Thread.CurrentThread.CurrentUICulture;
string matchingstr = "";
string newstr = exmsg;
string resourcecollection = "";
Assembly a = e.GetType().Assembly;
ResourceManager rm = new ResourceManager(a.GetName().Name, a);
ResourceSet rsOriginal = rm.GetResourceSet(currentui, true, true);
ResourceSet rsTranslated = rm.GetResourceSet(new CultureInfo("en-US"), true, true);
foreach (DictionaryEntry item in rsOriginal)
{
if (exmsg.Contains(item.Value.ToString()))
{
if (item.Key.ToString() == "Word_At") // sometimes with spanish errors this replaces words containing the letters 'en' with 'at'.
{
string newat = " " + item.Value.ToString() + " "; // this is the formatting the word 'at' appears with, in any culture I've tested.
matchingstr = " " + rsTranslated.GetString(item.Key.ToString(), false) + " ";
newstr = newstr.Replace(newat, matchingstr);
}
else
{
matchingstr = rsTranslated.GetString(item.Key.ToString(), false);
newstr = newstr.Replace(item.Value.ToString(), matchingstr);
}
}
resourcecollection = resourcecollection + Environment.NewLine + "Key: " + item.Key.ToString() + Environment.NewLine + "Value: " + item.Value.ToString();
}
return newstr; // success
}
I have also tried using the method posted here ( Exception messages in English? ) but without much luck. I still ended up with the same localized error messages. Here is the code where I know an error is being thrown but it doesn't seem like the catch block is doing anything to change the language. My ExceptionLogger class is set up the same way as in the Stackoverflow example with the addition of a line to write the error to a file. The error is being thrown at wcf.Client.Ping() (I don't care about the actual error. I'm using it to test).
private void PreloadWcfDlls(object state)
{
if (Global.Inst.ServerMode == ApplicationServerMode.Unknown)
return;
try
{
using (var wcf = ClientGrabber.GetSchemaClient(Global.Inst.ServerMode))
{
wcf.Client.Ping();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString()); //Will display localized message
ExceptionLogger el = new ExceptionLogger(ex);
System.Threading.Thread t = new System.Threading.Thread(el.DoLog);
t.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
t.Start();
}
}
If nothing else, is there a way I can get a list of all possible .NET Framework errors in English as well as in other languages? Is there a class I can access to get these from within my program or a list elsewhere? I've tried looking at sites like unlocalize.com and finderr.net but I really don't want to have to write something to crawl through all the pages to find every possible error.
Sorry if I'm completely missing something. I'm pretty new to C# and programming in general and this problem is driving me kind of crazy!
Edit: I forgot to add that I would prefer to avoid a solutions like these where you have to be constantly changing the CurrentUICulture:
Force exceptions language in English
Prevent exception messages from being translated into the user's language?
Or solutions where you delete language packs or something on the user's computer or just set the errors to be in English when debugging (these error logs will also be sent from an end users computer in the case that the application crashes and if they are using another language we need the errors logged in English).
Also, I know I could just google the error messages or use unlocalize.com or finderr.net to translate the messages but I think the other developers might kill me if they had to do that, hah. I guess if worse comes to worst I could query the unlocalize site? Seems like a real pain though.
Here you can find a solution for the problem. To make the long story short:
try
{
System.IO.StreamReader sr=new System.IO.StreamReader(#"c:\does-not-exist");
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString()); //Will display localized message
ExceptionLogger el = new ExceptionLogger(ex);
System.Threading.Thread t = new System.Threading.Thread(el.DoLog);
t.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
t.Start();
}
Where the ExceptionLogger class looks something like:
class ExceptionLogger
{
Exception _ex;
public ExceptionLogger(Exception ex)
{
_ex = ex;
}
public void DoLog()
{
Console.WriteLine(_ex.ToString()); //Will display en-US message
}
}
The exception framework loads the error messages based on culture of current thread.
So what you can do is, catch the exception and in catch block you can make your own logger object and set its culture according to your need.
try
{
//.....Code Goes Here
}
Catch (Exception ex)
{
var eh = new ExceptionHandler("Your-Culture");
//....code goes here
}
Public class ExceptionHandler
{
//code goes on
public ExceptionHandler(string culture)
{
//set your culture here
}
}
Try this:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
Environment:
Microsoft Visual Studio 2010 SP1
C# -- .NET 4.0
Problem:
Everything works fine, except the installation.
After much thought and research, I suspect that the problem is an attempted cast from -- “COM object of type 'System.__ComObject' to interface type 'WUApiLib.UpdateInstaller'.” As can be seen in the code, the IID and type have been set but the values of the parameters are suspect. The Following is the runtime error report:
System.InvalidCastException was caught. Message=Specified cast is not
valid. Source=PROGRAM_NAME StackTrace:
at WUApiLib.IUpdateInstaller.Install()
at PROGRAM_NAME.WindowsUpdates.InstallUpdates(UpdateCollection updatesToInstall) in %PATH%\visual studio 2010\Projects\ …
InnerException:
Request:
After many hours of research and study, any help to resolve the problem of installing the updates would be greatly appreciated. Please see the following code snippets.
Program attempts the following:
-- Windows update services are enabled (No problems)
-- That the host machine needs to be updated: (No problems)
-- Downloads the updates: (No problems)
public static UpdateCollection DownloadUpdates()
{
// Returns UpdateCollection object.
}
-- Attempts to install the updates. (Exception: Specified cast is not valid.)
public static void InstallUpdates(UpdateCollection updatesToInstall)
{
IUpdateInstaller updateInstaller;
Console.WriteLine("Creating UpdateInstasller...");
//Type itype = Type.GetTypeFromProgID("Microsoft.Update.Session", true);
//Type t = Type.GetTypeFromProgID("Microsoft.Update.Session", "127.0.0.1")
Type itype = Type.GetTypeFromProgID("Microsoft.Update.Installer", true);
updateInstaller = (UpdateInstaller)Activator.CreateInstance(itype);
updateInstaller.Updates = updatesToInstall;
updateInstaller.ClientApplicationID = "{3442D4FE-224D-4CEE-98CF-30E0C4D229E6}"; // Unsure of IID
IInstallationResult installationResult;
Console.WriteLine("Creating UpdateInstallationResult...");
updateInstaller.IsForced = true;
if (updateInstaller.IsBusy == false)
{
try
{
installationResult = updateInstaller.Install(); // ***Bad Cast exception here.***
if (updatesToInstall.Count > 0)
{
for (int i = 0; i < updatesToInstall.Count; i++)
{
if (installationResult.GetUpdateResult(i).HResult == 0)
Console.WriteLine("Installed : " + updatesToInstall[i].Title);
else
Console.WriteLine("Failed : " + updatesToInstall[i].Title);
// Is Reboot Required?
if (installationResult.RebootRequired == true)
Console.WriteLine("Reboot is required for one of more updates.");
} // end for
} // end if
} // end try
catch (Exception e)
{
Console.WriteLine("Error:: " + e.Message + "\n");
}
} // end if
} // end method
I want to get line number of code which cause error. For example;
static void Main(string[] args)
{
using (SqlConnection conn = new SqlConnection(bagcum))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
conn.Open();
int n = cmd.ExecuteNonQuery();
}
}
so As we know that code doesn't work, it will throw exception Line number of code which is:
int n = cmd.ExecuteNonQuery();
So how can get that line number of using try-catch? I tried using a StackTrace class but it gives line number as 0:
static void Main(string[] args)
{
try
{
using (SqlConnection conn = new SqlConnection(bagcum))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
conn.Open();
int n = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
}
}
OUTPUT:
Line:0
Update:
Usually error line of code is 22 so I have to get that number.
Thanks
Try this simple hack instead:
First Add this (extension) class to your namespace(most be toplevel class):
public static class ExceptionHelper
{
public static int LineNumber(this Exception e)
{
int linenum = 0;
try
{
//linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(":line") + 5));
//For Localized Visual Studio ... In other languages stack trace doesn't end with ":Line 12"
linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(' ')));
}
catch
{
//Stack trace is not available!
}
return linenum;
}
}
And its done!Use LineNumber method whenever you need it:
try
{
//Do your code here
}
catch (Exception e)
{
int linenum = e.LineNumber();
}
try this
To get the line numbers in the StackTrace, you need to have the correct debug information (PDB files) alongside your dlls/exes. To generate the the debug information, set the option in Project Properties -> Build -> Advanced -> Debug Info:
Setting it to full should suffice (see the MSDN docs for what the other options do). Debug info (ie. PDB files) are generated for Debug build configurations by default, but can also be generated for Release build configurations.
Generating PDBs for release builds enables you to ship you code without the PDBs, but to drop the PDBs next to the dlls if you need line numbers (or even to attach a remote debugger). One thing to note is that in a release build, the line numbers may not be entirely correct due to optimisations made by the compiler or the JIT compiler (this is especially so if the line numbers show as 0).
The problem is that you're trying to get the line number of the first frame of the exception:
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
However, the exception does not originate in the line you write ExecuteNonQuery, but somewhere within that function, possibly multiple stack frames (i.e. nested function calls) deeper. So the first frame (which you explicitly retrieve using GetFrame(0)) is somewhere inside Microsoft's code (most likely System.Data.dll) for which you don't have any debugging symbols.
Write out the complete exception stacktrace in your function to see what I mean:
try
{
// your code ...
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Short of parsing the stacktrace (i.e. ex.StackTrace) there is no reliable why to get the linenumber of the "ExecuteNonQuery()" invocation. I would especially not try to count the stackframes up the stack where your call to ExecuteNonQuery() happens.
I wonder however, what you need the sole linenumber for, why not just log/print/whatever the complete stacktrace instead. At least for diagnostics reasons that is much more useful anyway.
You might get 0 in result if you don't initialize StackTrace to include fileinfo.
Try this
try
{
//code
}
catch (Exception e)
{
var lineNumber = new System.Diagnostics.StackTrace(e, true).GetFrame(0).GetFileLineNumber();
}
This worked for me.
You can use the System.Diagnostics.StackTrace class as below:
public void MethodName()
{
try
{
throw new Exception();
}
catch (Exception ex)
{
// Get stack trace for the exception with source file information
var trace = new StackTrace(ex, true);
// Get the top stack frame
var frame = trace.GetFrame(0);
// Get the line number from the stack frame
var line = frame.GetFileLineNumber();
}
}
Here's a rather easy way to get a bunch of info from the Exception object: Just add code like this to any potentially exception-throwing methods:
catch (Exception ex)
{
String exDetail = String.Format(ExceptionFormatString, ex.Message, Environment.NewLine, ex.Source, ex.StackTrace);
MessageBox.Show(exDetail);
}
The information you get will often be more specific, especially as regards line numbers of where problems are occurring, than you would otherwise see.
You may have noted that the String.Format() uses a constant, namely "ExceptionFormatString". This is a good practice, so that if you want to change it, after adding the above code to 40-eleven methods, you can just change it one place. Anyway, here it is:
public static readonly String ExceptionFormatString = "Exception message: {0}{1}Exception Source: {2}{1}Exception StackTrace: {3}{1}";
Happy Debugging!
To get line numbers, you need your application to be in Debug mode or include the debug symbols in the same folder (the .pdb file) for line numbers to appear. You code as posted should then work.
the following code exception log handler method is works fine :
in catch :
catch (Exception ex)
{
CommonTools.vAddToLog(ex, EmpID, ErrorCodes.UnDefined);
Response.Redirect("~/ErrorPage.aspx");
}
in AddToLog method :
string _exMsgErr = string.Empty;
var frame = oStackTrace.FrameCount > 1 ? oStackTrace.GetFrame(1) : oStackTrace.GetFrame(0);
if (oException.GetType() == typeof(JOVALException))
{
JOVALException _JOVALEx = (JOVALException)oException;
_exMsgErr = _JOVALEx.Message;
}
else
{
_exMsgErr = oException.Message;
}
ErrorLog oError = new ErrorLog(frame.GetMethod().Name, (string)frame.GetFileName(), (int)frame.GetFileLineNumber(), sCustomErrorMessage == string.Empty ? _exMsgErr : sCustomErrorMessage, sUserID, oErrCode);
//Cont. your code of log file
Finally the xml log file looks like this :
<ErrorLog>
<MethodName>FillRolesDDLs</MethodName>
<FileName>
F:\Projects\ERP\ERP\Pages\SystemSettings\Roles.aspx.cs
</FileName>
<LineNumber>61</LineNumber>
<ErrorMesssage>
The given DataRow is not in the current DataRowCollection.
</ErrorMesssage>
<UserID>1</UserID>
<ErrCode>UnDefined</ErrCode>
<Time>15/03/2015 16:23:21.976</Time>
</ErrorLog>
In .NET 4.5 you can use the ExceptionDispatchInfo to rethrow your exceptions instead of the classic throw;(make sure the PDB files are there or no line numbers will be displayed):
static void A()
{
try
{
throw new Exception("A");
}
catch (Exception e)
{
ExceptionDispatchInfo.Capture(e).Throw();
}
}
Source: blogpost.
PDB files don't decrease performance on Windows.
Copy the entire stack trace in to a string or stringbuilder by using try/catch that can throw, see the below example
try
{
//Do some programming
}
catch(Exception ex)
{
//Catch the exception and assign the stack trace
StackTrace = ex;
}
The output will be
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Program.Run() in C:\Console Application1\Program.cs:line 37
at Program.Main(String[] args) in C:\Console Application1\Program.cs:line 45
The first line shows the type of the exception and the message. The second line shows the file, function and line number where the exception was thrown
I have been writing .NET applications and have been impressed with the error handling included in the framework.
When catching an error that has been throw by the processes or somewhere in the code I like to include the message (ex.Message, which is usually pretty general) but also the stacktrace (ex.stacktrace) which helps to trace the problem back to a specific spot.
For a simple example let's say for instance that we are recording numbers to a log in a method:
public void ExampleMethod(int number){
try{
int num = number
...open connection to file
...write number to file
}
catch(Exception ex){
.... deal with exception (ex.message,ex.stacktrace etc...)
}
finally{
...close file connection
}
}
Is there any way to see the method called (in this case ExampleMethod) with the specific number that was passed that potentially crashed the method call? I believe you could log this perhaps in the catch block but I am interested essentially in catching the method call and parameters that caused the system to throw the exception.
Any ideas?
I suggest stuffing the parameter values into the exception's Data dictionary, e.g.
public void ExampleMethod(int number) {
try {
int num = number
...open connection to file
...write number to file
}
catch(Exception ex) {
ex.Data["number"] = number;
//.... deal with exception (ex.message,ex.stacktrace etc...)
}
finally {
//...close file connection
}
Another advantage of this method is that you can stuff the parameters in the catch block, then re-throw the exception and log it somewhere else without losing the stack trace, e.g.
catch(Exception ex) {
ex.Data["number"] = number;
throw;
}
If you want to know the value of the parameters in your method, then there is only one way, IMO, to do it - you need to repackage the exception with data.
For example:
int param1 = 10;
string param2 = "Hello World";
try
{
SomeMethod(param1, param2)
}
catch(SomeExpectedException e)
{
throw new MyParameterSensitiveException(e, param1, param2);
}
You basically repackage the original exception as the inner exception of another exception, and additionally supply the parameters you used to call the method. Then you could inspect that in some way to figure out what went wrong.
The accepted answer and many of the solutions described will work fine but what you're doing is littering your source with a slightly different blob of code depending on what parameters are in your method signature.
When it comes time to add a new parameter you need to remember to update your handler to add that new parameter. Or if you remove a parameter then you need to remember to remove the parameter from your exception handler.
What if you have a two or more try..catch blocks? Then you now have two blocks of code to keep up to date. Definitely not refactor friendly.
Another approach is to remove the logging code use a technique called Aspect Oriented Programming.
One such tool to facilitate this is a product called PostSharp.
With PostSharp you can write a logger than is invoked whenever an exception is thrown without the need for messy method and parameter specific code. For example (using version 1.5 of PostSharp):
LoggerAttribute.cs -
[Serializable]
public class LoggerAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionEventArgs eventArgs)
{
Console.WriteLine(eventArgs.Method.DeclaringType.Name);
Console.WriteLine(eventArgs.Method.Name);
Console.WriteLine(eventArgs.Exception.StackTrace);
ParameterInfo[] parameterInfos = eventArgs.Method.GetParameters();
object[] paramValues = eventArgs.GetReadOnlyArgumentArray();
for (int i = 0; i < parameterInfos.Length; i++)
{
Console.WriteLine(parameterInfos[i].Name + "=" + paramValues[i]);
}
eventArgs.FlowBehavior = FlowBehavior.Default;
}
}
You then decorate your classes with the LoggerAttribute:
[Logger]
public class MyClass
{
public void MyMethod(int x, string name)
{
// Something that throws an exception
}
}
Anything that throws an exception in MyMethod will cause the OnException method to be executed.
There are two versions of PostSharp. Version 1.5 is free and open sourced under the GPL and is targeted at .NET 2.0. PostSharp 2.0 is not entirely free but its community edition will support the basic functionality described above.
In order to do this:
public void MyProblematicMethod(int id, string name)
{
try
{
object o = null;
int hash = o.GetHashCode(); // throws NullReferenceException
}
catch (Exception ex)
{
string errorMessage = SummarizeMethodCall(MethodBase.GetCurrentMethod(), id, name);
// TODO: do something with errorMessage
}
}
...and get this:
"MyProblematicMethod invoked: id = 1, name = Charlie"
...you could do something like this:
public static string SummarizeMethodCall(MethodBase method, params object[] values)
{
var output = new StringBuilder(method.Name + " invoked: ");
ParameterInfo[] parameters = method.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
output.AppendFormat("{0} = {1}",
parameters[i].Name,
i >= values.Length ? "<empty>" : values[i]
);
if (i < parameters.Length - 1)
output.Append(", ");
}
return output.ToString();
}
You could make a class that inherits Exception and add some arguments to it so you could pass the number to it.
You can get the method name and the parameters like this,
try
{
int a = 0;
int i = 1 / a;
}
catch (Exception exception)
{
StackTrace s = new StackTrace(exception);
StackFrame stackFrame = s.GetFrame(s.FrameCount - 1);
if (stackFrame != null)
{
StringBuilder stackBuilder = new StringBuilder();
MethodBase method = stackFrame.GetMethod();
stackBuilder.AppendFormat("Method Name = {0}{1}Parameters:{1}", method.Name, Environment.NewLine);
foreach (ParameterInfo parameter in method.GetParameters())
{
stackBuilder.AppendFormat("{0} {1}", parameter.ParameterType.FullName, parameter.Name);
stackBuilder.AppendLine();
}
// or use this to get the value
//stackBuilder.AppendLine("param1 = " + param1);
//stackBuilder.AppendLine("param2 = " + param2);
}
}
I am not sure whether you can get the parameter values directly off the stack like a debugger.
The Automatic Exception Handling from Crypto Obfuscator can do what you need.
The exception reports include all pertinent information including full stack trace info along with the values of all method arguments and local variables, plus the system information, the time of the exception, the build number, and optional developer defined custom data like log files, screenshots, etc.
DISCLAIMER: I work for LogicNP Software, the developer of Crypto Obfuscator.