File access error with FileSystemWatcher - c#

I am using File Watcher (.NET) and always getting an below error-
file is being used by another process.
The above error only comes in Network sharing, i.e. Watch Directory is shared and if someone puts the file into that directory then only this error occurs. It works fine when I put the file from my m/c to watch directory(locally).
This is how my below code looks, the error comes in first line itself. I have tried all the solutions given on net but nothing seems to working. The only solution worked when I put Thread.Sleep(500), but after that it is unable to pick the next file. Any suggestion would be a great help.
try
{
using (Stream stream = File.Open(xmlPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
XmlTextReader xmlTextReader = new XmlTextReader(stream);
document = XDocument.Load(xmlTextReader);
........ // my code
xmlTextReader.Close();
stream.Close();
}
}
catch (Exception exception)
{
EventLog.WriteEntry("Application", exception.ToString(), EventLogEntryType.Error);
}

I think you will find that the the file is not acessable hence why the wait works..
Take a look at this code and see if this helps...
// Consider having a List<String> named _changedFiles
private void OnChanged(object source, FileSystemEventArgs e)
{
lock (_changedFiles)
{
if (_changedFiles.Contains(e.FullPath))
{
return;
}
}
// do your stuff
System.Timers.Timer timer = new Timer(1000) { AutoReset = false };
timer.Elapsed += (timerElapsedSender, timerElapsedArgs) =>
{
lock (_changedFiles)
{
_changedFiles.Remove(e.FullPath);
}
};
timer.Start();
}
from:
FileSystemWatcher Changed event is raised twice

Related

Move file from the stage to archive (Issue :- Atleast one file doesnt move)

I have a file watcher, once the file is created in the stage directory, I want to move it to archive. When i manually copy file from a folder to stage, atleast one of those files doesnt move
Here is my code
class Program
{
public static String stagepath = #"C:\Users\a\Desktop\\stage\";
public static String archivePath = #"C:\Users\a\Desktop\archive\";
static void Main(string[] args)
{
MonitorDirectory(stagepath);
Console.ReadKey();
}
public static void MonitorDirectory(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.Created += FileCreated;
watcher.EnableRaisingEvents = true;
}
private static void FileCreated(object sender, FileSystemEventArgs e)
{
if (!FileIsReady(stagepath+e.Name)) return;
System.IO.File.Move(stagepath + e.Name, archivePath + e.Name);
//Console.WriteLine("File is available");
}
private static bool FileIsReady(string path)
{
try
{
using (var file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
{
return true;
}
}
catch (IOException)
{
return false;
}
}
}
}
I understand there are similar questions asked, but none of them is resolving my issue, so posted again.
One option would be to subscribe to FileSystemWatcher.Changed event. In your case you can just change the event name and the code should work.
But of course, there's no universal way of detecting that the writer had finished his work. You must invent one which will suit your needs. For example:
Assume the writer will always lock the file only once. This means
that the watcher can start his work right after the file becomes
unlocked (that's what you get if you follow my advice)
Use a checksum or any other method of validating file consistency. If
you can accomplish that, you should be able to avoid unnecessary
locks and exceptions. Just don't move the file until it is valid.
Think about why you're moving a file right after it was created
somewhere else. Most of the time you should avoid that kind of
operations, because the writer starts doing somewhat a strange job.

FileSystemWatcher: System.IO.IOException ("File used by another process")

Currently i'm working on an application, that should watch a specific directory for changes (say a new file was created) and then in turn upload the file to Sharepoint. Thatfore i'm using the FileSystemWatcher class which throws an event with the path to the created file, which in turn i use in another method to upload the file. The problem is: While in debug mode in Visual Studio i realized that the first file i create in the watched directory gets uploaded perfectly, even if i drag multiple files into the directory at once all are uploaded, BUT when i do it one file after another i get an exception that the second file is already in use. So i drag File1.txt into the directory, it works, but then, when i drag file2.txt into the directory right after i get a System.IO.IOException while trying to create a filestream to upload to Sharepoint telling me that file2.txt is in use by another process.
The code for the FileSystemWatcher:
public void StartWatcher()
{
FileSystemWatcher fsw = new FileSystemWatcher(this.path);
fsw.IncludeSubdirectories = true;
fsw.EnableRaisingEvents = true;
fsw.Created += new FileSystemEventHandler(CreateFile);
try
{
while (true)
{
fsw.WaitForChanged(WatcherChangeTypes.All);
}
}
catch
{ }
fsw.EnableRaisingEvents = false;
}
The CreateFile() method called by
fsw.Created += new FileSystemEventHandler(CreateFile);
looks like this:
private void CreateFile(object sender, FileSystemEventArgs e)
{
path = String.Format(e.FullPath);
filename = Path.GetFileName(path);
Stream fs = File.OpenRead(#path);
SPAPI spobj = new SPAPI();
spobj.SPUploader(fs, filename);
fs.Close();
}
The exception is thrown at
Stream fs = File.OpenRead(#path);
BUT only when a second file is dragged into the directory after the first one. The strange thing is that not the first file is in use, but the second one that i want to open as a stream. So it's not the stream that is still open and causing the exception. It seems that the second file is in use by the FileSystemWatcher. But why does the first file work just fine but the exception is just thrown when a second file is dragged into the directory?
You can modify and use like this. I hope this helps you
private void CreateFile(object sender, FileSystemEventArgs e)
{
int until = 5;
int i = 0;
bool success = false;
while (!success && i < until)
{
try
{
path = String.Format(e.FullPath);
filename = Path.GetFileName(path);
using (Stream fs = File.OpenRead(#path);)
{
SPAPI spobj = new SPAPI();
spobj.SPUploader(fs, filename);
}
success = true;
}
catch
{
i++;
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
}

How to monitor a logfile that seems to be open all the time (much like notepad++ does)?

I'm trying to build a small program to monitor my pfirewall.log, but I can't seem to open it.
I found quite many (simple) answers, that all kinda say
// use FilesystemWatcher
// open FileStream
// read from last position to end
// output new lines
The problem here is: The file seems to always be opened by another process already. I guess that's the windows process writing to the file, since it's getting written to all the time, as Notepad++ shows me.
Which means, Notepad++ can for some reason do what I can not: Read the file despite it being opened already.
I initialize my monitor in the constructor:
public FirewallLogMonitor(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException("Logfile not found");
this.file = path;
this.lastPosition = 0;
this.monitor = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path));
this.monitor.NotifyFilter = NotifyFilters.Size;
}
And try to read the file on monitor.Changed event:
private void LogFileChanged(object sender, FileSystemEventArgs e)
{
using (FileStream stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader reader = new StreamReader(stream))
{
stream.Seek(this.lastPosition, SeekOrigin.Begin);
var newLines = reader.ReadToEnd();
this.lastPosition = stream.Length;
var filteredLines = filterLines(newLines);
if (filteredLines.Count > 0)
NewLinesAvailable(this, filteredLines);
}
}
It always throws the IOException on new FileStream(...) to tell me the file is already in use.
Since Notepad++ does it, there has to be a way I can do it too, right?
**Edit: ** A button does this:
public void StartLogging()
{
this.IsRunning = true;
this.monitor.Changed += LogFileChanged;
this.monitor.EnableRaisingEvents = true;
}
**Edit2: ** This is not a duplicate of FileMode and FileAccess and IOException: The process cannot access the file 'filename' because it is being used by another process, since that one assumes I have control over the writing process. Will try the other suggestions, and report back with results.
If i understand your question you can use the notepad++ itself with a plugin to monitor you need to go to:
plugins -> Document Moniter -> Start to monitor
if you dont have this plugin you can download it here:
http://sourceforge.net/projects/npp-plugins/files/DocMonitor/

The process cannot access the file 'C:\PCLtoMove\print.pcl' because it is being used by another process. Windows service

I have a folder named PCLtoMove. I have applied a filewatcherSystem in this folder to move files from this folder to another folder. first time when I start windows service It works fine but from next time it gives exception-
The process cannot access the file 'C:\PCLtoMove\fileName.pcl' because it is being used by another process.
my code to move file is -
private void SavionFileWatcher_Created(object sender, System.IO.FileSystemEventArgs e)
{
try
{
string sourcePath = e.FullPath;
string destination = ConfigurationManager.AppSettings["destination"] + e.Name;
File.Move(sourcePath, destination);
}
catch (Exception ex)
{
this.EventLog.WriteEntry(ex.Message, EventLogEntryType.Information);
}
}
please tell me whats wrong I am doing.
I got the solution by adding following code to the above code. Its confirms that the file is completely moved or created.
FileStream fs = new FileStream(sourcePath, FileMode.Open, FileAccess.ReadWrite);
fs.ReadByte();
fs.Seek(0, SeekOrigin.Begin);
fs.Dispose();
File.Move(sourcePath,destination);
break;

Detect when PowerPoint has finished saving a file

I am having problems saving a PowerPoint file in an add-in I am writing.
Basically, I need to save the currently open presentation as a wmv and then FTP it to an external server... sounds easy eh?
I have worked out how to save the currently open presentation as a wmv.
I have also got code to check if a file is open so I can tell when the "save" process is complete.
But the code just goes into an infinite loop. The wmv starts for get written but never goes beyond 0kb.
If I remove the line
checkfile(exportPath, exportName);
it works just fine... otherwise it just stays in a loop.
This is the code I have so far...
using System;
using System.Windows.Forms;
using Office = Microsoft.Office.Core;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.IO;
namespace PowerPointAddIn2
{
public partial class LoginPanel : UserControl
{
public LoginPanel()
{
InitializeComponent();
}
private void LoginPanel_Load(object sender, EventArgs e)
{
}
private void btnLogin_Click(object sender, EventArgs e)
{
string exportName = "video_of_presentation";
string exportPath = #"C:\{0}.wmv";
// Export the currently open presentation
PowerPoint.Application ppApplication = null;
ppApplication = new PowerPoint.Application();
ppApplication.Activate();
ppApplication.ActivePresentation.SaveAs(String.Format(exportPath, exportName), PowerPoint.PpSaveAsFileType.ppSaveAsWMV, Office.MsoTriState.msoTrue);
checkfile(exportPath, exportName);
MessageBox.Show("Finished");
}
protected void checkfile(string exportPath, string exportName)
{
FileInfo f = new FileInfo(String.Format(exportPath, exportName));
while (IsFileLocked(f) == true) { System.Threading.Thread.Sleep(5000); }
MessageBox.Show("Finished");
}
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
}
}
Based on a previous thread I posted I also tried Thread.Join() to see if I could simply wait for the save thread to finish before I continued but it didn't pause at all while the file was being saved so I ended up with the same result.
Any help/pointers would be very much appreciated.
Thanks
The PowerPoint Application object has a ppMediaTaskStatus property that should return the info you need for this. You can get the various values using the Object Browser in the PPT VBA IDE .

Categories