I get a "file in use by another process exception" when creating a email and wants to add this file as attachment.
When i try to copy the same file to an other directory there is no problem. (state of the file is still the same)
does anybody knows whats happening here? and how i can solve this?
here is the code:
public Boolean AddAttachment(string filePath, string newName = "")
{
try
{
MimeData mime = _message.AddAttachment(filePath);
if (!string.IsNullOrEmpty(newName))
{
mime.FileName = newName;
}
return true;
}
catch (Exception err)
{
if (! AddAttachmentIfInUse(filePath, newName))
{
AddErrorInfo(err.Message, "AddAttachment", err.Source);
return false;
}
else
{
return true;
}
}
}
private Boolean AddAttachmentIfInUse(string filePath, string newName = "")
{
byte[] data;
string contentType = "";
string fileName = Path.GetFileName(filePath);
try
{
using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
data = new byte[stream.Length];
stream.Read(data, 0, (int)stream.Length);
}
// data = File.ReadAllBytes(filePath);
MimeData mime = new MimeFactory().CreateMimeData();
mime.Data = data;
mime.ContentType = ContentType.Parse(contentType);
if (!string.IsNullOrEmpty(newName))
{
mime.FileName = newName;
}
else{
mime.FileName = fileName;
}
return true;
}
catch (Exception err)
{
AddErrorInfo(err.Message, "AddAttachmentIfInUse", err.Source);
return false;
}
}
thanks
The 1st function gets the the error in _message.AddAttachment(..) ...
I had to change the 2nd function: do not use File.Open() but use FileStream() and now it's working well.
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
}
Related
So I'm getting exception "Process cannot access file because its used by another process.
The exception will show when i call this particular method:
public async static Task<bool> DownloadFileFromFTP(string PathToFile, string AppName)
{
return await Task.Run(() => {
if (File.Exists("settings.xml"))
{
XmlSerializer xs = new XmlSerializer(typeof(Information));
FileStream read = new FileStream("settings.xml", FileMode.Open, FileAccess.Read, FileShare.Read);
Information info = (Information)xs.Deserialize(read);
try
{
FtpClient client = new FtpClient(info.HDSynologyIP);
string a = info.FtpPassword;
string FTPPassword = EncryDecryptor.Decrypt(a);
client.Credentials = new NetworkCredential(info.FtpUsername, FTPPassword);
client.Connect();
bool finish = client.DownloadFile(#info.Downloads + "\\" + AppName, PathToFile, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry);
if (finish == true)
{
client.Disconnect();
read.Close();
return true;
}
else
{
client.Disconnect();
read.Close();
return false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
read.Close();
}
read.Close();
}
else
{
MessageBox.Show("Missing settings.xml file");
return false;
}
return false;
});
}
And call it in another class like this:
await General_Functions.DownloadFileFromFTP("Ultra_Script/Basic_SW/Adobe_Reader.exe", "Adobe_Reader.exe");
It wasn't asynchronous before but i had to remake it into asynchronous method. But i think I'm closing reader and client correctly. Can it be problem of async method? Because i don't had this problem before i made it asynchronous.
Can someone explain what I'm doing wrong?
Note, I am using FluentFTP from https://github.com/robinrodricks/FluentFTP .
use using to terminate the file reader process
using(FileStream read = new FileStream("settings.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
{
// your code here.....
}
I have download files by returning as stream like below using WCF rest service.
Stream stream = null;
var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
try
{
Directory.CreateDirectory(newFolderPath);
DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
string fullPath = newFolderPath + "\\" + fileName;
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
if (byteData != null)
{
fileStream.Write(byteData,0,byteData.Length);
fileStream.Close();
}
if (WebOperationContext.Current != null)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
}
}
stream = File.OpenRead(fullPath);
return stream;
}
catch (Exception exception)
{
return null;
}
The above code works perfectly and can download the file in browser. But i have to delete the file after return the stream. So i have try to close and delete the file including the directory in finally block like below
finally
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
}
Full Method code
public Stream DownloadAttachment(string engagementId, string documentId)
{
Stream stream = null;
var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
try
{
Directory.CreateDirectory(newFolderPath);
DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
string fullPath = newFolderPath + "\\" + fileName;
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
if (byteData != null)
{
fileStream.Write(byteData,0,byteData.Length);
fileStream.Close();
}
if (WebOperationContext.Current != null)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
}
}
stream = File.OpenRead(fullPath);
return stream;
}
catch (Exception exception)
{
return null;
}
finally
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
}
}
After adding this code file is not downloaded in client.Is there any way to delete the file?Please help me to resolve this
You can delete the file in OperationContext.OperationCompleted as shown in http://devdump.wordpress.com/2008/12/07/disposing-return-values/
OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
});
Change your method to this.
public void DownloadAttachment(string engagementId, string documentId, Action<Stream> processFile)
and instead of returning the stream call the processFile Action
processFile(stream);
This way you're not leaving the method in order to process the file. You will need to restructure the calling code in order to process the file though.
How to Zip a folder using ICSharplib.
Is there any way I can add a encrypt password while zipping it ?
There is no option that I can use any other dll. Have to use only ICSharplib.
Currently I am using this code block
private static void CompressFiles(string folderPath) {
string zipOutput = #"C:\temp\myoutput.zip";
try {
using (ZipOutputStream zs = new ZipOutputStream(File.Create(zipOutput))) {
zs.SetLevel(9); // 0-9 (9 being best compression)
foreach (string file in Directory.GetFiles(folderPath)) {
ZipEntry entry = new ZipEntry(Path.GetFileName(file));
entry.DateTime = DateTime.Now;
using (FileStream fs = File.OpenRead(file)) {
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
entry.Size = buffer.Length; // This is very important
zs.PutNextEntry(entry);
zs.Write(buffer, 0, buffer.Length);
}
}
zs.Finish();
zs.Close();
}
}
catch { throw; }
}
It can zip all the files in the folder.
But What I want is to zip the whole folder.
Like the folders in side that folder also be included in the zip file .
Thanks in advance
Use the FastZip object.
ICSharpCode.SharpZipLib.Zip.FastZip z = new ICSharpCode.SharpZipLib.Zip.FastZip();
z.CreateEmptyDirectories = true;
z.CreateZip("F:\\ZipTest.zip", "F:\\ZipTest\\", true, "");
if (File.Exists("F:\\ZipTest.zip"))
Console.WriteLine("Done");
else
Console.WriteLine("Failed");
I use following code:
public static bool ZipIt(string sourcePath, string destinationPath)
{
List<string> ListOfFiles = GetListOfFiles(sourcePath);
try
{
string OutPath = destinationPath + ".zip";
int TrimLength = (Directory.GetParent(sourcePath)).ToString().Length;
TrimLength += 1;
//remove '\'
FileStream ostream;
byte[] obuffer;
ZipOutputStream oZipStream = new ZipOutputStream(System.IO.File.Create(OutPath));
oZipStream.Password = EncodePassword("Password");
oZipStream.SetLevel(9);
// 9 = maximum compression level
ZipEntry oZipEntry;
foreach (string Fil in ListOfFiles.ToArray()) // for each file, generate a zipentry
{
oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength));
oZipStream.PutNextEntry(oZipEntry);
if (!Fil.EndsWith(#"/")) // if a file ends with '/' its a directory
{
ostream = File.OpenRead(Fil);
obuffer = new byte[ostream.Length];
ostream.Read(obuffer, 0, obuffer.Length);
oZipStream.Write(obuffer, 0, obuffer.Length);
ostream.Close();
}
}
oZipStream.Finish();
oZipStream.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
public static string EncodePassword(string originalPassword)
{
Byte[] encodedBytes;
encodedBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
return BitConverter.ToString(encodedBytes);
}
public byte[] GetFile(string filename)
{
FileStream aStream = File.Open(filename, FileMode.Open, FileAccess.Read);
BinaryReader binReader = new BinaryReader(aStream);
binReader.BaseStream.Position = 0;
byte[] binFile = binReader.ReadBytes(Convert.ToInt32(binReader.BaseStream.Length));
binReader.Close();
return binFile;
}
I run this method for a number of filepaths, problem is whenever a file cannot be accessed with File.Open (because it is used by another process) I get:
'aStream.Position' threw an exception of type 'System.ObjectDisposedException'
on the following line:
binReader.BaseStream.Position = 0;
And seldom I get
{System.IO.IOException: The process can not access the file '\folder\file.txt' because it is being used by another process.}
This is the exception I want. So why is the object disposed most of the times?
Note: I first had the FileStream line in a using statement but removed it because I thought that might have disposed the object. But the problem remains.
Edit: Using Compact Framework, which doesn't have ReadAllBytes.
Maybe that part of the time your FileStream is throwing the IOException whenever your file is in use, and at other times, perhaps, you are getting the ObjectDisposedException because your array is not initialized.
Obviously, I can not test this theory.
See if you can copy-n-paste this one with good results:
public byte[] GetFile(string filename)
{
byte[] binFile = null;
try
{
using (var aStream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
BinaryReader binReader = new BinaryReader(aStream);
binFile = new byte[binReader.BaseStream.Length];
binReader.BaseStream.Position = 0; // <= this step should not be necessary
binFile = binReader.ReadBytes(binReader.BaseStream.Length);
binReader.Close();
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return binFile;
}
Be sure to check for null return variables!
EDIT:
I wrote (what I think is) a simpler version. I tested it, and it seems to work OK. I also prefer Read() overload to ReadBytes(), because I know how much data was pulled in.
First, is the test function that calls the method for every image in my Pictures folder:
public void Test() {
DirectoryInfo dir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
foreach (var subDir in dir.GetDirectories()) {
if (-1 < subDir.Name.ToLower().IndexOf("pictures")) {
foreach (var file in subDir.GetFiles()) {
byte[] data = GetFile(file.FullName);
if (data != null) {
Console.WriteLine(data.Length);
}
}
}
}
}
public byte[] GetFile(string filename) {
byte[] result = null;
try {
if (File.Exists(filename)) {
int len = 0;
FileInfo file = new FileInfo(filename);
byte[] data = new byte[file.Length];
using (BinaryReader br = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read))) {
len = br.Read(data, 0, data.Length);
br.Close();
}
if (0 < len) {
if (len == data.Length) {
return data;
} else {
// this section of code was never triggered in my tests;
// however, it is good to keep it as a backup.
byte[] dat2 = new byte[len];
Array.Copy(data, dat2, len);
return dat2;
}
}
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return result;
}
I don't see any reason why these would not work - unless you are having an int overflow.
Just use this:
byte[] contents = File.ReadAllBytes(filename);
Why don't you simply use
public byte[] GetFile(string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
Just for fun, you could even define an extension method
public static class Extensions
{
public static byte[] GetFile(this string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
}
so you could do byte[] myfile = filename.GetFile();.
Remember you must check that return is not null before proceed:
if (myfile != null)
{
// Do what you need
}
I was trying to test a resumable download using c#. I found that add range will help by looking at some blogs. But in the following code add range have no meaning.
Guys Suggest me how to solve the issue.
What method will be effective to make a Resumable download??
HttpWebRequest myrequest = null;
HttpWebResponse myresponse = null;
private int interval=2048;
public bool set_url(string todonwloads,string tosaves)
{
this.todownload = todonwloads;
this.tosave = tosaves;
return true;
}
public bool start_download()
{
myrequest = (HttpWebRequest)WebRequest.Create(this.todownload);
// it the following code.
//If i dont write addrange. It will download same portion of the file.
myrequest.AddRange(4000,8000);
try
{
myresponse = (HttpWebResponse)myrequest.GetResponse();
if (myresponse.StatusCode == HttpStatusCode.OK)
{
Stream ReceiveSteam = myresponse.GetResponseStream();
FileStream fs = new FileStream(
this.tosave,
FileMode.Create,
FileAccess.Write,
FileShare.None);
int reads;
byte[] buffer = new byte[this.interval];
while ((reads = ReceiveSteam.Read(
buffer,
0,
this.interval)) > 0)
{
fs.Write(buffer, 0, reads);
}
return true;
}
}
catch (WebException ex)
{
throw ex;
}
finally
{
if (myresponse != null)
{
myresponse.Close();
}
}
return false;
}
You currently create and overwrite the file every time you download a section of the file:
// Overwrites the file each time -\/
... = new FileStream(this.tosave, FileMode.Create, ...
You instead need to open or create the file using FileMode.OpenOrCreate, then seek to the last section of the file you wrote to:
// seek to the last end offset, you'll need to save this somehow
fs.Seek(lastOffset, SeekOrigin.Begin);
int reads;
byte[] buffer = new byte[this.interval];
while ((reads = ReceiveSteam.Read(buffer, 0, this.interval)) > 0)
{
fs.Write(buffer, 0, reads);
lastOffset += reads;
}