I'm trying to use the solution found here [Create multiple instances of the same FileSystemWatcher to make FileSystemWatchers on the fly but the Watcher_Created event doesn't seem to be triggered. Any thoughts as to what I am doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Type Enter to exit:::");
StartWatchers();
Console.ReadLine();
}
public static void StartWatchers()
{
string[] ArrayPaths = new string[2];
List<FileSystemWatcher> watchers = new List<FileSystemWatcher>();
ArrayPaths[0] = #"\\WifeyPC\c$\User\Wifey\Desktop";
ArrayPaths[1] = #"\\HubbyPC\c$\Users\Hubby\Desktop";
int i = 0;
foreach (String String in ArrayPaths)
{
watchers.Add(MyWatcherFatory(ArrayPaths[i]));
i++;
}
foreach (FileSystemWatcher watcher in watchers)
{
watcher.EnableRaisingEvents = true; ;
Console.WriteLine("Watching this folder {0}", watcher.Path);
i++;
}
}
FileSystemWatcher MyWatcherFatory(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher(path);
watcher.Changed += Watcher_Created;
watcher.Path = path;
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
return watcher;
}
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
System.Threading.Thread.Sleep(1000);
FileInfo fileInfo = new FileInfo(e.FullPath);
Console.WriteLine("File Created!! :: {0}", e.FullPath);
}
}
}
You are never calling the StartWatchers method in your Main starting point.
Change the code as seen below:
static void Main(string[] args)
{
Console.WriteLine("Type Enter to exit:::");
StartWatchers();
Console.ReadLine();
}
You're also going to need to change your Watcher_Created method as seen below. You had the ending double quote after fullPath which would just display that entire string, when you need to place the double quote after the parameter {0}:
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
System.Threading.Thread.Sleep(1000);
FileInfo fileInfo = new FileInfo(e.FullPath);
Console.WriteLine("File Created!! :: {0}", e.FullPath);
}
You are 100% correct #scott-chamberlain. Below is the answer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Type Enter to exit:::");
StartWatchers();
Console.ReadLine();
}
public static void StartWatchers()
{
string[] ArrayPaths = new string[2];
List<FileSystemWatcher> watchers = new List<FileSystemWatcher>();
ArrayPaths[0] = #"\\WifeyPC\c$\User\Wifey\Desktop";
ArrayPaths[1] = #"\\HubbyPC\c$\Users\Hubby\Desktop";top";
int i = 0;
foreach (String String in ArrayPaths)
{
watchers.Add(MyWatcherFatory(ArrayPaths[i]));
i++;
}
foreach (FileSystemWatcher watcher in watchers)
{
watcher.EnableRaisingEvents = true; ;
Console.WriteLine("Watching this folder {0}", watcher.Path);
i++;
}
}
public static FileSystemWatcher MyWatcherFatory(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher(path);
watcher.Changed += Watcher_Created;
watcher.Path = path;
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
return watcher;
}
private static void Watcher_Created(object sender, FileSystemEventArgs e)
{
System.Threading.Thread.Sleep(1000);
FileInfo fileInfo = new FileInfo(e.FullPath);
Console.WriteLine("File Created!! :: {0}", e.FullPath);
}
}
}
Related
I am trying to store executed commands results inside a txt file, command execution is working fine and also showing a command prompt but I am unable to store results inside my file.
It's only creating a empty file inside that folder.
Program.cs :
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace commandExecutionPractice
{
class Program
{
static void Main(string[] args)
{
var folderPath = #"C:\";
var fileName = #"\commandLog.txt";
var fullPath = folderPath + fileName;
StreamWriter writer = new StreamWriter(fullPath);
using (CmdService cmdService = new CmdService("cmd.exe"))
{
string consoleCommand = String.Empty;
do
{
Console.WriteLine("Enter Command : ");
consoleCommand = Console.ReadLine();
string output = cmdService.ExecuteCommand(consoleCommand);
writer.WriteLine(">>> {0}", output);
Console.WriteLine(">>> {0}", output);
}
while (!String.IsNullOrEmpty(consoleCommand));
}
Console.ReadLine();
}
}
}
CmdService.cs :
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
namespace commandExecutionPractice
{
public class CmdService : IDisposable
{
private Process _cmdProcess;
private StreamWriter _streamWriter;
private AutoResetEvent _outputWaitHandle;
private string _cmdOutput;
public CmdService(string cmdPath)
{
_cmdProcess = new Process();
_outputWaitHandle = new AutoResetEvent(false);
_cmdOutput = String.Empty;
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = cmdPath;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.CreateNoWindow = true;
_cmdProcess.OutputDataReceived += _cmdProcess_OutputDataReceived;
_cmdProcess.StartInfo = processStartInfo;
_cmdProcess.Start();
_streamWriter = _cmdProcess.StandardInput;
_cmdProcess.BeginOutputReadLine();
}
public string ExecuteCommand(string command)
{
_cmdOutput = String.Empty;
_streamWriter.WriteLine(command);
_streamWriter.WriteLine("echo end");
_outputWaitHandle.WaitOne();
return _cmdOutput;
}
private void _cmdProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null || e.Data == "end")
_outputWaitHandle.Set();
else
_cmdOutput += e.Data + Environment.NewLine;
}
public void Dispose()
{
_cmdProcess.Close();
_cmdProcess.Dispose();
_streamWriter.Close();
_streamWriter.Dispose();
}
}
}
Edit : I added code of CmdService class which I forgot to add.
Thanks in Advance.
It's a simple fix.
In your Main function add the line writer.Flush(); after you write to the stream as per:
writer.WriteLine(">>> {0}", output);
writer.Flush();
Alternatetively, if you wrap the streams usage in a using block, it will flush it before it closes the stream.
using (StreamWriter writer = new StreamWriter(fullPath))
{
using (CmdService cmdService = new CmdService("cmd.exe"))
{
string consoleCommand = String.Empty;
do
{
Console.WriteLine("Enter Command : ");
consoleCommand = Console.ReadLine();
string output = cmdService.ExecuteCommand(consoleCommand);
writer.WriteLine(">>> {0}", output);
Console.WriteLine(">>> {0}", output);
}
while (!String.IsNullOrEmpty(consoleCommand));
}
}
i'm a very beginer in C # and it's also my first post here so please be nice with me :)
Well, i'm trying to code a litle apps that read a file only if it changed and update the new content in a richtextbox control in a Windows Form.
So there is my code :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string path = #"C:\MyPath\";
Filecheck NewFileChecker = new Filecheck();
NewFileChecker.WatchingFile(path, "myFile.txt");
}
And This is my Class FileCheck
class Filecheck
{
public void WatchingFile (string FilePath, string Filter)
{
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = FilePath;
fsw.Filter = Filter;
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
fsw.Changed += OnFileChange;
fsw.EnableRaisingEvents = true;
}
private void OnFileChange(object sender, FileSystemEventArgs e)
{
string line;
try
{
using (FileStream file = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(file, Encoding.Default))
{
while ((line = sr.ReadLine()) != null)
{
MessageBox.Show(line);
// I WOULD LIKE TO UPDATE A FORM1 RichTextBox from here....
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
So, i'll would like to update a Windows Form control from where i do the MessageBox method. Someone have an idea how can i do that ? Because when i tried to invoke like this :
Form1.richTextBoxName.Invoke(new MethodInvoker(delegate
{
Form1.richTextBoxName.Text(line);
}));
Well, i get this message: "CS0120: An object reference is required for the nonstatic field, method, or property"
Someone have an idea how can i solve that ?
Thanks
Yes! That's work very well in my project for my idea Nguyen Van Thanh. But I made some modifications to get this working if it can help anothers.. Thank you very much for your input.
In the main Class:
public Form1()
{
string path = #"C:\MyPath\";
Filecheck NewFileChecker = new Filecheck();
NewFileChecker.OnUpdateData += (d => UpdateRTBoxJournal(d));
NewFileChecker.WatchingFile(path, "myFile.txt");
}
public void UpdateRTBoxJournal(string line)
{
richTextBoxName.Invoke(new MethodInvoker(delegate
{
richTextBoxName.Text = line;
}));
}
And finally in the other class in another file...
public delegate void UpdateData(string data);
class Filecheck
{
public event UpdateData OnUpdateData;
public void WatchingFile (string FilePath, string Filter)
{
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = FilePath;
fsw.Filter = Filter;
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
fsw.Changed += OnFileChange;
fsw.EnableRaisingEvents = true;
}
private void OnFileChange(object sender, FileSystemEventArgs e)
{
string line;
try
{
using (FileStream file = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(file, Encoding.Default))
{
while ((line = sr.ReadLine()) != null)
{
this.OnUpdateData?.Invoke(line);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Une erreur s'est produite." + ex.Message);
}
}
}
Thanks again for your anwser.
There are alot of solutions for your idea, but I help you one case:
Use delegate:
Step 1: Create a new delegate with param is 01 string , return type is void, name is UpdateData:
public delegate void UpdateData(string data);
Step 2: Declare a event in Filecheck class (OnUpdateData) with the delegate created:
public event UpdateData OnUpdateData;
Step 3: Raise the event anywhen you want:
this.OnUpdateData?.Invoke(line);
Step 4: In your main function, set OnUpdateData by:
Filecheck NewFileChecker = new Filecheck();
NewFileChecker.OnUpdateData += (d => MessageBox.Show(d));
Full code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public delegate void UpdateData(string data);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string path = #"C:\MyPath\";
Filecheck NewFileChecker = new Filecheck();
NewFileChecker.OnUpdateData += (d => MessageBox.Show(d));
NewFileChecker.WatchingFile(path, "myFile.txt");
}
}
class Filecheck
{
public event UpdateData OnUpdateData;
public void WatchingFile(string FilePath, string Filter)
{
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = FilePath;
fsw.Filter = Filter;
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
fsw.Changed += OnFileChange;
fsw.EnableRaisingEvents = true;
}
private void OnFileChange(object sender, FileSystemEventArgs e)
{
string line;
try
{
using (FileStream file = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(file, Encoding.Default))
{
while ((line = sr.ReadLine()) != null)
{
//MessageBox.Show(line);
// I WOULD LIKE TO UPDATE A FORM1 RichTextBox from here....
this.OnUpdateData?.Invoke(line);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
The Form1 class needs to be new when you try to use it.
If you want to use the Form1 by your function, you can set the Form1 to Static Type.
I would like to understand the root cause for this error:
Unable to remove the file to be replaced.
This error comes while executing File.Replace(), and having in parallel in another application an active FileSystemWatcher, which as a reaction to the events, is calling Path.GetDirectoryName() for the actual element received in the eventargs.
The code for the two console applications looks like this:
FileReplacerr:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace ConsoleApplication1
{
internal static class FileReplacer
{
private static void Main(string[] args)
{
Console.WriteLine("Test Started.");
Directory.CreateDirectory(rootPath);
CleanUp(new List<string> { livePath, tempPath }, -1);
for (int loopIndex = 0; loopIndex < 10000; loopIndex++)
{
WriteXmlFile(livePath + loopIndex, "LiveContent");
WriteXmlFile(tempPath + loopIndex, "TempContent");
ReplaceFiles(livePath + loopIndex, tempPath + loopIndex);
CleanUp(new List<string> { livePath + loopIndex, tempPath + loopIndex }, loopIndex);
}
Console.WriteLine("---------------------------------------------");
Console.WriteLine("Test Finished.");
Console.WriteLine("Exception count: {0}", exceptionCount);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
private static void ReplaceFiles(string replacedFile, string replacementFile)
{
try
{
File.Replace(replacedFile, replacementFile, null);
}
catch (Exception ex)
{
exceptionCount++;
string extendedErrorMessage = string.Format("Replacement of original:'{0}' and temporary:'{1}' xml file completed with error code: {2}", replacedFile, replacementFile, ex.Message);
Console.WriteLine("Exception happened during replace:");
Console.WriteLine(extendedErrorMessage);
Console.WriteLine("Press any key to continue");
Console.ReadKey();
}
}
private static void WriteXmlFile(string filePath, string elementText)
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 32 * 1024, FileOptions.SequentialScan))
{
fileStream.Seek(0, SeekOrigin.Begin);
fileStream.SetLength(0);
XmlWriterSettings settings = new XmlWriterSettings { CheckCharacters = false };
using (XmlWriter xmlWriter = XmlWriter.Create(fileStream, settings))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement(elementText);
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
}
}
}
private static void CleanUp(List<string> filePaths, int loopIndex)
{
foreach (string filePath in filePaths)
{
File.Delete(filePath);
}
}
private static int exceptionCount = 0;
static readonly string rootPath = #"C:\teststorage\";
static readonly string liveFile = "live.xml";
static readonly string tempFile = "temp.xml.tmp";
static readonly string livePath = rootPath + liveFile;
static readonly string tempPath = rootPath + tempFile;
}
}
FileSystemWatcherr:
using System;
using System.IO;
namespace FileSystemWatcherr
{
class FileSystemWatcherr
{
static void Main(string[] args)
{
using (FileSystemWatcher watcher = new FileSystemWatcher
{
Path = #"c:\",
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName,
IncludeSubdirectories = true
})
{
watcher.Changed += OnFolderStructureChanged;
watcher.Created += OnFolderStructureChanged;
watcher.Deleted += OnFolderStructureChanged;
watcher.Renamed += OnFolderStructureChanged;
watcher.EnableRaisingEvents = true;
Console.WriteLine("FileSystemWatcher is active");
Console.WriteLine("Press any key to stop watching and exit");
Console.ReadKey();
watcher.EnableRaisingEvents = false;
watcher.Changed -= OnFolderStructureChanged;
watcher.Created -= OnFolderStructureChanged;
watcher.Deleted -= OnFolderStructureChanged;
watcher.Renamed -= OnFolderStructureChanged;
}
}
private static void OnFolderStructureChanged(object sender, FileSystemEventArgs e)
{
string path = string.Empty;
switch (e.ChangeType)
{
case WatcherChangeTypes.Changed:
case WatcherChangeTypes.Deleted:
case WatcherChangeTypes.Renamed:
case WatcherChangeTypes.Created:
default:
path = Path.GetDirectoryName(e.FullPath);
break;
}
}
}
}
Just start the FileSystemWatcherr and then start the FileReplacerr and you will see the error happening.
The issue happens more frequently on Win7 machines. On my Win10 machine, it did not happen, but running the applications on a virtual machine with Win10, the issue happens many times during 10000 loops.
Does anyone have an idea what could be the root cause?
Up to now, I tried using Process Monitor, but from its output I do not understand what the root cause could be:
If you have an idea how to find the root-cause, or you know it, let me know :)
Need to zip text files from a predefined location & save the zipped files in another location of hard disk using windows services & delete the old text file (a scheduled service)
I tried the following code in which i used 'icsharpcode' for zipping the files. But after installing the service.. i am getting a message that "this services has started & then stopped..." without showing any required output.
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Diagnostics.Design;
using System.Diagnostics.Eventing;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Timers;
using ICSharpCode.SharpZipLib.Zip;
namespace createzip
{
public partial class createzip : ServiceBase
{
Timer timer1 = new Timer();
public createzip()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer1.Elapsed += new ElapsedEventHandler(onelapsedtime);
timer1.Enabled = true;
timer1.Interval = 60000;
}
protected override void OnStop()
{
timer1.Enabled = false;
}
private void onelapsedtime(object source, ElapsedEventArgs e)
{
string folder = "#E:\\zipped files";
Directory.SetCurrentDirectory(folder);
string output = "#E:\\output";
string outputfilename = Path.Combine(output, "this file is zipped");
using (var x = new ZipFile(output))
{
foreach (var f in Directory.GetFiles(folder))
x.Add(f);
}
string[] filenames = Directory.GetFiles(folder);
using ( ZipOutputStream s = new
ZipOutputStream(File.Create(output))) //(args[1])))
{
s.SetLevel(9);
byte[] buffer = new byte[4096];
foreach (string file in filenames)
{
ZipEntry entry = new ZipEntry(Path.GetDirectoryName(file));
//entry.DateTime = DateTime.Now;
s.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(file))
{
int sourcebytes;
do
{
sourcebytes = fs.Read(buffer, 0, buffer.Length);
s.Write(buffer, 0, sourcebytes);
}
while (sourcebytes > 0);
}
}
s.Finish();
s.Close();
return;
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Timers;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
namespace trail2zip
{
public partial class trail2zip : ServiceBase
{
Timer timer;
string path1 = #"E:\zipped files\New Text Document.txt";
string path2 = #"E:\output\filezipname.zip";
string path3 = #"E:\zipped files\R_23122015.txt";
int timerInterval = 60000;
public trail2zip()
{
InitializeComponent();
timer = new Timer();
timer.Elapsed+=new ElapsedEventHandler(this.timer_Elapsed);
timer.Interval = timerInterval;
timer.Enabled = true;
}
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
timer.Stop();
timer.SynchronizingObject = null;
timer.Elapsed -= new ElapsedEventHandler(this.timer_Elapsed);
timer.Dispose();
timer = null;
}
public void timer_Elapsed(object sender, ElapsedEventArgs e)
{
ZipFile z = ZipFile.Create(path2); //(filezipname);
z.BeginUpdate();
z.Add(path1);
z.Add(path3);
z.CommitUpdate();
z.Close();
}
}
}
I have some code which outputs data from the FileSystemWatcher class, although each times to outputs a line to test.txt, it overwrites the previous entry, is there a way to stop this happening?
Code in question:
static void FileWatcher_Created(object sender, FileSystemEventArgs e)
{
using (StreamWriter fileWriter = new StreamWriter("test3.txt"))
{
var data = true;
fileWriter.Write("C:\\" + e.Name + Environment.NewLine);
}
Full Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace FileWatcherr
{
class Program
{
static void Main(string[] args)
{
string dirPath = "C:\\";
FileSystemWatcher fileWatcher = new FileSystemWatcher(dirPath);
fileWatcher.IncludeSubdirectories = true;
fileWatcher.Filter = "*.exe";
// fileWatcher.Filter = "C:\\$Recycle.Bin";
// fileWatcher.Changed += new FileSystemEventHandler(FileWatcher_Changed);
fileWatcher.Created += new FileSystemEventHandler(FileWatcher_Created);
// fileWatcher.Deleted += new FileSystemEventHandler(FileWatcher_Deleted);
// fileWatcher.Renamed += new RenamedEventHandler(FileWatcher_Renamed);
fileWatcher.EnableRaisingEvents = true;
// updated code
Console.ReadKey();
}
static void FileWatcher_Renamed(object sender, RenamedEventArgs e)
{
Console.WriteLine(e.OldName + " was renamed to " + e.Name);
}
static void FileWatcher_Deleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.Name + " was deleted");
}
static void FileWatcher_Created(object sender, FileSystemEventArgs e)
{
using (StreamWriter fileWriter = new StreamWriter("test3.txt"))
{
var data = true;
fileWriter.Write("C:\\" + e.Name + Environment.NewLine);
}
}
static void FileWatcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.Name + "");
}
}
}
Edit your code to be the below. The second parameter to the StreamWriter is if we should append or overwrite. Set to true to append and false to overwrite (default, thus your problem)
using (StreamWriter fileWriter = new StreamWriter("test3.txt", true))
{
var data = true;
fileWriter.WriteLine(Path.Combine("C:\\", e.Name));
}
More info about this constructor can be found here http://msdn.microsoft.com/en-us/library/36b035cb.aspx
Try
using (StreamWriter fileWriter = new StreamWriter("test3.txt", true))
{
...
}
Replace
new StreamWriter("test3.txt")
by
new StreamWriter("test3.txt", true)
This will make the stream append to the file.
Consider opening file to append:
using (StreamWriter fileWriter = new StreamWriter("test3.txt", true))
{
var data = true;
fileWriter.WriteLine("C:\\" + e.Name);
}
Note that it is better to use WriteLine method.
The StreamWriter class has an overload constructor that takes a second bool parameter which specifies if you want to append to an existing file. More information here.