Deleting Files - Skip Files in Use - c#

I'm trying to delete the files in a directory, but I get errors when attempting to remove the files which are currently in use. Is there a way to skip the files that are currently in use and delete the rest of them? Thanks.
foreach(var file in Directory.GetFiles(tempPath))
{
File.Delete(file);
}
That's the code I have so far, not sure how to go about this.

you can check by try catch
private bool IsLocked(string filePath)
{
FileInfo f = new FileInfo(filePath);
FileStream stream = null;
try
{
stream = f.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException ex)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
return false;
}
public void RemoveFile(string folderPath)
{
foreach (var file in Directory.GetFiles(folderPath))
{
if (!IsLocked(file))
{
File.Delete(file);
}
}
}

I think the easier way is surrounding your code with a try-catch block. Something like this:
foreach(var file in Directory.GetFiles(tempPath))
{
try
{
File.Delete(file);
}
catch (Exception)
{
//Decide what you want to do here, you can either
//ask user to retry if the file is in use
//Or ignore the failure and continue, or...
}
}

Wrap File.Delete in a try { } catch block

Related

Wait for HttpPostedBaseFile SaveAs to complete

I want to wait for SaveAs to complete before continuing, I've tried a few different solutions but it still just continues immediately, not waiting for the upload to complete. What I've tried:
Creating a wrapping function to return an int (this is what I found on Stack Overflow):
public int SaveFile(HttpPostedFileBase file, string filePath)
{
if (!System.IO.File.Exists(filePath))
{
try
{
file.SaveAs(filePath);
return 1;
}
catch
{
}
}
return 0;
}
And running this in my main method:
var success = SaveFile(hpf, savedFileName);
I also tried checking to see if the file is ready:
while (!IsFileReady(filePath))
{
System.Threading.Thread.Sleep(500);
}
Calling this:
[Authorize(Roles = "L,I")]
public static bool IsFileReady(String sFilename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = System.IO.File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (inputStream.Length > 0)
{
return true;
}
else
{
return false;
}
}
}
catch (Exception)
{
return false;
}
}
Again, no luck. I just need to make sure file.SaveAs(...) waits until the file completes uploading to continue.

C# Deleting Files - IOException handling

In reference to Deleting All Files how can we handle IO.Exceptions to quietly "skip" those files that the delete can't do? Should we use a try/catch or is there something built-in?
Looks like a simple question but I'm actually having trouble finding a solution for it on the net...
try:
public void DeleteDirectoryFiles(DirectoryInfo dirInfo)
{
foreach(FileInfo files in dirInfo.GetFiles())
{
try
{
files.Delete();
}
catch(IOException ex)
{
// code to handle
}
}
}
Of course. To update the code from the original answer by John Hartsock:
public void DeleteDirectoryFolders(DirectoryInfo dirInfo, bool ignoreIfFailed = false){
foreach (DirectoryInfo dirs in dirInfo.GetDirectories())
{
try
{
dirs.Delete(true);
}
catch (IOException)
{
if (!ignoreIfFailed)
{
throw;
}
}
}
}
public void DeleteDirectoryFiles(DirectoryInfo dirInfo, bool ignoreIfFailed = false) {
foreach(FileInfo files in dirInfo.GetFiles())
{
try
{
files.Delete();
}
catch (IOException)
{
if (!ignoreIfFailed)
{
throw;
}
}
}
}
public void DeleteDirectoryFilesAndFolders(string dirName, bool ignoreIfFailed = false) {
DirectoryInfo dir = new DirectoryInfo(dirName);
DeleteDirectoryFiles(dir, ignoreIfFailed);
DeleteDirectoryFolders(dir, ignoreIfFailed);
}
You can call it like this:
DeleteDirectoryFilesAndFolders(folder, true); // ignore on error
DeleteDirectoryFilesAndFolders(folder, false); // throw exception
DeleteDirectoryFilesAndFolders(folder); // throw exception
The only way to handle an exception quietly would be a try catch with nothing in the catch block.
Be sure to only catch the exception you're expecting though (i.e., catch (IOException)) else you might mask some other problem that you weren't aware of.

How to implement "retry/abort" mechanism for writing files that may be used by another process?

This is really short question. I don't understand try-catch mechanism completely.
This is my current code:
public static void WriteText(string filename, string text)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
}
}
Background:
Im writing application that shares configuration files with another application.
I need some dialog messagebox with "retry" and "abort" buttons, when that file is used by other application. When that message will appear - I will close that other application and I will try to rewrite that file again by pressing "Retry" button.
Whatr we have is using a counter for re-tries and possibly a thread sleep.
So something like
int tries = 0;
bool completed = false;
while (!completed)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
completed = true;
}
catch(Exception exc)
{
tries++;
//You could possibly put a thread sleep here
if (tries == 5)
throw;
}
}
Even though there's a good answer already I'll submit one that's more tuned towards the OP's question (let the user decide instead of using a counter).
public static void WriteText(string filename, string text)
{
bool retry = true;
while (retry)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
retry=false;
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
// change your message box to have a yes or no choice
// yes doesn't nothing, no sets retry to false
}
}
}
If you need more info on how to implement the messagebox check out the following links;
http://msdn.microsoft.com/en-us/library/0x49kd7z.aspx
MessageBox Buttons?
I would do it like that:
public static void WriteText(string filename, string text, int numberOfTry = 3, Exception ex = null)
{
if (numberOfTry <= 0)
throw new Exception("File Canot be copied", ex);
try
{
var file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch (Exception exc)
{
WriteText(filename,text,--numberOfTry,ex);
}
}
I like it more like this (example tries to save a RichTextBox on close and allows retrying save or aborting close):
protected override void OnClosing(CancelEventArgs e)
{
if (richTextBox_Query.Modified)
{
DialogResult result;
do
try
{
richTextBox_Query.SaveFile(
Path.ChangeExtension(Application.ExecutablePath, "sql"),
RichTextBoxStreamType.UnicodePlainText);
result = DialogResult.OK;
richTextBox_Query.Modified = false;
}
catch (Exception ex)
{
result = MessageBox.Show(ex.ToString(), "Exception while saving sql query",
MessageBoxButtons.AbortRetryIgnore);
e.Cancel = result == DialogResult.Abort;
}
while (result == DialogResult.Retry);
}
base.OnClosing(e);
}

Cannot write to a closed TextWriter

I am trying to write text to my txt file. After the first write the application crash with error
Cannot write to a closed TextWriter
My list contains links that the browser opens and I want to save all of them in txt file (like a log).
My code:
FileStream fs = new FileStream(
"c:\\linksLog.txt", FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
for (int i = 0; i < linksList.Count; i++)
{
try
{
System.Diagnostics.Process.Start(browserType, linksList[i]);
}
catch (Exception) { }
using (sw)
{
sw.WriteLine(linksList[i]);
sw.Close();
}
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked)
{
try
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName == getProcesses)
{
process.Kill();
}
}
}
catch (Exception) { }
}
}
You're in a for loop, but you close and dispose of your StreamWriter on the first iteration:
using (sw)
{
sw.WriteLine(linksList[i]);
sw.Close();
}
Instead, remove that block, and wrap everything in one using block:
using (var sw = new StreamWriter(#"C:\linksLog.txt", true)) {
foreach (var link in linksList) {
try {
Process.Start(browserType, list);
} catch (Exception) {}
sw.WriteLine(link);
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked) {
var processes = Process.GetProcessesByName(getProcesses);
foreach (var process in processes) {
try {
process.Kill();
} catch (Exception) {}
}
}
}
}
The line
using (sw)
closes/disposes your StreamWriter.
Since you are looping, you dispose an already disposed StreamWriter.
Better to close the StreamWriter outside the loop, after all write operations are finished.
In addition, catching exceptions and ignoring the caught exception is almost always a bad idea. If you can't handle an exception, do not catch it.
The problem is that you are closing you Stream in the loop, should done only after...
FileStream fs = new FileStream("c:\\linksLog.txt", FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
for (int i = 0; i < linksList.Count; i++)
{
try
{
System.Diagnostics.Process.Start(browserType, linksList[i]);
}
catch (Exception)
{
}
// Removed the using blocks that closes the stream and placed at the end of loop
sw.WriteLine(linksList[i]);
Thread.Sleep((int)delayTime);
if (!cbNewtab.Checked)
{
try
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName == getProcesses)
{
process.Kill();
}
}
}
catch (Exception)
{ }
}
}
sw.Close();
That's because you are, indeed, closing your stream in the middle of the loop. You have the using (sw) block in the middle, which will work fine in the first run through the for loop, and then crash. To fix it, just drop the sw.Close() call, and move the using to be outside the for loop:
Dont write the sw.Close() in your code because if the file is closed the code cannot read the file.

How should I initialize variables that will be used in a try/catch/finally block?

If I am using a try/catch/finally block where and how should I initialize variables? For example say I'm trying to use a FileStream . I want to catch any exceptions thrown while creating or using the stream. Then regardless of whether there were any problems or not I want to ensure any stream created is closed.
So I'd do something like this:
System.IO.FileStream fs;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
However this gives me an error in the finally block saying unassigned local variable fs. Yet, if I change the declaration of fs to System.IO.FileStream fs = null it works.
Why do I need to explicitly set fs to null? I've also tried declaring fs in the try block, but then I get the error The name fs does not exsist in the current context in finally block.
BTW: I know I could use a Using block, but the point of my question is to understand the correct usage of a try/catch/finally block.
Assign fs = null;
System.IO.FileStream fs = null;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
See section 5.3 of the specification.
http://msdn.microsoft.com/en-us/library/aa691172(VS.71).aspx
At a given location in the executable
code of a function member, a variable
is said to be definitely assigned if
the compiler can prove, by static flow
analysis, that the variable has been
automatically initialized or has been
the target of at least one assignment.
With your try/catch/finally, the assignment of the try block cannot be guaranteed when you attempt to access the object in the finally block. As you have seen, you can meet the requirement by assigning an initial value to the variable (null, in this case).
The C# design team feels that making sure you explicitly initialize things is a good idea. I tend to agree; I've been bitten by bugs from uninitialized variables enough in C++.
Initializing fs to null is the correct usage. The compiler wants to ensure that you are reading only initialized variables, to avoid serious mistakes. And it cannot garantee that the initialization in your try block is ever executed
The purist in me would want to do something like this:
void DoSomethingWithStream()
{
try
{
System.IO.FileStream fs = new System.IO.FileStream(#"C:\test.txt", System.IO.FileMode.Open);
try
{
// do something with the file stream
}
catch (Exception ex)
{
// handle exceptions caused by reading the stream,
// if these need to be handled separately from exceptions caused by opening the stream
}
finally
{
// FileStream.Close might throw an exception, so put FileStream.Dispose in a separate try/finally
fs.Dispose();
}
}
catch (Exception ex)
{
// handle exceptions that were either thrown by opening the filestream, thrown by closing the filestream, or not caught by the inner try/catch
}
}
Taken to the extreme, though, this would be messy:
void DoSomethingWithStream_PartDeux()
{
try
{
System.IO.FileStream fs = new System.IO.FileStream(#"C:\test.txt", System.IO.FileMode.Open);
try
{
try
{
// do something with the file stream
}
catch (Exception ex)
{
// handle exceptions caused by reading the stream,
// if these need to be handled separately from exceptions caused by opening the stream
}
finally
{
fs.Close();
}
}
finally
{
// FileStream.Close might throw an exception, so put FileStream.Dispose in a separate try/finally
fs.Dispose();
}
}
catch (Exception ex)
{
// handle exceptions
}
}
Accessing a database could be even worse:
void DoSomethingWithDatabase()
{
var connection = new System.Data.SqlClient.SqlConnection("Connect to mah database!");
try
{
var command = new System.Data.SqlClient.SqlCommand("Get mah data!", connection);
connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
try
{
// read data from data reader (duh)
}
finally
{
reader.Close();
}
}
finally
{
reader.Dispose();
}
}
finally
{
connection.Close();
}
}
finally
{
connection.Dispose();
}
}
But then, in most cases I don't really see a need to explicitly close your streams / connections / data readers if you are going to dispose of them immediately afterward (unless you're just really paranoid). So, the database code above could just as easily be this:
void DoSomethingWithDatabase_PartDeux()
{
using (var connection = new System.Data.SqlClient.SqlConnection("Connect to mah database!"))
{
var command = new System.Data.SqlClient.SqlCommand("Get mah data!", connection);
connection.Open();
using(var reader = command.ExecuteReader())
{
// read data from data reader (duh)
}
}
}
Maybe I've just been tainted from coding with Dr. Wily's evil API. Using the initialize-variable-to-null trick doesn't work with his framework:
void DoSomethingWithDrWilyEvilBoobyTrap()
{
Dr.Wily.Evil.BoobyTrap trap = null;
try
{
trap = new Dr.Wily.Evil.BoobyTrap(Dr.Wily.Evil.Evilness.Very);
// do something with booby trap
}
catch (Exception ex)
{
// handle exceptions
}
finally
{
if (trap != null) // Exception thrown here!
trap.Dispose(); // Exception thrown here as well!
}
}
Here's a sneak peek at some of the souce code in his API:
public enum Evilness
{
Slight,
Moderate,
Very,
}
class BoobyTrap : IDisposable
{
public Evilness Evil { get; protected set; }
public BoobyTrap(Evilness evil)
{
this.Evil = evil;
}
public void DoEvil()
{
// ... snip (sorry, it's just too evil) ...
}
public static bool IsNull(BoobyTrap instance)
{
throw new Exception("I bet you thought this function would work, didn't you? Well it doesn't! You should know whether or not your variables are null. Quit asking me!");
}
public static bool operator !=(BoobyTrap x, object y)
{
if(y == null)
throw new Exception("You cannot check if an instance of a BoobyTrap is null using the != operator. Mwahahaha!!!");
return x.Equals(y);
}
public static bool operator ==(BoobyTrap x, object y)
{
if (y == null)
throw new Exception("You cannot check if an instance of a BoobyTrap is null using the == operator. Mwahahaha!!!");
return x.Equals(y);
}
#region IDisposable Members
public void Dispose()
{
switch (this.Evil)
{
case Evilness.Moderate:
case Evilness.Very:
throw new Exception("This object is cursed. You may not dispose of it.");
}
}
#endregion
}
You are close. I'd set the declaration to be null.
System.IO.FileStream fs = null;
try
{
fs = new System.IO.FileStream("C:\test.txt", System.IO.FileMode.Open);
//do something with the file stream
}
catch (Exception exp)
{
//handle exceptions
}
finally
{
//ERROR: "unassigned local variable fs"
if (fs != null)
{
fs.Close();
}
}
I think that is very acceptable when you can't use a using statement.

Categories

Resources