Detect changes in iis logs files - c#

I am running a filesystemwatcher on the "w3svc1" folder, where the iis logs are stored by default. When I go to the adress localhost or anyone of my webapp localhost/xxxxx. The filesystemwatcher does not raise events. I know that there is a delay between the request and the writting in the logs, but even after one hour there is no change event raised. But then, when I open the file with notepad++, I see the logs added. Is anyone has an explaination. This is my code:
class Program
{
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"C:\inetpub\logs\LogFiles\W3SVC1";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.IncludeSubdirectories = true;
watcher.Filter = "*.log";
watcher.Changed += new FileSystemEventHandler(OnChangedok);
watcher.Created += new FileSystemEventHandler(OnChangedok);
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
private static void OnChangedok(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath);
}

This is because IIS open stream and write the logs into file but didn't flush the changes Immediately. When you open the file in notepad++, it access this file which trigger the file modification event . Please refer this thread also.

Related

How to transfer file via windows share from Android MAUI app?

I would like to be able to run commands on the command prompt on a windows pc from an Android phone.
I am currently doing it by a wpf app on windows which listens for files with .dev in their file name.
This method is very annoying to use on a phone as I have to type out the command in a .bat file and then copy the file to D:\Shared using an app like File Manager to transfer the file via windows share
using Microsoft.Win32;
using System.Diagnostics;
namespace Dev
{
public partial class Dev : ApplicationContext
{
class Var
{
public static string temp = Path.GetTempPath();
}
public Dev()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", true);
key.SetValue("Remote Dev", Application.ExecutablePath);
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new()
{
Path = "D:\\Shared",
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName,
// Only watch text files.
Filter = "*.dev.*"
};
// Add event handlers.
watcher.Created += new FileSystemEventHandler(Create);
// Begin watching.
watcher.EnableRaisingEvents = true;
//This method is called when a file is created.
static void Create(object source, FileSystemEventArgs e)
{
string tempPath = Var.temp + Path.GetFileName(e.FullPath);
if (File.Exists(tempPath)) File.Delete(tempPath);
File.Move(e.FullPath, tempPath);
Thread.Sleep(1000);
Process.Start("explorer", tempPath);
}
}
}
}
I would like to create an app that can automate the process of creating the .bat file and coping it to the D:\Shared without the need of any third party app.
! Please help me in the Maui part as I am new to it.
Thanks

FileSystemWatcher with the console application

To send bulk email in my web application I am using filewatcher to send the application.
I have planned to write filewatcher with the console application instead of windows service or scheduler.
I have copied the executable file shortcut in the following path.
%appdata%\Microsoft\Windows\Start Menu\Programs
Ref: https://superuser.com/questions/948088/how-to-add-exe-to-start-menu-in-windows-10
After run the executable file the file watcher is not watched always.
After searching some sites, i have found that we need to add the code
new System.Threading.AutoResetEvent(false).WaitOne();
Is this the right method to add in the executable file and to watch the folder?
After run the console application (without above code) is the file won't be watched always?
What will be the right method to use the file watcher?
FileSystemWatcher watcher = new FileSystemWatcher();
string filePath = ConfigurationManager.AppSettings["documentPath"];
watcher.Path = filePath;
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(OnChanged);
Since it's a Console Application you need to write a code in the Main method to wait and not to close immediately after running codes.
static void Main()
{
FileSystemWatcher watcher = new FileSystemWatcher();
string filePath = ConfigurationManager.AppSettings["documentPath"];
watcher.Path = filePath;
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(OnChanged);
// wait - not to end
new System.Threading.AutoResetEvent(false).WaitOne();
}
Your code only tracks changes in the root folder, if you wanted to watch the subfolders you need to set IncludeSubdirectories=true for your watcher object.
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
string filePath = #"d:\watchDir";
watcher.Path = filePath;
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Filter = "*.*";
// will track changes in sub-folders as well
watcher.IncludeSubdirectories = true;
watcher.Created += new FileSystemEventHandler(OnChanged);
new System.Threading.AutoResetEvent(false).WaitOne();
}
You must also be aware of buffer overflow. FROM MSDN FileSystemWatcher
The Windows operating system notifies your component of file changes
in a buffer created by the FileSystemWatcher. If there are many
changes in a short time, the buffer can overflow. This causes the
component to losing track of changes in the directory, and it will only
provide the blanket notification. Increasing the size of the buffer with
the InternalBufferSize property is expensive, as it comes from
non-paged memory that cannot be swapped out to disk, so keep the
buffer as small yet large enough to not miss any file change events.
To avoid a buffer overflow, use the NotifyFilter and
IncludeSubdirectories properties so you can filter out unwanted change
notifications.

Exception when moving a file 3 times

Why do i get an IOException (The process cannot access the file because it is being used by another process.), when i copy the same file 3 Times into Folder A?
class FileWatcher {
FileSystemWatcher fsw;
FileInfo file;
string destination = #"C:\FileMover\B\";
Random random;
public FileWatcher() {
fsw = new FileSystemWatcher();
random = new Random();
fsw.Path = #"C:\FileMover\A";
fsw.Created += fsw_Created;
fsw.EnableRaisingEvents = true;
}
void fsw_Created(object sender, FileSystemEventArgs e) {
string destinationFileName = destination + e.Name;
if (!File.Exists(destinationFileName)) {
file = new FileInfo(e.FullPath);
file.MoveTo(destinationFileName);
}
else {
file = new FileInfo(e.FullPath);
file.MoveTo(destinationFileName + random.Next());
}
file = null;
}
}
Main:
class Program {
static void Main(string[] args) {
FileWatcher watcher = new FileWatcher();
while (Console.ReadKey().Key != ConsoleKey.Q) {
}
}
}
After 2 times folder B contains 2 files (sourceFileName and sourceFileName1274968236)
When i debug the section no Exception will be thrown.
Created might be raised before the file is flushed (?) into the destination. Try using Changed and check for e.ChangeType==WatcherChangeTypes.Created.
ref: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created(v=vs.110).aspx
Edit:
The Changed event is raised after Created, if this is due to a race-condition, probably will help but problem may still happen.
The OnCreated event is raised as soon as a file is created. If a file
is being copied or transferred into a watched directory, the OnCreated
event will be raised immediately, followed by one or more OnChanged
events.
Found this: Wait Until File Is Completely Written
and this: Is there a way to check if a file is in use?
Using tips from #celerno and the links he shared, here is what I found to work:
public FileWatcher()
{
fsw = new FileSystemWatcher();
random = new Random();
fsw.Path = #"C:\FileMover\A";
fsw.Created += fsw_Created;
fsw.Changed += fsw_Created;
fsw.EnableRaisingEvents = true;
}
and change the fsw_Created to:
if(!IsFileLocked(fi)){
if (!File.Exists(destinationFileName))
{
fi = new FileInfo(e.FullPath);
fi.MoveTo(destinationFileName);
}
else
{
fi = new FileInfo(e.FullPath);
string fileName = destinationFileName + random.Next();
fi.MoveTo(fileName);
}
fi = null;
}
Where IsFileLocked is directly taken from the link that was mentioned by #celerno.
I dropped many many copies of the file and it never threw an exception. I'm guessing an Changed event happens right after the file gets released, otherwise, if it is locked at the time of the attempted move, the Created never gets called, so the file just sits there. It appears you need both in this situation.
I just wanted to edit in order to add that the exception seemed to only get thrown when you're copying a file of the same name over and over into the source directory. Guessing the lock on that filename just needs to be released before you can copy another with the same name.

Multi Threading FileSystemWatcher monitor local folder changed and timer to handle when network is down and Ping again in Window Service

By default a Script written by the machine saves the files to Local/Server Path folder, but due to network issue, both the folders are not in sync. I have witten a C# Window Service program using FileSystemWatcher, DiffEngine, System.Timers and PingService as below coding to handle this.
To monitor a local folder OnChange Event, Ping server IP whether is success/fail before Compare/Copy to Server path, When Ping Fail it will goes to logtemp folder, system timer handle this and Ping again before re-dump the logtemp files.
I do not know how to use threading for this. Where should be my system timer code when the ping fails?
protected override void OnStart(string[] args)
{ //all watcher config here//
watcher.Path = "path";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "filename_company-Pg1_Product*";
watcher.Changed += new FileSystemEventHandler(LogFileSystemChanges);
watcher.EnableRaisingEvents = true;}
private void LogFileSystemChanges(object sender, FileSystemEventArgs e)
{
FileInfo sourcepath = new FileInfo(e.FullPath);
FileInfo destPath = new FileInfo(Path.Combine(dFile, e.Name));
FileInfo _tempPath = new FileInfo(Path.Combine(tempPath, e.Name));
if (PingService())
//PingService Bool Type....Ping Specific IP Before Compare/Copy
{
if (!destPath.Exists)
{
LogEvent(destPath + " DOES NOT EXIST!! ");
CopyFunction.CopyFile(sourcepath, destPath, true, true);
}
else
{
if (BinaryDiff(sFile, Path.Combine(dFile, e.Name)))
//DiffEngine If Source & Diff are Different is TRUE.
{
CopyFunction.CopyFile(sourcepath, destPath, true, true);
}
}
string msg = string.Format("Filename {0} are {1} now at {2} ", _
e.Name, e.ChangeType, DateTime.Now.ToString());
LogEvent(msg);
}
else
{
CopyFunction.CopyFile(sourcepath, _tempPath, true, true);
}
}
Use NServiceBus (with what they call a Saga)
Its an open source project that lets you foolproof your code against cases where the network is down.
Or are you just asking how to make a thread?
If so see MSDN on examples for creating threads

FileSystemWatcher and unprocessed files

I am using the FileSystemWatcher to notify when the new files gets created in the network directory. We process the text files(about 5KB size) and delete them immediately when the new file gets created in the directory. If the FileSystemWatcher windows service stops for some reason we have to look for the unprocessed files after it gets back up and running. How can I handle if the new file comes while processing the old files from the directory? Any examples please?
Thank you,
Here is the code example I have with simple form.
public partial class Form1 : Form
{
private System.IO.FileSystemWatcher watcher;
string tempDirectory = #"C:\test\";
public Form1()
{
InitializeComponent();
CreateWatcher();
GetUnprocessedFiles();
}
private void CreateWatcher()
{
//Create a new FileSystemWatcher.
watcher = new FileSystemWatcher();
watcher.Filter = "*.txt";
watcher.NotifyFilter = NotifyFilters.FileName;
//Subscribe to the Created event.
watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
watcher.Path = #"C:\test\";
watcher.EnableRaisingEvents = true;
}
void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
//Parse text file.
FileInfo objFileInfo = new FileInfo(e.FullPath);
if (!objFileInfo.Exists) return;
ParseMessage(e.FullPath);
}
void ParseMessage(string filePath)
{
// Parse text file here
}
void GetUnprocessedFiles()
{
// Put all txt files into array.
string[] array1 = Directory.GetFiles(#"C:\test\");
foreach (string name in array1)
{
string path = string.Format("{0}{1}", tempDirectory, name)
ParseMessage(path);
}
}
}
When the process starts do the following:
first get the contents of the folder
process every file (end delete them as you already do now)
repeat until no files are in the folder (check again here, since a new file could have been placed in the folder).
start the watcher
For any of our services that use the FileSystemWatcher we always process all the files that exist in the directory first, prior to starting the watcher. After the watcher has been started we then start a timer (with a fairly long interval) to handle any files that appear in the directory without triggering the watcher (it does happen from time to time). That usually covers all the possibilities.

Categories