How to Log Exception in a file? - c#

I want to be able to do logging in every catch block. Something like this.
catch (Exception exception)
{
Logger.Write(exception);
}
and then the settings in the configuration will pick up the Message and StackTrace property etc using customer listener.
I would like to use Enterprise Library Logging Application Block. I'm sure someone must have done this already.

Others have posted some good links on getting the Logging Application Block (LAB) working so I won't duplicate that here.
In terms of formatting your exception you have 3 choices that I can think of:
Use the default Exception.ToString() implementation (it's not bad)
Write a Custom Formatter that integrates into the LAB.
Write a helper function that performs the formatting and passes the string into the Write method.
If option 1 doesn't meet your needs then I would recommend going with option 3 (since option 2 is overkill).
A simple example would be something like:
catch (Exception exception)
{
Logger.Write(LogHelper.CreateExceptionString(exception));
}
...
public static string CreateExceptionString(Exception e)
{
StringBuilder sb = new StringBuilder();
CreateExceptionString(sb, e);
return sb.ToString();
}
private static void CreateExceptionString(
StringBuilder sb,
Exception e,
string indent = "")
{
if (indent.Length > 0)
{
sb.AppendFormat("{0}Inner ", indent);
}
sb.AppendFormat("Exception Found:\n{0}Type: {1}",
indent, e.GetType().FullName);
sb.AppendFormat("\n{0}Message: {1}",
indent, e.Message);
sb.AppendFormat("\n{0}Source: {1}",
indent, e.Source);
sb.AppendFormat("\n{0}Stacktrace: {1}",
indent, e.StackTrace);
if (e.InnerException != null)
{
sb.Append("\n");
CreateExceptionString(sb, e.InnerException, indent + " ");
}
}

Microsoft has provided extensive guidance on this here: Developing Applications Using the Logging Application Block
It's well worth familiarizing yourself with what they have to say, as it's quite powerful.
If you want something a little more down to earth, some working examples are provided in this blog article: How To Configure and Use the Logging Application Block
If you're still having trouble after reading those, edit your post with more specific details about what seems to be the problem.

#iSid Is this what you are asking for
public static void printException(Exception ex){
Console.WriteLine("HelpLink = {0}", ex.HelpLink);
Console.WriteLine("Message = {0}", ex.Message);
Console.WriteLine("Source = {0}", ex.Source);
Console.WriteLine("StackTrace = {0}", ex.StackTrace);
Console.WriteLine("TargetSite = {0}", ex.TargetSite);
}

You need to add an appropriate listener for Text files - see this post, its for ASP.NET but the config files work the same way across applications.

Related

C# Procedures Do Not Hit

I'm trying to convert some VB.NET programs to C#. I'm quite familiar with VB and am just now getting started with C#. My first program seems to have been exported well enough. I used the MSDN to take care of a few errors after the conversion. BUT the two procedures below do not hit. The program has 0 errors in Visual Studios, and from what I can tell, they are structured just like the examples on the MSDN website. I'm using Visual Studio 2015.
It’s a simple program that opens a COM port and receives data; very basic. Works perfect in VB, and in C# everything but these 2 procedures fire. Any insight on what I’m doing wrong would be immensely appreciated.
//catches incoming data from serial device.
private void SerialPort1_DataReceived(System.Object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
ReceivedText(serialPort1.ReadExisting());
}
catch (Exception ex)
{
MessageBox.Show("Error (4)", "Error", MessageBoxButtons.OK);
}
}
//input from ReadExisting
private void ReceivedText(string text)
{
try
{
if (this.txtOutput.InvokeRequired)
{
SetTextCallback x = new SetTextCallback(ReceivedText);
this.Invoke(x, new object[] { (text) });
}
else
{
this.txtOutput.Text += text;
}
//append text
}
catch (Exception ex)
{
MessageBox.Show("Error (5)", "Error", MessageBoxButtons.OK);
}
}
When adding a serial port through the designer, set the call back in the properties window under the events tab:

Something is deleting a console app. Why is it being deleted?

I need to learn how to use SMO within a C# program, so the first thing I did was start a new, console app and then began putting in the basics. I decided to make the app accept parameters so I can pass in things like usernames, logins, etc. As I work on it and build it I have a PowerShell window open where I can call the app, give it parameters or not, etc. But something weird is happening which I don't understand. Sometimes when I run the app in the PowerShell window, it's then deleted for some reason. Why is it doing that? I discovered it when it first gave me the following error message:
Program 'SmoListLogins.exe' failed to run: The system cannot find the file specifiedAt line:1 char:1 + .\SmoListLogins.exe "MYCOMPANY\Rod"
My SmoListLogins.exe program isn't there. Naturally I can easily re-create it, but I don't understand why its being deleted.
So you can see what I'm working with, here's the source code. I took it from a MSDN article and have added a little bit:
using System;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
namespace SmoListLogins
{
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
var userName = args[0];
ListLogins(userName);
}
else
{
ListLogins();
}
}
static private void ListLogins(string userName = "")
{
var userNamePassed = (userName != "");
Server srv = new Server("YOURSQLINSTANCE");
//Iterate through each database and display.
foreach (Database db in srv.Databases)
{
Console.WriteLine("========");
Console.WriteLine("Login Mappings for the database: " + db.Name);
Console.WriteLine(" ");
//Run the EnumLoginMappings method and return details of database user-login mappings to a DataTable object variable.
DataTable d;
try
{
d = db.EnumLoginMappings();
//Display the mapping information.
foreach (DataRow r in d.Rows)
{
var userNameMatches = false;
var starting = true;
foreach (DataColumn c in r.Table.Columns)
{
if (!userNamePassed)
{
Console.WriteLine(c.ColumnName + " = " + r[c]);
}
else
{
if (starting)
{
starting = false;
if (userName == r[c].ToString())
{
userNameMatches = true;
}
}
if (userNameMatches)
{
Console.WriteLine(c.ColumnName + " = " + r[c]);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error processing database: {db.Name}");
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine();
}
}
}
}
}
I believe I now know what was deleting my executable. It wasn't something I thought of, so I'm sharing with everyone the answer. Today I got an email from our chief security officer, informing me that the program I wrote was being blocked by Symantec Endpoint Protection. In my testing I'd run my app over and over again. After a few iterations of that it would disappear. It didn't occur to me that it was our corporate AV that might be doing it. Now it looks as though that is exactly what was going on.
Thank you everyone for your input in trying to help me resolve this. I hope that if anyone else encounters this problem they might consider the possibility of their AV as the reason why the app they wrote disappears.

Error Logging in C# Website

I am planning to implement error logging writing something similar to this:
public static void WriteError(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)
{
WriteError(ex.Message);
}
}
My question is this: Since it is a website, I will have multiple users simultaneously. In that case, if multiple users encounter exceptions at the same time and try to write to the same file, it will again give me an exception right? In that case, how do I implement error logging correctly for simultaneous users? Or will this work?
Thanks in advance.
I'd recommend you use an established logging framework such as NLog or log4net. I have used log4net on many projects in the past and it handles this scenario perfectly.
EDIT:
Just as a further comment, as well as handling log messages from multiple threads log4net also allows you to manage how large your log files grow and provide a built in rolling log mechanism via the RollingFileAppender.
Beside using NLog or other log library, the way you lock this cases is with mutex. I suggest mutex, and not lock() because can catch all pools/threads that may throw an error.
On MSDN there are the details about mutex and examples:
http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
a simple example
public static void WriteError(string errorMessage)
{
var mut = new Mutex(true, "LogMutexName");
try
{
// Wait until it is safe to enter.
mut.WaitOne();
// here you open write close your file
}
finally
{
// Release the Mutex.
mut.ReleaseMutex();
}
}

Trying to catch System.Net.WebException (C#) in Java

What is the closest equivalent of System.Net.WebException in Java?
I am trying to do this in Java. The program is polling for new statuses and messages in a while true loop, but if the network "hiccups" for a second, I want to catch the exception.
while (true)
{
try
{
GetStatusChanges();
GetReturnMessages();
if (pollCounter == 30)
{
SubmitMessages();
pollCounter = 0;
}
}
catch (System.Net.WebException webException)
{
Console.WriteLine(webException);
}
Thread.Sleep(10000);
pollCounter++;
}
Looking in the java.net package, I'm not sure what to use.
I believe what you need is java.net.SocketException, or its descendants, based on this question.
I have found that some other cases might throw other IOException subclasses, like UnknownServiceException (SocketException is also a subclass of IOException.)

WebService Call Exception: Thread was being aborted

Recently we've been getting System.Threading.ThreadAbortExceptions from an ASP.NET webservice that posts data to a payment server each night.
The webservice is a standard .asmx page that gets called from another client.
Inside the page I have a foreach loop that iterates through many payment rows in a database:
foreach (var obtRow in readyToBeCaptured)
{
try
{
status = dibs.GetPagePost(...);
// handle status here
}
catch (ThreadAbortException tex)
{
SingletonLogger.Instance.Error(string.Format("Transactionhandler - Could not Capture, Thread was aborted. {0}", tex.Message), tex);
}
catch (Exception ex)
{
SingletonLogger.Instance.Error(string.Format("Transactionhandler - Could not Capture, statuscode: {0}, message: {1}.", status, ex.Message), ex);
}
}
The strange thing is I get a log entry from catch(ThreadAbortException tex) block when this error occurs, but then the code breaks out and is caught in another try catch block further up the call tree. Ideally I would have the code inside the foreach loop to continue
This is the GetPagePost method
private bool GetPagePost(string url, NameValueCollection nameValueCollection, string userName, string password)
{
WebClient client = new WebClient();
if (userName != "")
{
client.Credentials = new NetworkCredential(userName, password);
}
foreach (string str in nameValueCollection.AllKeys)
{
this._callCollection.Add(str, nameValueCollection[str]);
}
StringBuilder builder = new StringBuilder();
builder.Append("DIBS.NET/1.2.0 ( ");
builder.Append("OS ").Append(Environment.OSVersion.Platform).Append(" ").Append(Environment.OSVersion.Version).Append("; ");
builder.Append(".NET CLR ").Append(Environment.Version).Append("; ");
builder.Append("User ").Append(Environment.UserName).Append("; ");
builder.Append("Domain ").Append(Environment.UserDomainName).Append("; ");
builder.Append(" ) ");
client.Headers.Add("User-Agent", builder.ToString());
try
{
byte[] bytes = client.UploadValues(url, "POST", nameValueCollection);
this._httpStatus = 200;
this._httpBody = Encoding.UTF8.GetString(bytes);
return true;
}
catch (WebException exception)
{
this._httpBody = exception.Message;
this._httpStatus = (int) exception.Status;
}
catch (UriFormatException exception2)
{
this._httpBody = exception2.Message;
this._httpStatus = -9999;
}
catch (Exception exception3)
{
this._httpBody = exception3.Message;
this._httpStatus = -99999;
}
return false;
}}
Why is this error occuring and how can I prevent the code from breaking out of the foreach loop?
I've been looking at a few other posts here on StackOverflow but they seem to relate to the usage of Reponse.Redirect which I don't use.
Thanks
/Jens
I have a similar issue. I think IIS is terminating your thread for taking too long. From your description "I have a foreach loop that iterates through many payment rows in a database", you may be able to restructure your app to process each row individually. Create a webmethod to send the rows to the client, then have the client iterate the transactions one at a time and process them in a different webmethod. Then you can handle exceptions that occur and keep going. You may even be able to process many at once using Parallel.ForEach
Last days I had a similar problem with a web service and solved it adding to </system.web> of web.config this line: <httpRuntime executionTimeout="600"/>.
600 is the number of seconds till is shut downed by asp.net. The default is 110 seconds.
It explains here better what it does.
After some RND try few things:
try adding custom account in the application pool
try repairing the .net framework by running the NetFxRepairTool exe from official Microsoft website
try adding httpRuntime and targetFramework="4.5" (This works for me targetFramework="4.5")
httpRuntime targetFramework="4.5" maxRequestLength="4000"
executionTimeout="45"
ref: http://dotnetvisio.blogspot.com/2013/07/solution-for-thread-being-aborted-call.html

Categories