• 0

File Access Question (C#)


Question

Hello everyone.

I have an application that zips up some files and then attempts to send that in an e-mail as an attachment.

I have noticed that if the zip file is small it works fine (A few KB's), but the zip is generally between 1 and 2 MB's, and at that size (Which is still rather small) it fails. I get an error that it failed due to the target of an invocation.

I'm assuming that perhaps the zip file is not being released prior to the e-mail being generated when it's larger? I have both the zip creation and e-mail generation in their own backGroundWorkers.

I've been working on this for a good while now, and it doesn't seem to matter if my AntiVirus is running (I thought maybe it was trying to scan the zip), if I do a thread.Sleep, if I choose to send the mail upon the click of another button, etc. In fact, curiously, I created a test application that ONLY sends the zip file. This works perfectly. However, if I use my main application to create the zip file, this test application will be unable to send the zip until after the main application is closed. I really think that the file is not being released, but I don't know why, or from what. The backgroundWorker that is creating the zip is completing successfully (That is where I was originally calling the SendMail event).

My question is what the suggested course of action would be for doing something like this. I've never had an issue with accessing a file like this before.

I really appreciate any suggestions anyone may have for this. I can post whatever code you want, but there's a lot of it, so I'm not sure what all you would want.

Thanks Again,

Link to comment
Share on other sites

11 answers to this question

Recommended Posts

  • 0

My first train of thought would be to remove it from the backgroundworker and just run the whole thing in a single thread, see if that makes a difference. I would say its worth having a look at your code too and making sure that you're releasing any file handles that you're creating in the process.

Might be worth posting some relevant code (if you can) so we can take a look.

Link to comment
Share on other sites

  • 0
what is you're code for creating the zip file?

i like to use the ShapZipLib .NET Zip Library personally, have you given that a go?

can't really do much without knowing what your code is up to so, i await the response :)

Thank you very much for your response. I haven't tried that. I've been using DotNetZip Library (http://dotnetzip.codeplex.com/). It's been really good, and after mentioning this to the developer, it doesn't appear to be related to any of DotNetZip's code...

Here is the code for creating the zip:

		void CompileZip()
		{
			try
			string tempFolder = Path.GetTempPath();
			if (File.Exists(tempFolder + @"\JobFile.zip"))
			{
					SendMail()
			 }
			 else
			 {
					string[] tempDirectory = { tempFolder };
					CompileZipbackgroundWorker2.RunWorkerAsync(tempDirectory);
					Application.DoEvents();
			 }
		}

		private void CompileZipbackgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
		{
			BackgroundWorker worker = sender as BackgroundWorker;
			string[] tempDirectory = (string[])e.Argument;
			string FilePath = tempDirectory[0].ToString();

			string current = Directory.GetCurrentDirectory();
			System.IO.Directory.SetCurrentDirectory(FilePath);

			//int progress = 10;

			using (ZipFile zip = new ZipFile())
			{
				//Add Generated Files to zip
				zip.AddItem("JobFile");
				zip.AddItem("Resources");

				worker.ReportProgress(20);
				worker.ReportProgress(90);

				//Save the zip
				zip.Save(Path.Combine(FilePath, "JobFile.zip"));
			}
			Application.DoEvents();
			worker.ReportProgress(100);
			System.IO.Directory.SetCurrentDirectory(current);
		}

		private void CompileZipbackgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			SubProgressBar1.Value = e.ProgressPercentage;
		}

		private void CompileZipbackgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			if ((e.Cancelled == true))
			{
				MessageBox.Show("Canceled", "Error", MessageBoxButtons.OK);
			}

			else if (!(e.Error == null))
			{
				MessageBox.Show(e.Error.Message, "Error", MessageBoxButtons.OK);
			}

			else
			{
				string tempFolder = Path.GetTempPath();
				string zipedFile = tempFolder + @"\JobFile.zip";
				if (File.Exists(zipedFile))
				{
					try
					{
						SubProgressBar1.Style = ProgressBarStyle.Continuous;

						SendMail();
					}
					catch (Exception ex)
					{
						MessageBox.Show(ex.Error.Message, "Error", MessageBoxButtons.OK);

						return;
					}
				}
			}
		}

Here's the code for sending the E-Mail:

		void SendMail()
		{
			try
			{
				SubProgressBar1.Style = ProgressBarStyle.Marquee;

				string ccState = "";
				if (CCCheckBox1.Checked == true)
				{
					ccState = "true";
				}
				else
				{
					ccState = "false";
				}

				string urgentState = null;
				if (UrgentCheckBox1.Checked == true)
				{
					urgentState = "true";
				}
				else
				{
					urgentState = "false";
				}

				string attachState = null;
				if (SubmitStepTB1.Text == "Attach")
				{
					attachState = "true";
				}
				else
				{
					attachState = "false";
				}

				string[] SendMail = { CustLastNameTB1.Text, CustFirstNameTB1.Text, UserCB1.Text, UserEMailTB1.Text, AssemblyVersion, JobFileNotesTB1.Text, ccState, urgentState, attachState };
				SendMailbackgroundWorker1.RunWorkerAsync(SendMail);
			}
			catch
			{

			}
		}

		private void SendMailbackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
		{
			try
			{
				string[] SendMail = (string[])e.Argument;
				string CustLastName = SendMail[0].ToString();
				string CustFirstName = SendMail[1].ToString();
				string User = SendMail[2].ToString();
				string UserEMail = SendMail[3].ToString();
				string SoftVersion = SendMail[4].ToString();
				string JobFileNotes = SendMail[5].ToString();
				string CCState = SendMail[6].ToString();
				string UrgentState = SendMail[7].ToString();
				string attachState = SendMail[8].ToString();

				//Send E-Mail on click of Button
				MailMessage theMailMessage = new MailMessage("FromEMail", "ToEMail");

				BackgroundWorker worker = sender as BackgroundWorker;
				//worker.ReportProgress(25);

				//Generate the message body
				string messageBody = "New Job File Information Added For:  " + CustLastName + ", " + CustFirstName;
				messageBody += Environment.NewLine + "";
				messageBody += Environment.NewLine + "From:  " + User;
				messageBody += Environment.NewLine + "E-Mail:  " + UserEMail + "  (CC'd =  " + CCState + ")";
				messageBody += Environment.NewLine + "";
				messageBody += Environment.NewLine + "Software Version:  " + SoftVersion;
				messageBody += Environment.NewLine + "";
				messageBody += Environment.NewLine + @"\\server\shared\job files\" + CustLastName + ", " + CustFirstName + @"\";
				messageBody += Environment.NewLine + "";
				messageBody += Environment.NewLine + "Notes:  " + JobFileNotes;

				//worker.ReportProgress(50);

				//Set the property of the message body and subject body
				theMailMessage.Body = messageBody;
				theMailMessage.Subject = "New Job File for " + CustLastName + ", " + CustFirstName;

				//Set the CC Property
				if (CCState == "true")
				{
					MailAddress copy = new MailAddress(UserEMail);
					theMailMessage.CC.Add(copy);
				}

				//Set the Urgent Property
				if (UrgentState == "true")
				{
					theMailMessage.Priority = MailPriority.High;
				}

				//Set the Attachment Property
				if (attachState == "true")
				{
					string tempFolder = Path.GetTempPath();
					theMailMessage.Attachments.Add(new Attachment(tempFolder + @"\JobFile.zip"));
				}

				//worker.ReportProgress(75);

				//E-Mail Credentials and Sending
				SmtpClient theClient = new SmtpClient("smtp.1and1.com");
				System.Net.NetworkCredential theCredential = new
				System.Net.NetworkCredential("FromEMail", "Password");
				theClient.Credentials = theCredential;
				theClient.Send(theMailMessage);

				//worker.ReportProgress(100);
			}
			catch
			{
				MessageBox.Show("The Mail Message was unable to be sent.", "Error", MessageBoxButtons.OK);
			}
		}

		private void SendMailbackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			SubProgressBar1.Value = e.ProgressPercentage;
		}

		private void SendMailbackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			SubProgressBar1.Increment(100);

			Application.DoEvents();
		}

That should be everything. I'm curious what your thoughts might be. The SendMail code does work (As evidenced by the test project I created), but not if the file has just been created.

Thanks Again. If there is anything else you might want to look at, please let me know. I really, REALLY appreciate the help. I'm just completely out of ideas here and it's driving me nuts...

Edited by M_Lyons10
Link to comment
Share on other sites

  • 0

yeah.. iv only scanned the code (it's my lunch break ;)) but i would seriously try removing the background worker processes and seeing if you can get it to work without them. they do seem a little redundant..

or have you already done this? :o

Link to comment
Share on other sites

  • 0

Thank you very much for the suggestion. I will try that to see if it is able to send the mail, but the reason I had initially used a backgroundWorker was because the UI was locking up. Additionally, as the zip process takes some time, the code was attempting to send the mail prior to the zip being completed.

Thanks Again,

Link to comment
Share on other sites

  • 0

yeah i understand why the background process is there, but i think for the purposes of working out whats wrong it should be chopped.

it might also be related to having one end background process call another background process.. but i'm unsure

Link to comment
Share on other sites

  • 0
yeah i understand why the background process is there, but i think for the purposes of working out whats wrong it should be chopped.

it might also be related to having one end background process call another background process.. but i'm unsure

Thanks for your help and everything. I did rewrite the code yesterday / last night and was testing it. It locks up the UI something fierce, but it does work. So, the backgroundWorker is not terminating? Or is somehow holding onto the file? I thought that when a backgroundWorker completed it was done / terminated. I'm not sure what the difference would possibly be. I had run the application a bit ago while watching the file access of the zip file using Process Monitor and it was closing...

You say it's the "sendmail" that's failing. Many ISPs restrict the size of e-mails, so it's possible it's being rejected by the server because the payload is too large.

I realize that some do restrict attachment size, but I've never seen such a small limit (1 - 2 MB's). Just to test that though, I did make a test application that sends the zip file that has already been compiled. It works perfectly so long as the application that created the zip has exited.

Thanks Again,

Link to comment
Share on other sites

  • 0

first thing first ... if you get an exception and you are working with backgroundworkers, check the InnerException property - it should encapsulate what exception was raised in the background worker.

Secondly, since you have your send mail worker code wrapped up nicely in a try...catch clause, your assumption that the file is not release properly is void (+ the fact that you are using "using" clause when building the zip file helps in that it will release any stuff used by ZipFile immediatly (if coded properly by the DotNetZip dev))

I "tried" to replicate as close as possible the requirements of the code you posted (basically a progress bar, a button and a few checkboxes) to try to replicate the issue, and from what I can tell, you are trying to Increment the progress bar value when it is in Marquee Mode.

Hinty: Its a good idea to use BackgroundWorker for these kind of situations - situations that involve a UI and length operations so stick to it :) Just when you are handling exceptions, try not to use catch-all exception handlers so that if there is some serious "unhandled" stuff going on in your worker, an exception will be raised, and that can help you out to find the cause and fix it.

Link to comment
Share on other sites

  • 0
first thing first ... if you get an exception and you are working with backgroundworkers, check the InnerException property - it should encapsulate what exception was raised in the background worker.

Secondly, since you have your send mail worker code wrapped up nicely in a try...catch clause, your assumption that the file is not release properly is void (+ the fact that you are using "using" clause when building the zip file helps in that it will release any stuff used by ZipFile immediatly (if coded properly by the DotNetZip dev))

I "tried" to replicate as close as possible the requirements of the code you posted (basically a progress bar, a button and a few checkboxes) to try to replicate the issue, and from what I can tell, you are trying to Increment the progress bar value when it is in Marquee Mode.

Hinty: Its a good idea to use BackgroundWorker for these kind of situations - situations that involve a UI and length operations so stick to it :) Just when you are handling exceptions, try not to use catch-all exception handlers so that if there is some serious "unhandled" stuff going on in your worker, an exception will be raised, and that can help you out to find the cause and fix it.

Thank you very much for your response. I will take a look at the InnerException property. I will look into the progressBar increment as well. That may have been an error on my part. The error being thrown the Visual Studio is that the mail message timed out. I will try to improve the catches to help a bit further. It's an odd error and I am not sure what the solution would really be. Programs perform processes like this all the time, but it's really giving me a headache.

Link to comment
Share on other sites

This topic is now closed to further replies.