logging exception
the code below allows to save the content of an exception in a text file. Here I'm getting only the decription of the error.
but it is not telling me where the exception occured, at which line.
Can anyone tell me how can I achive that so I can get even the line number where the exception occured?
#region WriteLogError
/// <summary>
/// Write an error Log in File
/// </summary>
/// <param name="errorMessage"></param>
public void WriteLogError(string errorMessage)
{
try
{
string path = "~/Error/" + DateTime.Today.ToString("dd-mm-yy") + ".txt";
if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(path)))
{
File.Create(System.Web.HttpContext.Current.Server.MapPath(path))
.Close();
}
using (StreamWriter w = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path)))
{
w.WriteLine("\r\nLog Entry : ");
w.WriteLine("{0}", DateTime.Now.ToString(CultureInfo.InvariantCulture));
string err = "Error in: " + System.Web.HttpContext.Current.Request.Url.ToString()
+ ". Error Message:" + errorMessage;
w.WriteLine(err);
w.WriteLine("__________________________");
w.Flush();
w.Close();
}
}
catch (Exception ex)
{
WriteLogError(ex.Message);
}
}
#endregion
I find that the easiest way to log exceptions in C# is to call the ToString() method:
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
This usually gives you all the information you need such as the error message and the stack trace, plus any extra exception specific context information. (however note that the stack trace will only show you source files and line numbers if you have your application compiled with debug information)
It is worth noting however that seeing a full stack trace can be fairly offputting for the user and so wherever possible you should try to handle exceptions and print out a more friendly error message.
On another note - you should replace your method WriteLogError with a fully featured logging framework (like Serilog) instead of trying to write your own.
Your logging method is not thread safe (your log file will probably end up with log messages being intermingled with each other) and also should definitely not call itself if you catch an exception - this will mean that any exceptions that occur whilst logging errors will probably cause a difficult to diagnose StackOverflow exception.
I could suggest how to fix those things, however you would be much better served just using a proper logging framework.
Just log ToString(). Not only will it give you the stack trace, but it'll also include the inner exceptions.
Also, when you deploy a release build of your code to a production environment for instance, don't forget to include the .pdb files in the release package. You need that file to get the line number of the code that excepted (see How much information do pdb files contain? (C# / .NET))
Your solution is pretty good. I went through the same phase
and eventually needed to log more and more (it will come...):
logging source location
callstack before exception (could be in really different place)
all internal exceptions in the same way
process id / thread id
time (or request ticks)
for web - url, http headers, client ip, cookies, web session content
some other critical variable values
loaded assemblies in memory
...
Preferably in the way that I clicked on the file link where the error occurred,
or clicked on a link in the callstack, and Visual Studio opened up at the appropriate location.
(Of course, all you need to do is *.PDB files, where the paths from the IL code
to your released source in C # are stored.)
So I finally started using this solution:
It exists as a Nuget package - Desharp.
It's for both application types - web and desktop.
See it's Desharp Github documentation. It has many configuration options.
try {
var myStrangeObj = new { /*... something really mysterious ...*/ };
throw new Exception("Something really baaaaad with my strange object :-)");
} catch (Exception ex) {
// store any rendered object in debug.html or debug.log file
Desharp.Debug.Log(myStrangeObj, Desharp.Level.DEBUG);
// store exception with all inner exceptions and everything else
// you need to know later in exceptions.html or exceptions.log file
Desharp.Debug.Log(ex);
}
It has HTML log formats, every exception in one line,
and from html page you can open in browser, you can click
on file link and go to Visual Studio - it's really addictive!
It's only necessary to install this Desharp editor opener.
See some demos here:
Web Basic App
Web MVC App
Console App
Try to check out any of those repos and log something by the way above.
then you can see logged results into ~/Logs directory. Mostly anything is configurable.
I am only answering for the ask, other people have already mentioned about the code already. If you want the line number to be included in your log you need to include the generated debug files (pdb) in your deployment to the server. If its just your Dev/Test region that is fine but I don't recommend using in production.
Please note that the exception class is serializable. This means that you could easily write the exception class to disk using the builtin XmlSerializer - or use a custom serializer to write to a txt file for example.
Logging to output can ofcourse be done by using ToString() instead of only reading the error message as mentioned in other answers.
Exception class
https://learn.microsoft.com/en-us/dotnet/api/system.exception?redirectedfrom=MSDN&view=netframework-4.7.2
Info about serialization, the act of converting an object to a file on disk and vice versa.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/
Related
I am getting this error:
ImageMagick.MagickResourceLimitErrorException: 'TooManyExceptions (exception processing is suspended) # error/exception.c/ThrowException/969'
On this line
using (MagickImageCollection tiffPageCollection = new MagickImageCollection())
{
tiffPageCollection.Read(tifName); // fails here.
}
The problem occurs because the 92 page tif has three errors like this on each page:
{"ASCII value for tag \"Copyright\" does not end in null byte. `TIFFFetchNormalTag' # warning/tiff.c/TIFFWarnings/1007"} ImageMagick.MagickException {ImageMagick.MagickCoderWarningException}
The number of warning errors is exceeded so that triggers TooManyExceptions errors.
This URL alludes to a solution:
http://www.imagemagick.org/discourse-server/viewtopic.php?t=33989
of adding this handler:
private void MagickNET_Log (object sender, LogEventArgs e)
{
// write to a single log file...
if ((RemoteImageMagickEventLogging & e.EventType) != LogEvents.None)
{
switch (e.EventType)
{
case LogEvents.Exception:
if (!e.Message.Contains ("TIFFWarnings"))
{
TriggerRemoteLoggingEvent (e.EventType,
EZLogger.LoggingLevel.Note1, e.Message);
}
break;
}
}
}
It also references that this exception was added to "ImageMagick.Net 7.4.5 Q8 AnyCPU" and did not happen on earlier versions. I am experiencing the problem on "ImageMagick.Net-Q16-AnyCPU v7.9.1" I updated to v7.10.0 and still had the same problem.
So, my questions are:
What versions of ImageMagick have and don't have this feature?
What are the steps to handing that handler to my code?
Is there a way to increase the maximum number of allowed warnings and I can just raise that limit to something so high that I will not hit it?
This issue has been fixed in Magick.NET 7.10.1.0: https://github.com/dlemstra/Magick.NET/releases/tag/7.10.1.0. The TooManyExceptions (exception processing is suspended) exception will no longer be thrown because this has been changed into a warning.
What versions of ImageMagick have and don't have this feature?
From the changelog, it was added as early as version 7.0.7-22. The body of work around this feature was in response to Google's OSS-fuzz project.
Is there a way to increase the maximum number of allowed warnings and I can just raise that limit to something so high that I will not hit it?
Not currently. The limit is hardcoded MagickCore/exception.c as ...
#define MaxExceptionList 64
But this is opensource, and a rather new feature. If you post an issue under 'Bugs' message board, you may be able to have the developers revise the limit, or allow some resource attribute under polices.xml to be controlled by the user. Presenting a real world test-case also helps, and tiff file with 64+ warnings should require some level of scrutiny.
I am facing issue with perforce api (.net), as i am unable to pull sync logs in real time.
- What am I trying to do
I am trying to pull real time logs as Sync is triggered using the
Perforce.P4.Client.SyncFiles() command. Similar to the P4V GUI Logs, which update when we try to sync any files.
- What is happening now
As the output is generated only after the command is done execution its not something intended for.
Also tried looking into Perforce.P4.P4Server.RunCommand() which does provide detailed report but only after the execution of the command.
Looked into this
Reason is -
I am trying to add a status update to the Tool i am working on which shows which Perforce file is currently being sync'd.
Please advise. Thanks in Advance.
-Bharath
In the C++ client API (which is what P4V is built on), the client receives an OutputInfo callback (or OutputStat in tagged mode) for each file as it begins syncing.
Looking over the .NET documentation I think the equivalents are the P4CallBacks.InfoResultsDelegate and P4CallBacks.TaggedOutputDelegate which handle events like P4Server.InfoResultsReceived etc.
I ended up with the same issue, and I struggled quite a bit to get it to work, so I will share the solution I found:
First, you should use the P4Server class instead of the Perforce.P4.Connection. They are two classes doing more or less the same thing, but when I tried using the P4.Connection.TaggedOutputReceived events, I simply got nothing back. So instead I tried with the P4Server.TaggedOutputReceived, and there, finally, I got the TaggedOutput just like I wanted.
So, here is a small example:
P4Server p4Server = new P4Server(cwdPath); //In my case I use P4Config, so no need to set user or to login, but you can do all that with the p4Server here.
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess=false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the method to handle the error messages or the taggedOutput:
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]); //Write the synced file name.
//Note that I used this only for a 'Sync' command, for other commands, I guess there might not be any Obj["clientFile"], so you should check for that.
}
When attempting to download asset files for Minecraft, half of the files fail with a download error : "An exception occurred during a WebClient request."
With the InnerException being : "{"The process cannot access the file 'C:\\Users\\[redacted]\\AppData\\Roaming\\[redacted]\\Minecraft 1.10\\assets\\objects\\bdbdf48ef6b5d0d23bbb02e17d04865216179f510a' because it is being used by another process."}".
I am using the FileDownloadCompleted event.
I have also tried adding a "." to the end of each file that doesn't have a proper extension but it has not solved the problem.
Also, this problem is not consistent. Some files with similar names download normally, while other files fail to download. However, it's not an Internet issue either and I have tested on multiple computers.
How can I resolve this exception?
As a makeshift workaround, I have added a while loop to wait for the file to become available.
else if(e.Error.InnerException is IOException)
{
bool canAccess = false;
while (!canAccess)
{
try
{
File.Move(Userstate[0], Userstate[0]);
canAccess = true;
Debug.Print("Can now access file: " + Userstate[0]);
}
catch(IOException) { }
}
}
This code is part of the DownloadCallback handler, and checks the status of e.Error.InnerException. This does not seem like the best solution, but it's the only one I have come up with.
I asked a question yesterday, and recieved great help (especially from #AviTurner).
I have further developed the program I was working on yesterday, and I have encountered a new problem.
The code of my program can be found here.
Basicly what it does, is:
The user can select a path of a directory, and the program scans all files for read-only attribute.
It sets the read-only attribute on those files that does not currently have it.
Now the problem occurs, when it encounters a file that is currently in use (such as system files).
I have been told there is no way around this, but I thought:
Is there a way to ignore the error (by this I mean continue the program, just skip this file); and add the name of the file to a list for later tracking purposes?
I hope I made my problem clear.
Thanks.
try surrounding your code in try/catch:
try
{
System.IO.FileAttributes attr = System.IO.File.GetAttributes(file);
}
catch(Exception ex)
{
files.add(file)
}
basically if you get an exception in the try block, the program executes the catch block
I suggest...
try
{
System.IO.File.SetAttributes(file, attr);
}
catch // You can specify a specific error with catch(UnauthorizedAccessException ex) for instance.
{
filesInError.Add(file); // A list<string>() to keep track of errors.
}
Here the details, and exceptions raised, by the SetAttributes().
SetAttributes on MSDN
And some explanations about try catch if you're not familiar with.
try ... catch on MSDN
public static List<Product> Load(string filename)
{
if (!File.Exists(filename))
{
throw new FileNotFoundException("Data could not be found ", filename );
}
}
Visual Studio 2010 gives the following exception, "FileNotFoundException"
emmm.. ok. this problem seem to have been solved.
.
But however, I still can not find the file!! But the file is there, in the same directory, Ive already verified and double-verified the name is correct! I have no idea what is going on.
The file is called "Products.xml".
You are the one who is throwing the exception. Do you mean to put up an error message?
File.Exists may return false if the user that the code runs under does not have access to the file, as well as if the does not exist.
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx
The file is called "Products.xml".
You expose yourself to random failure with a filename like that. You should use the full path name of the file, like c:\mumble\foo\products.xml. If you don't then you completely rely on your program's working directory being set correctly. The value of Environment.CurrentDirectory.
Even if it is set correctly by whatever program is starting yours (like a shortcut on the desktop), you still can get into trouble when code you didn't write changes the working directory. A good example is OpenFileDialog with the RestoreDirectory property left to the default value of false.
Always use full path names in your code. Or let the user select the file.
It looks like the problem is File.Exists is returning false and you're throwing an exception which is not handled by your code. Did you intend for this exception to be handled or does this represent a fatal error to your program?
The file located at filename does not exist, and thus it throws the exception with the following line: throw new FileNotFoundException("Data could not be found ", filename );
Did you mean to just output an error?
In you code first check for empty filename as the passed parameter may be empty string, plus apply try catch block on the code as the passed filename might not satisfy the path rules for a file. in catch block through your exception too.
You either:
A) Don't want to throw the exception via this line
throw new FileNotFoundException()
and instead want to display a Dialog to the user, or use some other error handling technique in there. To output an error either use one of the following:
Console.WriteLine("File not found")
MessageBox.Show("File not found");
B) Higher up in your call stack have a try/catch and handle your error there, similarly with a dialog or another error handling approach suitable for your application.
try
{
Load(filename);
}
catch(FileNotFoundException fe)
{}