I would like to tag some existing mp3 with taglib#.
I have the following error message:
"The process cannot access the file because it is being used by another process."
I don't know what kind of process it can be. I can access any mp3 files on any of my hard drives, I also can use the properties of the file, but I cannot save changes.
This is the code.
OpenFileDialog f = new OpenFileDialog();
if ((bool)f.ShowDialog())
{
try
{
if ( f.OpenFile() != null)
{
TagLib.File file = TagLib.File.Create(f.FileName);
file.Tag.Album = "Album1";
file.Save();
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
else
{
MessageBox.Show("Problem occured, try again later");
}
Could you help me?
Thanks
f.OpenFile() creates a FileStream around the file.
Since you never close this stream, the file remains open.
Don't do that.
Related
I have a solution that acts as an interface between two systems, reading files that were dropped on an FTP site and importing any orders/products/etc. into the target system.
When a file is picked up, it is moved to a temp file in the same location, and then the contents are read into an XmlDocument.
string[] files = Directory.GetFiles(pickupFolder, fileFilter, SearchOption.TopDirectoryOnly);
foreach (string pathToFile in files)
{
FileInfo srcFile = new FileInfo(pathToFile);
string tmpFilename = Path.Combine(srcFile.DirectoryName, $"~{Path.GetFileNameWithoutExtension(srcFile.Name)}.tmp");
srcFile.MoveTo(tmpFilename);
XmlDocument srcXml = new XmlDocument();
try
{
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
{
srcXml.Load(fs);
}
}
catch (XmlException ex)
{
throw new FileException($"Invalid XML in {srcFile.Name}.", ex);
}
}
Very, very occassionally, the interface will attempt to open the file so that it can be loaded into the XmlDocument while the moving process has not been completed, throwing an IOException. Is there some way to prevent this from happening?
What is the best way to create something like this that needs to iterate through and process files?
The file move operation will throw an exception when the FTP server is still having a lock on the file. That may happen when the file is still being uploaded and is not yet completed, but is "visible" on the disk. Such collisions are rare, but they happen.
Start by checking your FTP server settings and features if it can hide incomplete files during upload. Another way is if you control the system that uploads files, you could upload them with a special "do not download" extension, and rename them after the upload is complete (atomic operation). Finally, as other pointed out, you could simply catch this specific exception and retry with a delay.
As others have pointed out, if process runs periodically, you can simply wrap it with try / catch block:
try
{
srcFile.MoveTo(tmpFilename);
}
catch (Excption ex)
{
// Write log entry if required
continue;
}
If it's a one-off process, then you'll need to periodically attempt MoveTo until file is released and can be moved. Something like this may work:
int maxRetries = 60;
int retries = 0;
bool success = false;
while (retries < maxRetries)
{
try
{
retries++;
srcFile.MoveTo(tmpFilename);
success = true;
break;
}
catch (Excption ex)
{
// Log the error if required
Thread.Sleep(1000); // Wait 1 second
}
}
if (success == fale)
{
// Log the error
continue; // Skip the file if its still not released
}
The code tries to access the file every second during a minute. If it fails, then program skips this file and continues to next.
I have a requirement where
when uploading the files to the pick-up folder, files will be uploaded
with a .tmp (or)._ (or) .filepart extensions and after successful
upload files will be renamed to the original file name.
This is required to avoid any partial pick-up of .xml files by settings on SFTP folder side.
For eg. Upload with .xml.tmp and after successful upload, rename the files to .xml
Any idea on how to achieve this in MVC, C#.
I prefer to do this in a separate folder entirely. And then do a move to the pickup folder.
Then renaming is not required.
private bool IsFileLocked()
{
try
{
FileStream fs = File.OpenWrite(FilePath);
fs.Close();
return false;
}
catch (Exception)
{
Console.WriteLine("File locked: " + FileName);
return true;
}
}
To check if the file is locked prior to attempting to send, might also work, or in conjunction.
I was talking about generating a local file first, once its completely done being written, simply use the File.Move() method, so you move the newly generated file from its "safe" folder, into the pickup folder, that the SFTP is continually looking for files in.
If it is picking up a file you are receiving, then it's just the check prior to attempting to do anything with it.
First of all, once you receive the file stream from the post, the upload is "already" successful (most likely). Therefore, the moment you have the data from the post, you should already be good to write it. The only point I can remotely see here is that, the remote process either checks .xml files constantly so let's say if the .xml file is quite large, and let's assume (which wont be the case) it takes a while for you to write the stream to the remote destination, they do not want to check just part of the xml, they need all of it. If that is the case, something like the following should work (modify it for your needs);
[HttpPost]
public ActionResult Upload()
{
if (Request.Files.Count < 1)
{
ViewBag.Result = "No files were provided";
return PartialView("Error");
}
foreach (string F in Request.Files)
{
var FInfo = Request.Files[F];
var TemporaryFileName = $"{FInfo.FileName}.tmp";
try
{
using (var FStream = new FileStream(TemporaryFileName, FileMode.Create, FileAccess.Write))
{
FInfo.InputStream.CopyTo(FStream);
}
}
catch (Exception e)
{
ViewBag.Result = e.Message;
return PartialView("Error");
}
finally
{
System.IO.File.Move(TemporaryFileName, $"{FInfo.FileName}");
}
}
ViewBag.Result = "Files have been uploaded";
return View();
}
I am working on an application which reads paths of all the text files from a folder into a list. It reads each file, creates a temporary output file, overwrites the original file with temporary output file and deletes the temporary output file.
Following is my code:
foreach (string lF in multipleFiles)
{
int lineNumber = 0;
using (StreamReader sr = new StreamReader(lF))
{
using (StreamWriter sw = new StreamWriter(lF + "Output"))
{
while (!sr.EndOfStream)
{
//LOGIC
sw.WriteLine(line);
}
}
}
File.Copy(lF + "Output", lF, true);
//File.Delete(lF + "Output");
try
{
File.Delete(lF + "Output"); <--- ERROR HERE
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I am unable to delete the temporary output file due to the following error:
{"The process cannot access the file '' because it is being
used by another process."}
The error does not occur for every file but only a few. None of the files are open or being used by any other application.
How can the temporary file be deleted?
UPDATE: Refereed to Does FileStream.Dispose close the file immediately?
Added Thread.Sleep(1) before File.Delete(), The issue still exists. Tried increasing the sleep value to 5. No luck.
You always run the risk that an virus scanner or some other driver in the stack still holds on to that file or its directory entry. Use some retry mechanisms but that still doesn't guarantee you'll be able to remove that file as the file operations are not atomic, so any process can open that file between your calls trying to delete it.
var path = lf + "Output";
// we iterate a couple of times (10 in this case, increase if needed)
for(var i=0; i < 10; i++)
{
try
{
File.Delete(path);
// this is success, so break out of the loop
break;
} catch (Exception exc)
{
Trace.WriteLine("failed delete #{0} with error {1}", i, exc.Message);
// allow other waiting threads do some work first
// http://blogs.msmvps.com/peterritchie/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program/
Thread.Sleep(0);
// we don't throw, we just iterate again
}
}
if (File.Exists(path))
{
// deletion still not happened
// this is beyond the code can handle
// possible options:
// store the filepath to be deleted on startup
// throw an exception
// format the disk (only joking)
}
Code slightly adapted from my answer here but that was in a different context.
How can i write to a text file outside of the scope it is created in?
say for example my code looks a bit like this:
try
{
StreamWriter file = new StreamWriter(path);
}
catch (NullReferenceException) //unable to create file
{
MessageBox.Show("Cannot create file");
//end program
}
file.WriteLine("hello world!") //error at compile time here
// "The name 'file' does not exist in current context"
if the file cannot be created the program is ended straight away
can i do this or not?
Sadly it is very complex to use the using pattern in this case. This is a "bad" thing...
StreamWriter file = null;
try
{
try
{
file = new StreamWriter(path);
}
catch (Exception ex) //unable to create file
{
MessageBox.Show("Cannot create file");
return;
}
file.WriteLine("hello world!");
}
finally
{
if (file != null)
{
file.Dispose();
}
}
Note that I don't like this code for TWO reasons:
You can't easily use the using pattern. I consider the using pattern to be VERY important
You are supposing that if you can create the file then everything will go correctly... This is WRONG. EVERY time you write to the file something could go kaboom (throw an Exception)... The disk could be full for example... Even simply closing a file you have written to could go kaboom (for example StreamWriter is buffered, so it doesn't write immediately. When you close it the buffer is written, but NOW the disk is full :-) )
this is may be helpful you..
StreamWriter file;
try
{
file = new StreamWriter(path);
}
catch (NullReferenceException) //unable to create file
{
MessageBox.Show("Cannot create file");
return;
//end program
}
file.WriteLine("hello world!") //error at compile time here
//"The name 'file' does not exist in current context"
I am trying to delete a folder but am getting the following error message:
The process cannot access the file .it is being used by another process.
string target_dir="D:\\projectpath\\page";
if (Directory.Exists(target_dir))
Directory.Delete(target_dir, false);
How can I resolve this error?
It looks like the file is locked by some other process. This could happen if when reading/writing to it you forgot to dispose the stream reader/writer and you leaked the unmanaged handler to the file.
For example if you used the following code to read from the file:
StreamReader reader = new StreamReader(fileName);
string contents = reader.ReadToEnd();
and you never release the reader, the file will be locked. The proper way is to wrap IDisposable resources such as Streams and StreamReaders in using statements:
using (StreamReader reader = new StreamReader(fileName))
{
string contents = reader.ReadToEnd();
}
If on the other hand the file is locked by some other external process to your application then there's very little you could do about it, other than killing this process.
I think on the surface, your problem should be apparent: the file is in use by something else, so you can't delete the directory it resides in. If there was a way to "force delete" the file, it could cause other programs to crash. I'd recommend catching the error and either logging it or displaying it to the user, so they can decide if they really want to delete the in-use file.
If you MUST delete the file, you could take a look at:
Using C#, how does one figure out what process locked a file?
And once you know what the process is, you can then kill it, which should free up the file. Again, this isn't a good practice and should only be used in exceptional circumstances.
To delete the diectory you must have the correct Permissions.
var target_dir = "D:\\projectpath\page";
var isWriteAccess = false;
try
{
var collection = Directory.GetAccessControl(target_dir)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
if (collection.Cast<FileSystemAccessRule>().Any(rule => rule.AccessControlType == AccessControlType.Allow))
{
isWriteAccess = true;
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
MessageBox.Show("no access to directory.");
// Handle here close and kill the blocking process
}
else
{
Directory.Delete(target_dir, false);
}
}