Beginner programmer here....hope it makes sense :)
I have created a console app that I need to run in the background and watch a directory for any changes/rename events. I have used the FileWatcher class and have added the event handlers as so:
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
and defined the handlers then below like so:
private static void OnChanged(object source, FileSystemEventArgs e)
{
//specify what is done when a file is changed, created or deleted
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
//specify what is done when a file is renamed
Console.WriteLine("File {0} renamed to {1}", e.OldFullPath, e.FullPath);
I would like to be able to add in some code that dumps any files that have changed/renamed into another local directory but I dont know where to start. At the minute the console is writing back the Fullpath to me but ideally I would like it to copy that into another folder
Thanks Guys
You can use string destination = Path.Combine(localDirectory, e.Name); to create the destination path and File.Copy(e.FullPath, destination); actually copies the file.
Note that a process may still be writing to the file when you get the Changed event, so you may get an exception or copy half-processed data. Also you should think about what to do if the file already exists in your local directory (notice the File.Copy(string, string, bool overwrite) overload).
Also make sure you check if the changed item is a file and not a directory (for instance, by using File.Exists(e.FullPath).
Related
I need to copy a file after it's been created and changed twice.
I have no idea how to do it, except by using 3 FileSystemWachers. First one on creation and two for changing.
Is there any easier way?
The FileSystemWatcher has several events that you can use to listen to different types of events on the file system. There is also a NotifyFilter property which you can use to specify which event types it should monitor.
So you don't need to use three different watchers; one would suffice. You just need some form of counter to keep track of how many changes were made to the file. Here's a quick example:
Dictionary<string, int> changeCounter = new Dictionary<string, int>();
...
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"C:\Path\To\Some\Folder";
watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite;
watcher.Created += OnCreated;
watcher.Changed += OnChanged;
...
private void OnCreated(object source, FileSystemEventArgs e)
{
changeCounter.Add(e.FullPath, 0);
}
private void OnChanged(object source, FileSystemEventArgs e)
{
if (changeCounter.ContainsKey(e.FullPath))
{
changeCounter[e.FullPath]++;
if (changeCounter[e.FullPath] == 2)
{
CopyFile(e.FullPath);
}
}
}
This would only call CopyFile after the watcher detected a file creation event and two file change events for a single file. You may also want to modify handle deletions, too, in case you are worried about files being created once, edited, deleted, recreated, and edited—this would trigger CopyFile even though, technically, the file has only been edited once after it was created.
I'm going to start off by apologizing if this is a duplicated question. There were a ton of FileSystemWatcher questions but I didn't see any that addressed my issue.
Ok, so I have a console application in C# that is monitoring a directory, which we will call Root. Root has many subfolders. The purpose of this application is to write to a log file if any .csv files are create, modified, or deleted within Root or any of its subfolders. I currently have this working fine, sort of. The only problem is that when a .csv file is created, modified, or deleted it actually raises the event for all 3.
For example, if I create a file in Root called test.csv, the log file would look like this:
10/04/2012: File F:/Root/test.csv Created
10/04/2012: File F:/Root/test.csv Changed
10/04/2012: File F:/Root/test.csv Created
10/04/2012: File F:/Root/test.csv Deleted
I'm not sure whats going on, so here is the code that sets up the FileSystemWatcher
_watchFolder.Path = ConfigurationManager.AppSettings["RootToWatch"];
_watchFolder.Filter = ConfigurationManager.AppSettings["FileNameToWatch"];
_watchFolder.NotifyFilter = NotifyFilters.FileName
| NotifyFilters.LastWrite;
_watchFolder.IncludeSubdirectories = true;
_watchFolder.Changed += new FileSystemEventHandler(OnChanged);
_watchFolder.Created += new FileSystemEventHandler(OnChanged);
_watchFolder.Deleted += new FileSystemEventHandler(OnChanged);
_watchFolder.Renamed += new RenamedEventHandler(OnRenamed);
try
{
_watchFolder.EnableRaisingEvents = true;
}
catch (ArgumentException ex)
{
AbortMonitoring(ex.Message);
}
And here is my OnChanged event (Renamed is same but has different argument)
protected static void OnChanged(object sender, FileSystemEventArgs e)
{
//compile message to insert into log file.
string message = "File: " + e.FullPath + " " + e.ChangeType;
UpdateLogFile(message);
}
Just add a handler only for the changed event. It should gather all change types. The other types of events like created are there if you want the event to be raised only on a particular change type.
watchFolder.IncludeSubdirectories = true;
_watchFolder.Changed += new FileSystemEventHandler(OnChanged);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Detecting moved files using FileSystemWatcher
I was looking for a solution to watch a directory and notify my app whenever a new file is moved into the directory. The Obvious solution was to use FileSystemWatcher class of the .NET.
But the problem is , it raises a event a new file is created/deleted in the folder but does not raises event when a file is moved/copied into the folder.
Can anyone tell me what could be the cause of such behavior.
my code is
static void Main(string[] args)
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"D:\New folder";
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
I used FileSystemWatcher in one of my Home application. But FileSystemWatcher do not have any move or copy detection events as per my knowledge.
As per MSDN
Copying and moving folders
The operating system and FileSystemWatcher object interpret a
cut-and-paste action or a move action as a rename action for a folder
and its contents. If you cut and paste a folder with files into a
folder being watched, the FileSystemWatcher object reports only the
folder as new, but not its contents because they are essentially only
renamed.
For more information click here.
What I did was monitoring the parent folder and sub folders and logged every changes in it.
To include sub directories I used the following property.
watcher.IncludeSubdirectories=true;
Some googling suggesting to use timer to detect changes. But I don't know how effective it is.
We have users that rename the shortcut file on their desktop to our application. What is the best way to delete/modify the shortcut based on targetpath if the icon changes for the application? In other words, I'm having a hard time locating the file name because it keeps getting changed.
It's a nice question and I surprised that nobody answered it correctly in 10 years.
The code below iterate through all links in given folder and finds one with TargetPath pointing to the currently executing WinForms app.
Add COM reference to your project to Windows Script Host Object Model.
using IWshRuntimeLibrary;
private static void DeleteShortcuts(string path)
{
// Example for path: Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
foreach (var fileName in Directory.GetFiles(path, "*.lnk"))
{
WshShell shell = new WshShell();
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(fileName);
if (link.TargetPath == Application.ExecutablePath)
{
System.IO.File.Delete(fileName);
}
}
}
Note: Application.ExecutablePath works for WinForms to get the current exe path, for Console app you should use Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]). Refer to documentation for other types of projects.
You should use FileSystemWatcher class:
Listens to the file system change notifications and raises events when
a directory, or file in a directory, changes.
Infact you can exploit FileSystemWatcher.Changed, FileSystemWatcher.Created, FileSystemWatcher.Renamed , FileSystemWatcher.Deleted events to keep control on your file.
Here is an example by MSDN:
public static void Main()
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "mypath";
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read()!='q');
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
Renaming a shortcut does not modify the target path, however, the best way I know to work with shortcuts in c# is with the IwshRuntimeLibrary.
To delete a file please use System.IO.File.Delete method
To modify the file you can use System.IO.File.AppendText method
Update after comments from below :
Please use the ShellClass to create or modify shortcuts Also you will
need to get the special directory from desktop using
Environment.SpecialFolder.DesktopDirectory
A very good example showing step by step can be found here http://www.codeproject.com/Articles/146757/Add-Remove-Startup-Folder-Shortcut-to-Your-App
Whats the best way to monitor multiple folders (not subdirectories) using FileSystemWatcher in C#?
I don't think FSW supports monitoring multiple folders, so just instantiate one per folder you want to monitor. You can point the event handlers at the same methods, though, which should end up working like I think you want.
The easiest way is to create multiple instances of the FileSystemWatcher object.
http://www.c-sharpcorner.com/UploadFile/mokhtarb2005/FSWatcherMB12052005063103AM/FSWatcherMB.aspx
You'll have to make sure the you handle events between the two folders correctly:
Although some common occurances, such
as copying or moving a file, do not
correspond directly to an event, these
occurances do cause events to be
raised. When you copy a file, the
system raises a Created event in the
directory to which the file was copied
but does not raise any events in the
original directory. When you move a
file, the server raises two events: a
Deleted event in the source directory,
followed by a Created event in the
target directory.
For example, you create two instances
of FileSystemWatcher.
FileSystemWatcher1 is set to watch
"C:\My Documents", and
FileSystemWatcher2 is set to watch
"C:\Your Documents". Now, if you copy
a file from "My Documents" into "Your
Documents", a Created event will be
raised by FileSystemWatcher2, but no
event is raised for
FileSystemWatcher1. Unlike copying,
moving a file or directory would raise
two events. From the previous example,
if you moved a file from "My
Documents" to "Your Documents", a
Created event would be raised by
FileSystemWatcher2 and a Deleted event
would be raised by FileSystemWatcher
Link to FileSystemEventArgs
Out of the box, FileSystemWatcher only supports monitoring a single parent directory. To monitor multiple sibling directories, you would need to create multiple instances of FileSystemWatcher.
You can try cheating this behavior, however, by taking advantage of FileSystemWatcher's ability to include subdirectories. You can create an NTFS junction point (aka symbolic link) as a subdirectory from the directory you are watching. Mark Russinovich of Sysinternals fame has a utility called Junction to simplify creation and management of symlinks.
Note that you can only create symlinks to directories on your local machine.
Although this is an old question I decided to answer, because I couldn't find a good answer anywhere.
So, the aim was to monitor multiple folders (not subdirectories) using FileSystemWatcher? Here's my suggestion:
using System;
using System.IO;
using System.Security.Permissions;
using System.Collections.Generic;
namespace MultiWatcher
// ConsoleApplication, which monitors TXT-files in multiple folders.
// Inspired by:
// http://msdn.microsoft.com/en-us/library/system.io.filesystemeventargs(v=vs.100).aspx
{
public class Watchers
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
string[] args = System.Environment.GetCommandLineArgs();
// If a directory is not specified, exit program.
if (args.Length < 2)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Watcher.exe PATH [...] [PATH]";
return;
}
List<string> list = new List<string>();
for (int i = 1; i < args.Length; i++)
{
list.Add(args[i]);
}
foreach (string my_path in list)
{
Watch(my_path);
}
// Wait for the user to quit the program.
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
private static void Watch(string watch_folder)
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = watch_folder;
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
}
}
Can you simply use multiple instances of the FileSystemWatcher, one for each directory?
You would have to instantiate multiple instances of the FileSystemWatcher object. Though you can bind the Events to the same method and use the sender object to determine which FileSystemWatcher triggered the event.
var fsw1 = new FileSystemWatcher();
var fsw2 = new FileSystemWatcher();
FileSystemEventHandler fsw_changed = delegate(object sender, FileSystemEventArgs e)
{
Console.WriteLine("{0} - {1}", (sender as FileSystemWatcher).Path, e.ChangeType);
};
fsw1.Changed += fsw_changed;
fsw2.Changed += fsw_changed;
or you can pass the paths in-code, to mark a certain range of the domain watched like in this :
multiple monitor link
hope this helps.