Best practice error handling in Global asax - c#

I have code below in global asax now, I want to store exception log in database, is this good practice? because if sql error happens there, I want to log it too. So I am thinking changing the code below to write text log instead email, then on sql error, write text log.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
string testEnvironment = ConfigurationSettings.AppSettings["isTestEnvironment"];
if (testEnvironment == "0")
{
Exception ex = Server.GetLastError();
if (ex is HttpException && ex.InnerException is ViewStateException)
{
Response.Redirect(Request.Url.AbsoluteUri)
return
}
StringBuilder theBody = new StringBuilder();
theBody.Append("URL: " + Request.Url + "\n");
theBody.Append("Referer: " + Request.ServerVariables["HTTP_REFERER"] + "\n");
theBody.Append("IP: " + Request.ServerVariables["REMOTE_HOST"] + "\n");
theBody.Append("Error Message: " + ex.ToString() + "\n");
if (User.Identity.IsAuthenticated)
theBody.Append("User: " + User.Identity.Name + "\n");
else
theBody.Append("User is not logged in." + "\n");
theBody.Append("Form Values: " + "\n");
foreach (string s in Request.Form.AllKeys)
{
if (s != "__VIEWSTATE")
theBody.Append(s + ":" + Request.Form[s] + "\n");
}
theBody.Append("Session Values: " + "\n");
foreach (string s in Session.Keys)
theBody.Append(s + ":" + Session[s] + "\n");
System.Net.Mail.MailMessage email = new System.Net.Mail.MailMessage();
email.IsBodyHtml = false;
email.From = new System.Net.Mail.MailAddress("errors#karpach.com", "ErrorManager");
email.To.Add(new System.Net.Mail.MailAddress("errornotification#karpach.com", "Developer"));
email.Subject = Request.Url.ToString().Split('/')[2] + " has ASP.NET error";
email.Body = theBody.ToString();
try
{
System.Net.Mail.SmtpClient emailProvider = new System.Net.Mail.SmtpClient();
emailProvider.Send(email);
}
catch (Exception anException)
{
}
finally
{
if (Request.Url.Segments[Request.Url.Segments.Length - 1].ToLower() != "error.aspx")
Response.Redirect("~/error.aspx?msg=4");
else
{
Response.Write(#"We encountered an internal error. We apologize for any inconvenience
but know that our staff gets emailed EVERY error that occurs so that we can solve it promptly.");
Response.End();
}
}
}
}

You could log it to the EventLog. System admins can setup monitoring to see when new events are added and be alerted to potential problems.
Here's an example from MSDN for the EventLog class:
if(!EventLog.SourceExists("MySource"))
{
//An event log source should not be created and immediately used.
//There is a latency time to enable the source, it should be created
//prior to executing the application that uses the source.
//Execute this sample a second time to use the new source.
EventLog.CreateEventSource("MySource", "MyNewLog");
Console.WriteLine("CreatedEventSource");
Console.WriteLine("Exiting, execute the application a second time to use the source.");
// The source is created. Exit the application to allow it to be registered.
return;
}
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "MySource";
// Write an informational entry to the event log.
myLog.WriteEntry("Writing to event log.");

Related

Cannot access the File to write after sending it in Mail attachment

I have the C# console application which writes the step it is doing in a Log text file using the code below
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("dd-MM-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
if (!logFileInfo.Exists)
{
fileStream = logFileInfo.Create();
}
else
{
fileStream = new FileStream(logFilePath,FileMode.Append);
}
log = new StreamWriter(fileStream);
log.WriteLine("---------------" + DateTime.Now.ToString() + "--------------------------");
log.WriteLine(strLog);
log.WriteLine("---------------------------------------------------------------");
log.Close();
It works fine but when an exception occurs I will attach the log text file to the mail and send it after that when I try to invoke the Method again which writes into the same log text file after mail with log text file attachment I get the exception IOException: The process cannot access the file 'file path' because it is being used by another process
I had tried FileShare Option and other things nothing worked out
Exception is thrown in the below code
client.Send(mail);
client.Dispose();
LogWriter.WriteLog("######--Re-Start of the Process at -" + Convert.ToString(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss")) + "--######"); //Exception thrown here
Console.WriteLine("######--Re-Start of the Process at -" + Convert.ToString(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss")) + "--######");
BridgePage.GetData();
Console.WriteLine("######--Re-End of the Process at -" + Convert.ToString(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss")) + "--######");
LogWriter.WriteLog("######--Re-End of the Process at -" + Convert.ToString(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss")) + "--######");
As per the comment to use FileInfo.AppendText by Panagiotis Kanavos tried the below code, but still same exception
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("dd-MM-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
if (!logFileInfo.Exists)
{
//Create a file to write to.
using (StreamWriter logsw = logFileInfo.CreateText())
{
logsw.WriteLine("---------------" + DateTime.Now.ToString() + "--------------------------");
logsw.WriteLine(strLog);
logsw.WriteLine("---------------------------------------------------------------");
}
}
else
{
using (StreamWriter logsw = logFileInfo.AppendText())
{
logsw.WriteLine("---------------" + DateTime.Now.ToString() + "--------------------------");
logsw.WriteLine(strLog);
logsw.WriteLine("---------------------------------------------------------------");
}
}
Please help
Instead of Disposing the SmtpClient I had free'd the Attachments of MailMessage.Attachments after sending the mail
if (mail.Attachments != null)
{
for (int i = mail.Attachments.Count - 1; i >= 0; i--)
{
mail.Attachments[i].Dispose();
}
mail.Attachments.Clear();
mail.Attachments.Dispose();
}
mail.Dispose();
mail = null;
It worked out

Problem with consumer.receive MessageSelector

I have a problem in activemq. I want to receive a special message from my activemq queue. I have there over 300 Messages, and I want one of the message. I solved this with a multiselectcombobox. In this box I have all messages with all properties I need.
When I click on the 247 item, I want do select the item to receive the message, after them I want to send the message but first I have a problem with the receive.
I don't know why it doesn't work. Maybe someone has an idea?
ErrorMessageProperty prop = new ErrorMessageProperty();
IMessage message = null;
try
{
string MsgID = MSGID;
string desinationque = sourceQueue;
string selector = "ProducerId = '" + MsgID + "'";
IDestination dest = MQSession.GetDestination(desinationque);
Uri _activeMQURI = new Uri(conf.ActiveMqURL);
MQConnectionFactory = new NMSConnectionFactory(_activeMQURI);
using (MQConnection = MQConnectionFactory.CreateConnection(conf.ActiveMqUser, conf.ActiveMqPWD))
using (MQSession = MQConnection.CreateSession(AcknowledgementMode.AutoAcknowledge))
{
try
{
MQConnection.Start();
}
catch (Exception ex)
{
myLogger.NLogger.Info("MQReceiveTextMessage Connection fehlgeschlagen: " + ex.Message);
}
using (IMessageConsumer consumer = this.MQSession.CreateConsumer(dest, selector,false))
{
if (shallwait)
{
try
{
message = consumer.Receive();
}
catch (Exception ex)
{
myLogger.NLogger.Error("Error in consumer Receive (MQReceiveTextMessage): Message" + message + " Fehler-Exception: " + ex.Message);
}
}
else
{
message = consumer.Receive(TimeSpan.FromSeconds(1));
}
}
}
}
catch (Exception ex)
{
myLogger.NLogger.Error("Error in MQReceiveTextMessage: Parameter: sourceQueue: " + sourceQueue + " MSGID: " + MSGID + " Message: " + message + " Fehler-Exception: " + ex.Message);
}
return message;
}
My ProducerID is correct. But why doesn't this work? It stops at the line
message = consumer.receive();
I don't know anymore
With the selector ProducerId = 'MsgIDValue', the operation consumer.receive() is searching a Message in the queue with a custom property "ProducerId" with the value of the variable MsgID. If the message is not found the consumer waits new messages.
If you want to search for a default message field, message header field references are restricted to JMSDeliveryMode, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be null and if so are treated as a NULL value.
Source Message Selectors
I used Apache.NMS and Apache.NMS.ActiveMQ (1.7.1.3924)
is it possible to u se this api than the jms?
I try this since 1 Week and the selector does'nt work....
Maybe someone othe

Value assigned more than once in single assignment

I made script task that's downloading and saving on disk two spreadsheets from Google Drive using file ID and prepared URL address.
This is main() from my C# code, there are no things outside of it:
public void Main()
{
string m_FileId = Dts.Variables["User::varFileId"].Value.ToString();
string m_RemoteUrl = "https://docs.google.com/spreadsheets/d/" + m_FileId + "/export?format=xlsx";
string m_FilePath = null;
WebClient client = new WebClient();
try
{
m_FilePath = Dts.Variables["User::varFilePath"].Value.ToString() + Dts.Variables["User::varFileName"].Value.ToString();
client.DownloadFile(new System.Uri(m_RemoteUrl), m_FilePath);
m_FilePath = "";
m_FileId = Dts.Variables["User::varFileId2"].Value.ToString();
m_RemoteUrl = "https://docs.google.com/spreadsheets/d/" + m_FileId + "/export?format=xlsx";
m_FilePath = Dts.Variables["User::varFilePath"].Value.ToString() + Dts.Variables["User::varFileName2"].Value.ToString();
client.DownloadFile(new System.Uri(m_RemoteUrl), m_FilePath);
}
catch(Exception e)
{
Dts.Events.FireError(0, "FileDownload", e.Message
+ "\r" + e.StackTrace
+ " \rUrl: " + m_RemoteUrl
+ " \rFilePath: " + m_FilePath
+ " \rPath: " + Dts.Variables["User::varFilePath"].Value.ToString()
+ " \rFileName2: " + Dts.Variables["User::varFileName2"].Value.ToString()
, string.Empty, 0);
Dts.TaskResult = (int)ScriptResults.Failure;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Problem occurs exactly on every second time I run this code and I don't know how to get rid of it. There's just exception in my script task. I'm printing all variables that are used in this code, and as you can see there's something wrong with m_FilePath, it's like multiplied despite of being printed just once.
[FileDownload] Error: An exception occurred during a WebClient request.
at System.Net.WebClient.DownloadFile(Uri address, String fileName)
at ST_84b63d1593dd449886eb2b32dff40b2d.ScriptMain.Main()
Url: https://docs.google.com/spreadsheets/d/----------/export?format=xlsx
FilePath: C:\Google Drive extract\ga_manual_cost_file.xlsxC:\Google Drive extract\ga_manual_cost_file.xlsx
Path: C:\Google Drive extract\ga_manual_cost_file.xlsx
FileName2: ga_manual_cost_file.xlsx
SSIS variables that I'm using are ReadOnly, and are used only in this script task(I tried running only this part of control flow), and their values are as follows:

Copying a file that is a virus caused my program to terminate

I have made a tool that will copy files from a source to a destination. However during the copy, the software came across a virus that was flagged by the anti-virus software (Symantec).
The anti-virus then caused my software to close down, and quarantine the program as a "dropper".
Is there anyway I can gracefully handle this scenario, rather than shutting down my program completely?
I appreciate that the action was the result of the anti-virus, but is there anything I can do to help the situation? For example, Robocopy does not just terminate when it comes across a virus.
Here is my copy code;
void CopyFileExactly(CopyParameterBundle cpb, bool overwrite)
{
string CTP = "", CFP = "";
CFP = cpb.SourcePath;
if (cpb.RenameFile)
CTP = cpb.DestPath ;
else
CTP = cpb.DestPath;
//Check firstly if the file to copy exists
if (!File.Exists(CFP))
{
throw new FileNotFoundException();
}
//Check if destination file exists
//If it does, make it not read only so we can update MAC times
if (File.Exists(CTP))
{
var target = GetFile(CTP);//new FileInfo(CTP);
if (target.IsReadOnly)
target.IsReadOnly = false;
}
var origin = GetFile(CFP);//new FileInfo(CFP);
GetFile(CTP).Directory.Create();
//(new FileInfo(CTP)).Directory.Create();
origin.CopyTo(CTP, (overwrite ? true : false));
if (!File.Exists(CTP))
{
throw new FileNotFoundException("Destination file not found!");
}
var destination = GetFile(CTP);//new FileInfo(CTP);
if (destination.IsReadOnly)
{
destination.IsReadOnly = false;
destination.CreationTime = origin.CreationTime;
destination.LastWriteTime = origin.LastWriteTime;
destination.LastAccessTime = origin.LastAccessTime;
destination.IsReadOnly = true;
}
else
{
destination.CreationTime = origin.CreationTime;
destination.LastWriteTime = origin.LastWriteTime;
destination.LastAccessTime = origin.LastAccessTime;
}
if (performMD5Check)
{
var md5Check = compareFileMD5(CFP, CTP);
cpb.srcMD5Hash = md5Check.Item2;
cpb.dstMD5Hash = md5Check.Item3;
if (!md5Check.Item1)
throw new MD5MismatchException("MD5 Hashes do NOT match!");
}
}
The calling code;
void BeginCopy(int DegreeOfParallelism, int retryCount, int retryDelay)
{
object _lock;
//Setup cancellation token
po.CancellationToken = cts.Token;
//Set max number of threads
po.MaxDegreeOfParallelism = DegreeOfParallelism;
//Exceptio logging queue
var exceptions = new ConcurrentQueue<Exception>();
var completeItems = new ConcurrentQueue<CopyParameterBundle>();
var erroredItems = new ConcurrentQueue<CopyParameterBundle>();
//Logger logger = new Logger(sLogPath);
//logger.Write("Starting copy");
Task.Factory.StartNew(() =>
{
Parallel.ForEach(CopyParameters,
po,
(i, loopState, localSum) =>
{
localSum = retryCount;
do
{
try
{
//Go off and attempt to copy the file
DoWork(i);
//Incrememt total count by 1 if successfull
i.copyResults.TransferTime = DateTime.Now;
i.copyResults.TransferComplete = true;
completeItems.Enqueue(i);
//logger.Write("Copied file from: " + i.SourcePath + "\\" + i.SourceFile + " => " + i.DestPath + "\\" + i.SourceFile);
break;
}
catch (Exception ex)
{
//this.richTextBox1.AppendText("[-] Exception on: " + i.SourcePath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + System.Environment.NewLine);
//Exception was thrown when attempting to copy file
if (localSum == 0)
{
//Given up attempting to copy. Log exception in exception queue
exceptions.Enqueue(ex);
this.SetErrorText(exceptions.Count());
//Write the error to the screen
this.Invoke((MethodInvoker)delegate
{
this.richTextBox1.AppendText("[-] Exception on: " + i.SourcePath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + System.Environment.NewLine);
i.copyResults.TransferComplete = false;
i.copyResults.TransferTime = DateTime.Now;
i.copyResults.exceptionMsg = ex;
erroredItems.Enqueue(i);
//logger.Write("ERROR COPYING FILE FROM : " + i.SourcePath + "\\" + i.SourceFile + " => " + i.DestPath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + " => " + ex.Source);
});
}
//Sleep for specified time before trying again
Thread.Sleep(retryDelay);
localSum--;
}
//Attempt to Repeat X times
} while (localSum >= 0);
//Check cancellation token
po.CancellationToken.ThrowIfCancellationRequested();
Interlocked.Increment(ref TotalProcessed);
this.SetProcessedText(TotalProcessed);
//Update Progress Bar
this.Invoke((MethodInvoker)delegate
{
this.progressBar1.Value = (TotalProcessed);
});
});
//aTimer.Stop();
this.Invoke((MethodInvoker)delegate
{
this.label9.Text = "Process: Writing Log";
});
WriteLog(sLogPath, completeItems, erroredItems);
this.Invoke((MethodInvoker)delegate
{
this.label9.Text = "Process: Done!";
});
if (exceptions.Count == 0)
MessageBox.Show("Done!");
else
MessageBox.Show("Done with errors!");
EnableDisableButton(this.button2, true);
EnableDisableButton(this.button4, false);
});
}
What happened is most likely that the antivirus was aware of the virus file, so when it detected that a change in the file system (moving the file) occurred, it terminated the program because by moving the virus to a different location in your computer, it could cause problems (since it's a virus). It was flagged as dropper, basically a type of program that is designed to install the virus.
Edit: i forgot to mention that to solve the problem you will most likely need to license your program.

Event Log not creted, even with administrative privileges

I'm using the following code:
public static void ErrorRoutine(Exception e, string obj, string method)
{
//EventLog.Delete("Info3070"); // uncomment this line to delete log
EventLog log = new EventLog();
log.Source = "Helpdesk Case1";
log.Log = "Info3070";
if (e.InnerException != null)
{
log.WriteEntry("Error in Models, object = " + obj + ", method = " + method + ", inner exception = " +
e.InnerException.Message, EventLogEntryType.Error);
throw e.InnerException;
}
else
{
log.WriteEntry("Error in Models, object = " + obj + ", method = " + method + ", message = " + e.Message,
EventLogEntryType.Error);
throw e;
}
}
It is supposed to log errors in an Event Log in the Windows Event Viewer but will not do so even when run as administrator.
You must define your source first, I suspect "Helpdesk Case1" is not known.
If event log with the specified parameters doesn't exist, you should create it before:
const string sSource = "Helpdesk Case1";
const string sLog = "Info3070";
if (!EventLog.SourceExists(sSource))
EventLog.CreateEventSource(sSource, sLog);
EventLog log = new EventLog { Source = sSource, Log = sLog };

Categories