I want to have a custom error page that displays some error information, but not the stack trace.
I would like for it to display the information for the offending page and the line number.
The default SERVER ERROR IN APPLICATION page shows the url/line number and surrounding code/stack trace.
I just want the url/line number to appear somewhere inside a prettier custom error page. That way our code isn't exposed when an error is thrown, but I can still find the error quickly by url/line number.
I already have custom error pages turned on. I just want to add additional information to them.
I'm using C#.NET 4.0 and webforms.
This is a question I have had for a while and for the longest time though it was not possible, so I did some research and found a solution. You need to use the StackFrame object from the System.Diagnostics namespace. I just put together an example and it appears to have worked.
try
{
int a = 10;
int b = 0;
litDebug.Text = (a / b).ToString();
}
catch (Exception ex)
{
StackTrace st = new StackTrace(ex, true);
StackFrame sf = st.GetFrame(0);
litDebug.Text = "" +
"<br />File Name: " + sf.GetFileName() +
"<br />Method Name: " + sf.GetMethod().Name +
"<br />Error Line Number: " + sf.GetFileLineNumber() +
"<br />Error Column Number: " + sf.GetFileColumnNumber();
}
The page output is:
File Name: c:\inetpub\www.website.com\dev\error.aspx.cs
Method Name: Page_Load
Error Line Number: 17
Error Column Number: 4
The only questionable item is the Error Column Number - everything else matches up perfectly.
Related
I have a logging system set up in my C# WinForms project that writes to a log txt file. A typical error message looks like this:
Error :
8:34:48 AM Tuesday, April 21, 2020
:
:System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.ArrayList.get_Item(Int32 index)
at System.Windows.Forms.DataGridViewColumnCollection.get_Item(Int32 index)
at CrossReferenceTool.frmXRefTool.DefineControlsLayout() in <PathToSourceCsFile>:line 306
Is there any way to grab parts of that error message? Specifically, I'd like to pull the offending method (DefineControlsLayout() in this case) and the line number.
Instantiate a new StackTrace and go log the details from that after any exception occurs.
Original link I used: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stacktrace.getframe?view=netframework-4.8
Example code
using System.Diagnostics;
try
{
throw new Exception("Fail");
}
catch (Exception e)
{
StackTrace st = new StackTrace(e);
// Display the most recent function call.
StackFrame sf = st.GetFrame(0);
Console.WriteLine();
Console.WriteLine(" Exception in method: ");
Console.WriteLine(" {0}", sf.GetMethod());
if (st.FrameCount > 1)
{
// Display the highest-level function call
// in the trace.
sf = st.GetFrame(st.FrameCount - 1);
Console.WriteLine(" Original function call at top of call stack):");
Console.WriteLine(" {0}", sf.GetMethod());
// will only work if .pdb is included
var lineNumber = sf.GetFileLineNumber();
var fileName = sf.GetFileName();
}
}
If you are already catching an Exception type then you have sub properties such as
Exception.StackTrace
Exception.TargetSite
I don't think that you can use them to pull the line of code though.
I have a program that dynamically runs user entered C# code, that part works fine and the results are outputted to a location given by the user (or a system default).
My users are asking that I output the results to an "output window" so they can view the results without having to go to file.
I am trying to reference the program the dynamically created C# code is being generated in so I can output the results, but I am getting a file not found error when trying to add the reference for the program that it is being run in.
Here is my code:
private static Assembly CompileSourceCodeDom(string sourceCode)
{
CodeDomProvider cpd = new CSharpCodeProvider();
var cp = new CompilerParameters();
LogConsoleMessage(Assembly.GetExecutingAssembly().CodeBase + "\n");
cp.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().CodeBase);
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.GenerateExecutable = false;
CompilerResults cr = cpd.CompileAssemblyFromSource(cp, sourceCode);
cr.Errors.Cast<CompilerError>().ToList().ForEach(error =>
LogConsoleMessage(error.ErrorText + " Line #: " + error.Line + " Column:
" + error.Column + "\n"));
if (cr.Errors.Count == 0)
{
return cr.CompiledAssembly;
}
else
{
return null;
}
}
This is the line where the error is being displayed
cr.Errors.Cast<ComplierErrors>().ToList().ForEach(error =>
LogConsoleMessage(error.ErrorText + " Line #: " + error.Line + " Column:
" + error.Column + "\n")); is where the error message is coming out
Here is the exact error message. I checked the folder and it does exists.
Metadata file 'file:///C:/Users/[my user]/source/repos/test/test/bin/Debug/test.exe' could not be found Line #: 0 Column: 0
Does this have to do with the fact that the program is currently running? Because I cannot seem to find a way to reference this code. Does anyone have any suggestions about a different way to output the results to a visible location?
Thanks in advance!
EDIT
Assembly.GetExecutingAssembly().CodeBase
was changed to
Assembly.GetExecutingAssembly().Location
Assembly.CodeBase returns the assembly location formatted as an URI like file://... which the compiler is apparently not able to parse.
Instead, try using the "pure" local or UNC path of your assembly. To get the local or UNC path of the assembly, replace CodeBase with the Location property:
LogConsoleMessage(Assembly.GetExecutingAssembly().Location + "\n");
cp.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
Hi I've coded my MVC c# application and it's all fine, however there does seem to be a few bugs. This being one of my first applications, I'm not surprised.
The application though is internal and so I do get good feedback from the users.
They do give me the screens shots 'Server Error in ........ Application'
This gives me the controller action which does help narrow down the error.
However how do I turn the +number at end of the line to an actual line number.
I'm aware that this is some sort of byte offset, but getting a rough idea of the line number would be helpful. Is there a plugin or something I can use?
Or is there another way to handle these. I've got a Base controller that all the controllers extend from - I've seen some things that say you can use this to write to a file to give you information about the error. If I made it a generic file (similar to the php error file) then that would help me with any application I make.
You can handle server errors in Global.asax inside Application_Error() method. Create a well designed error page and save it somewhere inside your project. In global asax create a method and put error handling code inside it. See below for example code.
protected void Application_Error()
{
if (httpContext.AllErrors != null)
{
// you can handle message
var message = HttpUtility.HtmlEncode(httpContext.AllErrors[0]);
//you can redirect ugly server error page to the one you created
httpContext.Response.Redirect($"~/Error/Global");
}
}
Just developing on what hhh's answer here.
This is what I've got at the end.
protected void Application_Error()
{
if (this.Context.AllErrors != null)
{
var p = Path.Combine(Server.MapPath("~"), "Errors.log");
var message = DateTime.Now.ToString();
message = message + " " + this.Context.User.Identity.Name;
message = message + " " + this.Context.Request.Url;
message = message + Environment.NewLine;
message = message + "Post";
message = message + Environment.NewLine;
string[] keys = this.Context.Request.Form.AllKeys;
for (int i = 0; i < keys.Length; i++)
{
message = message+keys[i] + ":" + this.Context.Request.Form[keys[i]];
message = message + Environment.NewLine;
}
message = message + Environment.NewLine;
// you can handle message
message = message+ HttpUtility.HtmlEncode(this.Context.AllErrors[0]);
message = message + Environment.NewLine;
message = message + "----------------------------------";
message = message + Environment.NewLine;
System.IO.File.AppendAllText(p, message);
//you can redirect ugly server error page to the one you created
}
}
Basically giving you a file with all the key variables in the there.
Feel free to modify as you wish.
I am having some trouble with this error in Visual Studio:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'C:\Users\aheij\Desktop\KinectOutput\swipe.txt' because it is being used by another process.
What I Have tried:
I have tried using these codes obtained from other solved StackOverflow questions similar to mine to try to solve the problem - but even that didn't seem to work?
Ive tried checking if the file is in use, but with no success.
I also run Visual Studio as administrator.
The file is not read-only.
The folder is not open, and the file is not being used in any other program when executing the code - at least not that I can see/know of.
The code:
So, to add some context to my code: I am writing some quick gesture detection code to the Kinect c# BodyBasics SDK v2 code freely available. This is a helper method that I added, that gets called in when a person is in view. If that person is executing the gesture, the method writes the frame time and gesture name to a text file.
Half the time, when the code does work, the gesture recognition works well. However, the other half of the time, the code breaks/stops because the writing to file bit causes the error.
Below is my code to see if the person is standing in the neutral position - its a bit waffly, so apologies about that. I have commented 'ERROR' where the error is (unsurprisingly):
private void Neutral_stance(VisualStyleElement.Tab.Body body, IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, BodyFrame bf)
{
CameraSpacePoint left_hand = joints[JointType.HandLeft].Position;
CameraSpacePoint left_elbow = joints[JointType.ElbowLeft].Position;
CameraSpacePoint left_shoulder = joints[JointType.ShoulderLeft].Position;
CameraSpacePoint left_hip = joints[JointType.HipLeft].Position;
CameraSpacePoint right_hand = joints[JointType.HandRight].Position;
CameraSpacePoint right_elbow = joints[JointType.ElbowRight].Position;
CameraSpacePoint right_shoulder = joints[JointType.ShoulderRight].Position;
CameraSpacePoint right_hip = joints[JointType.HipRight].Position;
double vertical_error = 0.15;
double shoulderhand_xrange_l = Math.Abs(left_hand.X - left_shoulder.X);
double shoulderhand_xrange_r = Math.Abs(right_hand.X - right_shoulder.X);
if (bf != null)
{
TimeSpan frametime = bf.RelativeTime;
string path_p = #"C:\Users\aheij\Desktop\KinectOutput\Punch.txt"; //write to punch file
string path_s = #"C:\Users\aheij\Desktop\KinectOutput\swipe.txt"; //write to swipe file
if (left_hand.Y < left_elbow.Y)
{
if (right_hand.Y < right_elbow.Y)
{
if (shoulderhand_xrange_l < vertical_error)
{
if (shoulderhand_xrange_r < vertical_error)
{
Gesture_being_done.Text = " Neutral";
File.AppendAllText(path_p, frametime.ToString() + " Neutral" + Environment.NewLine); //ERROR
File.AppendAllText(path_s, frametime.ToString() + " Neutral" + Environment.NewLine); //ERROR
}
}
}
}
else
{
Gesture_being_done.Text = " Unknown";
File.AppendAllText(path_p, frametime.ToString() + " Unknown" + Environment.NewLine); //ERROR
File.AppendAllText(path_s, frametime.ToString() + " Unknown" + Environment.NewLine); //ERROR
}
}
}
Any solutions/ideas/suggestions to point me on the right track would be appreciated. I think that it would be good to use the 'using streamwriter' method as opposed to the method I am using here - but I am not sure how? Any help would be appreciated.
Additonal Info: Using Visual Studio 2015; Using windows 10.
Sidenote: I read somewhere that the Windows Search tool in Windows 10 can interfere and cause problems like this so I need to disable it?
As suggested to me I used the Filestream method & ensured the file was closed after use. But, even this still caused the same error.
Thus, I also got rid of having two file-writing actions in rapid succession of each other. I dont know if this is technically right or even true, but based off of this post here: link, my error could be coming up because I am trying to execute the second 'write to text file' line whilst the previous 'write to text file' line is still executing/writing to that same folder & location - hence the clash? Please someone, correct me if I am wrong.
Either way, this seems to have worked.
See below for my edited/corrected method:
private void Neutral_stance(Body body, IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, BodyFrame bf)
{
//cameraspace point joint stuff here again (see original post for this bit leading up to the if statements.)
if (bf != null)
{
TimeSpan frametime = bf.RelativeTime;
string path_s = #"C:\Users\aheij\Desktop\KinectOutput\swipe.txt";
if (left_hand.Y < left_elbow.Y)
{
if (right_hand.Y < right_elbow.Y)
{
if (shoulderhand_xrange_l < vertical_error)
{
if (shoulderhand_xrange_r < vertical_error)
{
Gesture_being_done.Text = " Neutral";
FileStream fs_s = new FileStream(path_s, FileMode.Append); //swipe
byte[] bdatas = Encoding.Default.GetBytes(frametime.ToString() + " Neutral" + Environment.NewLine);
fs_s.Write(bdatas, 0, bdatas.Length);
fs_s.Close();
}
}
}
}
else
{
Gesture_being_done.Text = " Unknown";
FileStream fs_s = new FileStream(path_s, FileMode.Append);
byte[] bdatas = Encoding.Default.GetBytes(frametime.ToString() + " Unknown" + Environment.NewLine);
fs_s.Write(bdatas, 0, bdatas.Length);
fs_s.Close();
}
}
}
Do let me know if there is any way I can make this more elegant or anything else I should be aware of w.r.t this answer.
The code is based off of the code found here: FileStream Tutorial website
I have an application that runs from a batch file using parameters in said file to pull PDF email attachments from an email inbox. It takes those and saves them onto drive so our web app can display them to a user. Essentially it is an incoming email handler.
Anyway, I am getting this error:
System.StackOverflowException was unhandled
{Cannot evaluate expression because the current thread is in a stack
overflow state.}
Here is the code:
static List<string> SplitPDF(string PDFPath)
{
try
{
List<string> retval = new List<string>();
ExpertPdf.PDFSplit.PDFSplitManager pds = new PDFSplitManager();
pds.LicenseKey = "XXXXXXXXXXXX";
int Pages = pds.GetPdfPageCount(PDFPath);
for (int i = 0; i < Pages; i++)
{
pds.ExtractPagesFromFileToFile(PDFPath, PDFPath + i.ToString() + ".pdf", i + 1, 1);
retval.Add(PDFPath + i.ToString() + ".pdf");
}
retval.Add(PDFPath);
return retval;
}
catch (Exception ex)
{
throw ex;
}
}
This method throws the error on
int Pages = pds.GetPdfPageCount(PDFPath);
Don't know why or how. The funny thing is, it only happens with one of three batch files. The other two work fine (Production fails, dev and test work fine).
We think it may have to do with the file folders, maybe something is happening in there, but I am unsure...
Any suggestions? Need any other code? I know I only provided one method, but that is where the error is.
Thanks!
EDIT: here is the stack trace, if it helps
IncomingFax.exe!IncomingFax.Program.SplitPDF(string PDFPath = "D:\www\443\PBIN\fax\inbox\preproc\3lz3npbd2sy") Line 726 + 0x17 bytes
IncomingFax.exe!IncomingFax.Program.ProcessMessage(ForAspNet.POP3.EmailMessage Message = {ForAspNet.POP3.EmailMessage}) Line 326 + 0x9 bytes
IncomingFax.exe!IncomingFax.Program.Main(string[] args = {string[6]}) Line 78 + 0x9 bytes