using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
// The 'windowHandle' parameter will contain the window handle for the:
// - Active window when run by hotkey
// - Trigger target when run by a Trigger rule
// - TitleBar Button owner when run by a TitleBar Button
// - Jump List owner when run from a Taskbar Jump List
// - Currently focused window if none of these match
public static class DisplayFusionFunction
{
/////////////////////////////////////////////////////////////////////////////////////
//Note: Replace the "Path" variable with the file you want to watch, //
// and replace the "SearchText" varaible with the text you want to watch for //
/////////////////////////////////////////////////////////////////////////////////////
private static readonly string Path = @"C:\Users\UserName\AppData\Roaming\Slack\logs\browser.log";
private static readonly string SearchText = "NEW_NOTIFICATION";
public static void Run(IntPtr windowHandle)
{
// Create a new FileTailWatcher with the parameters of our choosing
using(FileTailWatcher watcher = new FileTailWatcher(Path, SearchText))
{
// Assign the event that will get fired when the text is found in the file
watcher.OnSearchTextFound += SlackWatcher_OnSearchTextFound;
// Run the FileTailWatcher App
Application.Run(watcher);
}
}
// This event gets fired when the search text gets found
private static void SlackWatcher_OnSearchTextFound()
{
// Put any code you want here
BFS.Dialog.ShowTrayMessage("Hey You! You have a new slack message!!!");
}
// This custom class uses a FileSystemWatcher to watch for changes in
private class FileTailWatcher : ApplicationContext
{
// Variables
private long LastFileSize = 0;
private FileSystemWatcher Watcher;
private readonly string Path;
private readonly string SearchText;
// Delegates and Events
public delegate void DelegateVoid();
public event DelegateVoid OnSearchTextFound;
// This function sets up the class, and starts watching the end of the file
public FileTailWatcher(string path, string searchText)
{
this.Path = path;
this.SearchText = searchText;
FileInfo info = new FileInfo(this.Path);
this.LastFileSize = info.Length;
this.Watcher = new FileSystemWatcher(info.DirectoryName, info.Name);
this.Watcher.Changed += this.Watcher_Changed;
this.Watcher.EnableRaisingEvents = true;
}
// Do some cleanup
protected override void Dispose(bool disposing)
{
if(this.Watcher != null)
this.Watcher.Dispose();
base.Dispose(disposing);
}
// This method gets run when the file we're watching changes
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// Get the new file size
long length = new FileInfo(this.Path).Length;
// No point of looking through an empty file
// When other apps write to the file, they might also clear it, so don't set LastFileSize
if(length == 0)
return;
// If the file is the same size, ignore the change
if (length == this.LastFileSize)
return;
// Open the file for reading, but allow other programs to read and write from the file
using (FileStream file = File.Open(this.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader reader = new StreamReader(file))
{
//set the position of the stream to the last file size
reader.BaseStream.Position = this.LastFileSize;
//read each line until we find the EOF, or what we're looking for
while (true)
{
string line = reader.ReadLine();
if (line == null)
break;
// The text we're looking for isn't going to be on an empty line
if(string.IsNullOrEmpty(line))
continue;
//if we havn't found our text on this line, continue to the next one
if (line.IndexOf(this.SearchText, StringComparison.OrdinalIgnoreCase) == -1)
continue;
// If we got this far, we found what we wanted. no need to keep looking through the file.
// Fire the event
if(this.OnSearchTextFound != null)
this.OnSearchTextFound();
break;
}
}
// Set our last position searched
this.LastFileSize = length;
}
}
}