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

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

Related

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:

Login and Register using System.IO

Don't Know What's wrong but I can't Access even It created a directory.. This is my code
private void btnRegister_Click(object sender, EventArgs e)
{
try
{
var sw = new System.IO.StreamWriter("E:Praisey\\" + txtAcc.Text + "\\Login.ID");
sw.Write(txtAcc.Text + "\n" + txtZipCode.Text);
sw.Close();
}
catch(System.IO.DirectoryNotFoundException ex)
{
System.IO.Directory.CreateDirectory("E:Praisey\\" + txtAcc.Text + "\\Login.ID");
var sw = new System.IO.StreamWriter("E:Praisey\\" + txtAcc.Text + "\\Login.ID");
sw.Write(txtAcc.Text + "\n" + txtZipCode.Text);
sw.Close();
}
}
it always getting error! The error is
UnauthorizedAccessException was unhandled
Access to the path 'E:\Praisey\48492995\Login.ID' is denied.
As I see from your catch block, "E:Praisey\\" + txtAcc.Text + "\\Login.ID" is actually a directory. You must also add the file name to the path.
var sw = new System.IO.StreamWriter("E:Praisey\\" + txtAcc.Text + "\\Login.ID\\filename.txt");
This error occurs (had it yesterday too) when the Directory does not exist. You need to create it before starting your StreamWriter.
if (!Directory.Exists("E:Praisey\\" + txtAcc.Text))
Directory.CreateDirectory("E:Praisey\\" + txtAcc.Text);

Best practice error handling in Global asax

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.");

how to make streamwriter create a url link in a non-system folder in C#

I am having a problem with creating a url link (shortcut) in a non-system folder. The link is getting created properly on the desktop without any problem, but if I change the path to a non-system folder the folder remains empty and there is no error message either. Is there a restriction on the paths allowed? Why is there no error message? Code is given below:
private void urlShortcutToFolder(string linkName, string linkUrl)
{
//string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
//using (StreamWriter writer = new StreamWriter(deskDir + "\\" + linkName + ".url"))
string nonSystemDir = "C\\Downloads";
using (StreamWriter writer = new StreamWriter(nonSystemDir + "\\" + linkName + ".url"))
{
writer.WriteLine("[InternetShortcut]");
writer.WriteLine("URL=" + linkUrl);
writer.Flush();
}
}
If you are running your application locally then your code is right. It must work.
if your application is running oline then you have to set permission for Internet user on the folder where you want to save your url.
Hope this will solve your problem
For as far I know this no proper path:
string nonSystemDir = "C\\Downloads";
Shouldn't it be
string nonSystemDir = "C:\\Downloads";
or more readable
string nonSystemDir = #"C:\Downloads";
You could also add System.IO.Directory.Exists like so
private void urlShortcutToFolder(string linkName, string linkUrl)
{
//string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
//using (StreamWriter writer = new StreamWriter(deskDir + "\\" + linkName + ".url"))
string nonSystemDir = #"C:\Downloads";
if(!System.IO.Directory.Exists(nonSystemDir))
{
throw New Exception("Path " + nonSystemDir + " is not valid");
}
using (StreamWriter writer = new StreamWriter(nonSystemDir + "\\" + linkName + ".url"))
{
writer.WriteLine("[InternetShortcut]");
writer.WriteLine("URL=" + linkUrl);
writer.Flush();
}
}

C# WinForms App - Debug Error - Length can not be less than zero. Parameter Name: Length

In debug mode, while running the C# WinForms App, I successfully select multiple files through the OpenFileDialog, which is then displayed in the logging window, these files are copied to a temp directory and I believe I get the error when trying to convert the excel files to csv. I get the following runtime debug error:
Error: You may not have permission to read the file or it may be corrupt.
Reported Error: Length Can not be less than zero.
Parameter Name: Length.
How do I fix this error?
Here's my code on MainForm.cs
// Consolidate Button Click Commands that executes if there are no user input errors
void ExecuteConsolidate()
{
string consolidatedFolder = targetFolderBrowserDialog.SelectedPath;
string tempfolder = targetFolderBrowserDialog.SelectedPath + "\\tempDirectory";
string sFile = "";
//create a temporary directory to store selected excel and csv files
if (!Directory.Exists(tempfolder))
{
Directory.CreateDirectory(tempfolder);
}
try
{
for (int i = 0; i < listBoxSourceFiles.Items.Count; i++)
{
sFile = listBoxSourceFiles.Items[i].ToString();
// Copy each selected xlsx files into the specified Temporary Folder
System.IO.File.Copy(textBoxSourceDir.Text + "\\" + sFile, tempfolder + #"\" + System.IO.Path.GetFileName(sFile), true);
Log("File " + sFile + " has been copied to " + tempfolder + #"\" + System.IO.Path.GetFileName(sFile));
} // ends foreach
Process convertFilesProcess = new Process();
// remove xlsx extension from filename so that we can add the .csv extension
string csvFileName = sourceFileOpenFileDialog.FileName.Substring(0, sourceFileOpenFileDialog.FileName.Length - 3);
// command prompt execution for converting xlsx files to csv
convertFilesProcess.StartInfo.WorkingDirectory = "I:\\CommissisionReconciliation\\App\\ConvertExcel\\";
convertFilesProcess.StartInfo.FileName = "ConvertExcelTo.exe";
convertFilesProcess.StartInfo.Arguments = " ^ " + targetFolderBrowserDialog.SelectedPath + "^" + csvFileName + ".csv";
convertFilesProcess.StartInfo.UseShellExecute = true;
convertFilesProcess.StartInfo.CreateNoWindow = true;
convertFilesProcess.StartInfo.RedirectStandardOutput = true;
convertFilesProcess.StartInfo.RedirectStandardError = true;
convertFilesProcess.Start();
//Process that creates all the xlsx files in temp folder to csv files.
Process consolidateFilesProcess = new Process();
// command prompt execution for CSV File Consolidation
consolidateFilesProcess.StartInfo.WorkingDirectory = targetFolderBrowserDialog.SelectedPath;
consolidateFilesProcess.StartInfo.Arguments = "Copy *.csv ^" + csvFileName + ".csv";
consolidateFilesProcess.StartInfo.UseShellExecute = false;
consolidateFilesProcess.StartInfo.CreateNoWindow = true;
consolidateFilesProcess.StartInfo.RedirectStandardOutput = true;
consolidateFilesProcess.StartInfo.RedirectStandardError = true;
consolidateFilesProcess.Start();
Log("All Files at " + tempfolder + " has been converted to a csv file");
Thread.Sleep(2000);
StreamReader sOut = consolidateFilesProcess.StandardOutput;
sOut.Close();
}
catch (SecurityException ex)
{
// The user lacks appropriate permissions to read files, discover paths, etc.
MessageBox.Show("Security error. The user lacks appropriate permissions to read files, discover paths, etc. Please contact your administrator for details.\n\n" +
"Error message: " + ex.Message + "\n\n");
}
catch (Exception ex)
{
// Could not load the image - probably related to Windows file system permissions.
MessageBox.Show("You may not have permission to read the file, or " +
"it may be corrupt.\n\nReported error: " + ex.Message);
}
try
{
if (Directory.Exists(tempfolder))
{
Directory.Delete(tempfolder, true);
}
}
catch (SecurityException ex)
{
// The user lacks appropriate permissions to read files, discover paths, etc.
MessageBox.Show("Security error. The user lacks appropriate permissions to read files, discover paths, etc. Please contact your administrator for details.\n\n" +
"Error message: " + ex.Message + "\n\n");
}
catch (Exception ex)
{
// Could not load the image - probably related to Windows file system permissions.
MessageBox.Show("You may not have permission to read the file, or " +
"it may be corrupt.\n\nReported error: " + ex.Message);
}
finally
{
// reset events
m_EventStopThread.Reset();
m_EventThreadStopped.Reset();
// create worker thread instance;
m_WorkerThread = new Thread(new ThreadStart(this.WorkerThreadFunction));
m_WorkerThread.Start();
}
} // ends void ExecuteConsolidate()
Thanks for looking! :)
All helpful answers will receive up-votes! :)
If you need more information like the workerThread method or the app.config code, let me know!
It is most likely this line that is causing your problem:
string csvFileName = sourceFileOpenFileDialog.FileName.Substring(0, sourceFileOpenFileDialog.FileName.Length - 3);
Why not use Path.GetFileNameWithoutExtension to get the filename without extension?
I suppose it dies here:
string csvFileName = sourceFileOpenFileDialog.FileName.Substring(0,
sourceFileOpenFileDialog.FileName.Length - 3);
Write it like this and see if it helps:
string selectedFile = sourceFileOpenFileDialog.FileName;
string csvFileName = Path.Combine(Path.GetDirectoryName(selectedFile),
Path.GetFileNameWithoutExtension(selectedFile));
This is the translation of your line.
But I think, you really wanted to just have the filename without path:
string csvFileName =
Path.GetFileNameWithoutExtension(sourceFileOpenFileDialog.FileName);
And to break on All Errors:
Go to "Debug" -> Exceptions (or CTRL+ALT+E)
Tick "Thrown" on Common Language Runtime Exceptions
Once done with you fix, dont forget to reset it (Reset All button)

Categories