I am delivering media contents to a client system (download from internet) and want to acknowledge if the media file was opened (and viewed) by the operator.
I am using a file system watcher (C# 3.5) to check for the last access time of file (so whenever the media file is played I should get the event) and I send an acknowledgement.
I have enabled the last access time in registry of my Windows 7 machine here and rebooted my system. File system watcher fires events on directory opened but not on media play.
Here is my code :
private FileSystemWatcher fsWatcher = null;
private static Object objLock = new Object();
private void StartAccessWatcher(string _folderPath)
{
fsWatcher = new FileSystemWatcher(_folderPath, "*.*");
fsWatcher.Changed += new FileSystemEventHandler(fsWatcher_Changed);
fsWatcher.IncludeSubdirectories = true;
fsWatcher.NotifyFilter = NotifyFilters.LastAccess;
fsWatcher.EnableRaisingEvents = true;
}
private void fsWatcher_Changed(object sender, FileSystemEventArgs e)
{
lock (objLock)
{
fsWatcher.EnableRaisingEvents = false;
DisplayMessage(string.Concat(e.ChangeType, " ", e.FullPath));
fsWatcher.EnableRaisingEvents = true;
}
}
private void btn_StartWatcher_Click(object sender, EventArgs e)
{
StartAccessWatcher(#"E:\Surewaves\Media-Store\MP1 Videos");
}
You may also download my code sample from here.
Please tell me how best can I achieve it ? I need to get the the last access time (when ever the video or audio or image or .swf file was played by any player) ?
As an update to this three year old question, the code given works correctly now* with videos played on the local machine.
The machine must have lastAccess successfully enabled with the following command
fsutil behavior set DisableLastAccess 0
as noted in the question.
*- at the time of this post, using Windows Server 2012 R2
The FileSystemWatcher is used to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. In your case there is no change being made on media files. I would suggest try extending FileSystemWatcher class and create new events for media file reading and then fire those events.
Related
I'm building a simple Windows Service (basically combining this tutorial with this class).
Now I have a "FROM" directory and two "TO" (TO1, TO2) directories. When I place a file into FROM, it should be copied both to TO1 and TO2. I install the service and I start it in the Service Control Manager where I see it's running. On the first run, it copies the file to TO1 and TO2 and the service is still running after that.
Then, when I place another file to FROM (with a different name), nothing happens. And refreshing the services I find that the service stopped.
Why does the service stop? It seems it stops just in the moment when I place the second file.
Here I register the file system watcher:
// File System Watcher
var fileSystemWatcher = new FileSystemWatcher();
fileSystemWatcher.Created += FileSystemWatcher_MoveOnCreate;
fileSystemWatcher.Path = this.fromPath;
fileSystemWatcher.EnableRaisingEvents = true;
And here is the event handler:
private void FileSystemWatcher_MoveOnCreate(object sender, FileSystemEventArgs e)
{
string FROM = Path.Combine(fromPath, e.Name);
string TO1 = Path.Combine(toPathOne, e.Name);
string TO2 = Path.Combine(toPathTwo, e.Name);
File.Copy(FROM, TO1);
File.Copy(FROM, TO2)
}
If the Windows Service stops there was an unhandled exception in your code somewhere. Try to surround the key point of your code ( maybe the entire body of the function FileSystemWatcher_MoveOnCreate ) with try{}catch(){} and log what's happening. In general you should add log to your windows service is the only way you can understand if things are going on anyway.
I'm attempting to watch a network share for folders where a file is added to the share to indicate the upload is complete. I wanted to use a FileSystemWatcher to monitor that share and its subdirectories for that trigger file, as shown below.
FileSystemWatcher fsw = new FileSystemWatcher(share, triggerFilePattern);
fsw.IncludeSubdirectories = true;
fsw.Created += new FileSystemEventHandler(OnCreated);
fsw.Renamed += new RenamedEventHandler(OnRenamed);
fsw.Error += new ErrorEventHandler(OnError);
If a file is created at the root of the share, the event triggers. If a file is created within a subdirectory of the share, the event does not trigger, and I don't get an error either.
If I create a new FileSystemWatcher for that subdirectory, then I do receive an event when a file is created there. But, similar to the top level FileSystemWatcher, I won't get events for files created in any further subdirectories.
If I change the network share to a local directory for testing, it does work as expected.
Any ideas? Could I have set up some wonky network share setting that blocks recursive FileSystemWatcher checks? I can work around this, but it would be nice to not have to complicate the code.
Edit: I saw that I didn't have Full Control under Properties->Security tab, so I thought that could be it. But I was able to get normal desired behavior on a different share with the same visible permissions, so I'm back to not knowing why this specific share isn't working.
Edit2: At a coworker's suggestion, I added a Changed handler too. Doesn't make sense to me how a file can be changed without getting Created first, but... I'm getting Changed events on the share in question when creating files in a subdirectory. (And I'm still getting nothing when renaming them.) This solves my immediate problem, but I'm going to leave the question open in case someone's able to answer why that's happening.
Try this
private static FileSystemWatcher fw;
static void Main(string[] args)
{
fw = new FileSystemWatcher(#"D:\Folder_Watch");
fw.IncludeSubdirectories = true;
fw.NotifyFilter = NotifyFilters.LastAccess |
NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
fw.Created += fw_Created;
fw.Changed += fw_Created;
fw.Renamed += fw_Created;
fw.Filter = "*.*";
fw.EnableRaisingEvents = true;
new System.Threading.AutoResetEvent(false).WaitOne();
}
static void fw_Created(object sender, FileSystemEventArgs e)
{
try
{
fw.EnableRaisingEvents = false;
//Your Code
}
finally
{
fw.EnableRaisingEvents = true;
}
}
I had same problem and I solved it by giving write permission to the shared network folder (it had only read permission so far). Shared folder is originally on Linux but I have it mounted on Windows Server 2008 R2 where I'm running program with FileSystemWatcher.
I have a file, it is large, reading it takes a long time and I'd like to have some monitoring to see when it's being written to.
I can solve this quite easily by chucking some logging into the application that it reading it, however I'd like something more agnostic. There are quite a few application that have a similar use case. Monitoring writes should be easy enough as I can watch the last modified date, but reading isn't so easy.
If there any way to passively monitor read and writes to a file?
To clarify: If it can do done in 100% C#, then great, if not then shelling out to some other 'thing', or even resorting to some other language is fine. I don't really mind what the watching bit is written in.
Trying Rahul's Solution
I have set up ithe following test code. It dumps events to the console:
public static void Main()
{
var taskFactory = new TaskFactory();
var setup = new Action(() =>
{
var setupWatcher =
new Action<NotifyFilters, string, FileSystemWatcher>((filters, s, watcher) =>
{
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = filters;
watcher.Changed += (sender, args) => System.Console.WriteLine(s, args.FullPath, args.ChangeType);
});
var lastAccessWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastAccess,
"File: {0}\tFilter: LastAccess\tType: {1}", lastAccessWatcher);
var lastWriteWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastWrite, "File: {0}\tFilter: LastWrite\tType: {1}",
lastWriteWatcher);
var fileNameWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.FileName,
"File: {0}\tFilter: FileName\tType: {1}", fileNameWatcher);
var directoryNameWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastWrite, "File: {0}\tFilter: DirectoryName\tType: {1}",
directoryNameWatcher);
});
taskFactory.StartNew(setup);
while (true)
{
Thread.Sleep(10);
}
}
However, when I open a text file in notepad, no event is thrown by the lastAccessWatcher, whereas, when I save, two events are thrown by the lastWriteWatcher and the directoryNameWatcher, as per below.
File: F:\FileMonitor\New Text Document.txt Filter: LastWrite Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: LastWrite Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: DirectoryName Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: DirectoryName Type: Changed
So...
What does trigger 'last access'
Can I actually have any trigger fired when a file is read?
For watching writes to the file, the FileSystemWatcher class is the right way to go. However if you want to know if a file is being written, what I would do is get a list of all the open files by process, and monitor when the file is opened and then closed.
There is a CodeProject article that shows how to get the open files by process here.
One solution would be to use a Microsoft tool called Process Monitor. It's able to list all CreateFile/ReadFile/WriteFile calls any process does. There are several command line options available:
You can use the FileSystemWatcher class
Listens to the file system change notifications and raises events when
a directory, or file in a directory, changes.
You can use the different events
Changed
Created
Deleted
Renamed
and also read this FileSystemWatcher Tips
An example:
public void MyFileWatcher(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "myFile.txt";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath + " " + e.ChangeType);
}
Similarly you can add other event handlers definition.
Also if you want to check the read then you can use the FileInfo.LastAccessTime and FileInfo.Refresh() in a polling loop to get the information of when your file is being read.
In code your task is handled with a filesystem filter driver. Process Monitor application (already mentioned in another answer) includes such driver in pre-built form.
You can write a kernel-mode driver yourself, yet this would probably be an overkill. Then there exists our CallbackFilter - a class library with a pre-created kernel-mode driver included. You write code in C# and catch all filesystem operations before or after they are performed. If your need is short-term, then the evaluation license will work.
The Pc I use have an UNC file. I'm in a Network with other people.
Every other can open the file by tipping in the adress line \\file.
Know I want to write a c# programm in Vs2010 which watch over the file I use Win7 32bit. If any one Open the file the programm shall write in a Logfile that someone has open my file.
I tried to use the FileSystemWatcher but this only look for changes/saves/cration but not for Opening.
I read somthing about "auditing" and that I'm be able to do that(watch over my unc file) with this(auditing).But i tried to find out how to use auditing in c# but i found not much.
.
So my Questions:
Is it possible to do what i want with "auditing" ?
Did someone worked with auditing in c# befor or has anyone a link or somtihng to show me how it works in c#?
mfg Sam
Sry for bad english
You might want to use the Audit Object Access.
The steps you have to follow:
Enable the Audit object access in the Local Computer Policy.
Enable auditing for the object you want to follow.
From your application, use the EventLog.EntryWritten Event to detect the file opening event
Here's a simplistic sample usage, but you'll have to dig in the documentation in order to capture and log as you need to:
class Program
{
public static void Main()
{
EventLog myNewLog = new EventLog("Security", ".", "Microsoft Windows security");
myNewLog.EntryWritten += new EntryWrittenEventHandler(MyOnEntryWritten);
myNewLog.EnableRaisingEvents = true;
Console.ReadLine();
}
public static async void MyOnEntryWritten(object source, EntryWrittenEventArgs e)
{
await Task.Factory.StartNew(() =>
{
if (e.Entry.InstanceId == 4656 || e.Entry.InstanceId == 4663)
{
Console.WriteLine(e.Entry.Message);
}
});
}
}
I would like to be notified in my C# application when another process makes changes to a particular textfile.
The reason for this is that I launch a 3rd party tool from my application in order to retrieve some information about a device. this tool saves the current state of the device into an ini file. This takes some undetermined time, but I want to react and read the state information as soon as it's available.
How can I do this?
You could use the System.IO.FileSystemWatcher class.
Something like this:
string fileToWatch = #"C:\MyFile.txt";
fileSystemWatcher = new FileSystemWatcher(fileToWatch);
void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
Debug.WriteLine(e.Name + " has changed");
}
You can monitor file changes using System.IO.FileSystemWatcher
Also, see Notification when a file changes? for more info.