initial checkin of yaulw (locally)
This commit is contained in:
287
File/CHMFile.cs
Normal file
287
File/CHMFile.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Resources;
|
||||
using IO = System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using Yaulw.Process;
|
||||
using Diag = System.Diagnostics;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <summary>
|
||||
/// CHM Help File Wrapper
|
||||
/// </summary>
|
||||
public class CHMFile
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
/// <summary>
|
||||
/// The Full File Name and Path to the CHM File
|
||||
/// </summary>
|
||||
private string _FileNameNPath = "";
|
||||
|
||||
/// <summary>
|
||||
/// The File Stream that created the CHM File (if used)
|
||||
/// </summary>
|
||||
private IO.Stream _FileStream = null;
|
||||
|
||||
/// <summary>
|
||||
/// Internally we keep track of each Form to Help Context ID
|
||||
/// </summary>
|
||||
private Dictionary<Form, int> s_FormContextMap = new Dictionary<Form, int>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Construct a CHMFile object with the specified chm file
|
||||
/// </summary>
|
||||
/// <param name="FileNameNPath">a full path to a valid chm file</param>
|
||||
public CHMFile(string FileNameNPath)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(FileNameNPath) && IO.File.Exists(FileNameNPath) && (IO.Path.GetExtension(FileNameNPath).ToLower() == "chm"))
|
||||
_FileNameNPath = FileNameNPath;
|
||||
else
|
||||
throw new ArgumentException("Invalid chm File or File does not exist");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a CHMFile object from the specified stream (will construct a chm file in
|
||||
/// a temporary location from the specified stream)
|
||||
/// </summary>
|
||||
/// <param name="stream">stream to construct the chm file from</param>
|
||||
/// <param name="ApplicationName">The name of the application (will be used when creating the .chm file)</param>
|
||||
/// <param name="ForceNewFile">if true, will force a new file to be written out, false will only write file if not exists</param>
|
||||
public CHMFile(IO.Stream stream, string ApplicationName, bool ForceNewFile)
|
||||
{
|
||||
if (stream != null && !String.IsNullOrEmpty(ApplicationName))
|
||||
{
|
||||
_FileStream = stream;
|
||||
_FileNameNPath = IO.Path.GetTempPath() + ApplicationName + ".chm";
|
||||
EnsureCHMFileExistance(ForceNewFile);
|
||||
}
|
||||
else
|
||||
throw new ArgumentNullException("Resource can not be null. ApplicationName can not be empty");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Consts
|
||||
|
||||
/// <summary>
|
||||
/// Legacy MFC View Context offset
|
||||
/// </summary>
|
||||
public const int MNU = 0x10000;
|
||||
|
||||
/// <summary>
|
||||
/// Legacy MFC Dialog Context offset
|
||||
/// </summary>
|
||||
public const int DLG = 0x20000;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the HelpRequest Handler as well as shows the HelpButton on the CaptionBar
|
||||
/// </summary>
|
||||
/// <param name="form">WinForm to Attach Help Button to</param>
|
||||
/// <param name="dwContextId">the Help Topic Context Id to attach to the specified WinForm</param>
|
||||
public void AttachHelpCaptionButtonToWinForm(Form form, int dwContextId)
|
||||
{
|
||||
// Set the HelpButton to be displayed
|
||||
form.MinimizeBox = false;
|
||||
form.MaximizeBox = false;
|
||||
form.HelpButton = true;
|
||||
|
||||
// add the form / contextID to the map
|
||||
s_FormContextMap[form] = (int)dwContextId;
|
||||
|
||||
// Subscribe to the Help Requested Handler
|
||||
form.HelpRequested += new HelpEventHandler(form_HelpRequested);
|
||||
|
||||
// Subscribe to the Destroyed Event Handler *to remove the form from the list*
|
||||
form.HandleDestroyed += new EventHandler(form_HandleDestroyed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launch CHM Help
|
||||
/// </summary>
|
||||
public void LaunchHelp()
|
||||
{
|
||||
int bHelpIsAlreadyRunning_Pid = 0;
|
||||
Diag.Process[] ps = ProcessW.AllRunningProcessesOf("hh", false, true);
|
||||
if (ps != null && ps.Length >= 1)
|
||||
{
|
||||
foreach (Diag.Process p in ps)
|
||||
{
|
||||
string ProcessName = "";
|
||||
string CommandLine = "";
|
||||
ProcessW.GetCommandLineArgumentsForProcessPID(p.Id, out ProcessName, out CommandLine);
|
||||
if (CommandLine.Contains(_FileNameNPath))
|
||||
{
|
||||
bHelpIsAlreadyRunning_Pid = p.Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to launch a second time
|
||||
if (bHelpIsAlreadyRunning_Pid != 0)
|
||||
{
|
||||
// Set Focus
|
||||
IntPtr hWnd = Yaulw.Win32.Functions.GetFirstTopLevelWindowForProcess(bHelpIsAlreadyRunning_Pid);
|
||||
if (hWnd != IntPtr.Zero)
|
||||
Yaulw.Win32.User32.SetActiveWindow(hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Launch
|
||||
EnsureCHMFileExistance(false);
|
||||
PStarter.StartProcess(PStartInfo.CreateProcess(_FileNameNPath, "", "", false, System.Diagnostics.ProcessWindowStyle.Normal, true), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launch CHM Help
|
||||
/// </summary>
|
||||
/// <param name="form">form which will be the parent of the CHM File</param>
|
||||
public void LaunchHelp(Form form)
|
||||
{
|
||||
if (form != null)
|
||||
{
|
||||
Control control = Control.FromHandle(form.Handle);
|
||||
if (control != null)
|
||||
{
|
||||
EnsureCHMFileExistance(false);
|
||||
Help.ShowHelp(control, _FileNameNPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aunch CHM Help
|
||||
/// </summary>
|
||||
/// <param name="window">Window which will be the parent for the CHM file</param>
|
||||
public void LaunchHelp(Window window)
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
Control control = Control.FromHandle(GetHandleForWPFWindow(window));
|
||||
if (control != null)
|
||||
{
|
||||
EnsureCHMFileExistance(false);
|
||||
Help.ShowHelp(control, _FileNameNPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launch CHM Help for the specified Context
|
||||
/// </summary>
|
||||
/// <param name="form">form which will be the parent of the CHM File</param>
|
||||
/// <param name="dwContextId">Context Id to launch chm file with</param>
|
||||
public void LaunchHelp(Form form, int dwContextId)
|
||||
{
|
||||
if (form != null)
|
||||
{
|
||||
Control control = Control.FromHandle(form.Handle);
|
||||
if (control != null)
|
||||
{
|
||||
EnsureCHMFileExistance(false);
|
||||
Help.ShowHelp(control, _FileNameNPath, HelpNavigator.TopicId, dwContextId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aunch CHM Help for the specified Context
|
||||
/// </summary>
|
||||
/// <param name="window">Window which will be the parent for the CHM file</param>
|
||||
/// <param name="dwContextId">Context Id to launch chm file with</param>
|
||||
public void LaunchHelp(Window window, int dwContextId)
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
EnsureCHMFileExistance(false);
|
||||
Help.ShowHelp(null, _FileNameNPath, HelpNavigator.TopicId, dwContextId.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private WinForm Help Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handle HelpRequests
|
||||
/// </summary>
|
||||
private void form_HelpRequested(object sender, HelpEventArgs hlpevent)
|
||||
{
|
||||
Form form = sender as Form;
|
||||
if (form != null)
|
||||
{
|
||||
int dwContextId = s_FormContextMap[form];
|
||||
Help.ShowHelp(form, _FileNameNPath, HelpNavigator.TopicId, dwContextId.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Form Destroys
|
||||
/// </summary>
|
||||
private void form_HandleDestroyed(object sender, EventArgs e)
|
||||
{
|
||||
Form form = sender as Form;
|
||||
if (form != null)
|
||||
s_FormContextMap.Remove(form);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Creates the CHMFile from the stream (if a stream was used)
|
||||
/// </summary>
|
||||
/// <param name="ForceCreationOfFile">true to force re-creation of the file, false otherwise</param>
|
||||
private void EnsureCHMFileExistance(bool ForceCreationOfFile)
|
||||
{
|
||||
if (_FileStream != null)
|
||||
{
|
||||
if (ForceCreationOfFile || !IO.File.Exists(_FileNameNPath))
|
||||
{
|
||||
using (IO.FileStream fs = new IO.FileStream(_FileNameNPath, IO.FileMode.Create))
|
||||
{
|
||||
using (IO.BinaryWriter writer = new IO.BinaryWriter(fs))
|
||||
{
|
||||
// Read from the Resource
|
||||
Byte[] streamData = new Byte[_FileStream.Length];
|
||||
_FileStream.Read(streamData, 0, streamData.Length);
|
||||
|
||||
// Write to File
|
||||
writer.Write(streamData);
|
||||
writer.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the InteropHelper to get the Handle of a WPF Window
|
||||
/// </summary>
|
||||
/// <param name="window">a WPF Window</param>
|
||||
/// <returns>an hWnd for the specified WPF Window</returns>
|
||||
private IntPtr GetHandleForWPFWindow(Window window)
|
||||
{
|
||||
WindowInteropHelper InteropHelper = new WindowInteropHelper(window);
|
||||
return InteropHelper.Handle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
193
File/FileWriter.cs
Normal file
193
File/FileWriter.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <remarks>
|
||||
/// Simple Line-By-Line UTF/Ascii File Writer Object
|
||||
/// </remarks>
|
||||
public class FileWriter
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private string _FileName = "";
|
||||
private string _FileType = "";
|
||||
private string _dirPath = "";
|
||||
private bool _OverideExisting = false;
|
||||
private bool _FileIsCreated = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Create a Simple UTF/Ascii Line FileWriter Object
|
||||
/// </summary>
|
||||
/// <param name="FileName">The Name of the File (If blank will generate a random file name)</param>
|
||||
/// <param name="FileType">The Type of File to write to (Default = "log")</param>
|
||||
/// <param name="dirPath">The path where to write the file (If Blank will use Temp Path)</param>
|
||||
/// <param name="OverideExisting">true to overide an existing file, false will try to append by default</param>
|
||||
public FileWriter(string FileName = "", string FileType = "log", string dirPath = "", bool OverideExisting = true)
|
||||
{
|
||||
_FileName = FileName;
|
||||
_FileType = FileType;
|
||||
_dirPath = dirPath;
|
||||
_OverideExisting = OverideExisting;
|
||||
|
||||
// Generate File Name and Path, if not exist
|
||||
if(String.IsNullOrEmpty(_FileName))
|
||||
_FileName = System.IO.Path.GetFileNameWithoutExtension(System.IO.Path.GetRandomFileName());
|
||||
if(String.IsNullOrEmpty(_dirPath))
|
||||
_dirPath = System.IO.Path.GetTempPath();
|
||||
|
||||
// Make Sure Path Exists
|
||||
if (!Directory.Exists(_dirPath))
|
||||
Directory.CreateDirectory(_dirPath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Write Ascii
|
||||
|
||||
/// <summary>
|
||||
/// Write a Line in Ascii to File
|
||||
/// </summary>
|
||||
/// <param name="line">ascii line to write</param>
|
||||
public void WriteLineA(string line)
|
||||
{
|
||||
using (FileStream fs = CreateFileStream())
|
||||
using(StreamWriter sw = new StreamWriter(fs, Encoding.ASCII))
|
||||
{
|
||||
sw.WriteLine(line);
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Lines in Ascii to file
|
||||
/// </summary>
|
||||
/// <param name="lines">ascii lines to write</param>
|
||||
public void WriteLineA(string[] lines)
|
||||
{
|
||||
using (FileStream fs = CreateFileStream())
|
||||
using (StreamWriter sw = new StreamWriter(fs, Encoding.ASCII))
|
||||
{
|
||||
foreach (string line in lines)
|
||||
sw.WriteLine(line);
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Write UTF
|
||||
|
||||
/// <summary>
|
||||
/// Write a Line in UTF to File
|
||||
/// </summary>
|
||||
/// <param name="line">utf line to write</param>
|
||||
public void WriteLineUTF8(string line)
|
||||
{
|
||||
using (FileStream fs = CreateFileStream())
|
||||
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
|
||||
{
|
||||
sw.WriteLine(line);
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Lines in UTF to File
|
||||
/// </summary>
|
||||
/// <param name="lines">utf lines to write</param>
|
||||
public void WriteLineUTF8(string[] lines)
|
||||
{
|
||||
using (FileStream fs = CreateFileStream())
|
||||
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
|
||||
{
|
||||
foreach (string line in lines)
|
||||
sw.WriteLine(line);
|
||||
sw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns the File Name
|
||||
/// </summary>
|
||||
public string FileName { get { return (this._FileName + "." + this._FileType); } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Path where the File is located
|
||||
/// </summary>
|
||||
public string Path { get { return (this._dirPath); } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns both Path and FileName
|
||||
/// </summary>
|
||||
public string FileNameNPath { get { return (this.Path + "\\" + this.FileName); } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the File, if it exists
|
||||
/// </summary>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
public bool DeleteFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (System.IO.File.Exists(this.FileNameNPath))
|
||||
{
|
||||
System.IO.File.Delete(this.FileNameNPath);
|
||||
_FileIsCreated = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates the File Stream, either in Create or Append Mode
|
||||
/// </summary>
|
||||
/// <returns>a File Stream to Write to * Must be Closed by Caller *</returns>
|
||||
private FileStream CreateFileStream()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool bFileExists = System.IO.File.Exists(this.FileNameNPath);
|
||||
if (!_FileIsCreated && _OverideExisting && bFileExists)
|
||||
{
|
||||
_FileIsCreated = true;
|
||||
return (new FileStream(this.FileNameNPath, FileMode.Create));
|
||||
}
|
||||
else if (bFileExists)
|
||||
{
|
||||
return (new FileStream(this.FileNameNPath, FileMode.Append));
|
||||
}
|
||||
else
|
||||
{
|
||||
_FileIsCreated = true;
|
||||
return (new FileStream(this.FileNameNPath, FileMode.Create));
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
213
File/INIFile.cs
Normal file
213
File/INIFile.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Yaulw.Tools;
|
||||
using Yaulw.Win32;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <remarks>
|
||||
/// Responsible for Reading and Writing an INI File.
|
||||
/// Simply construct an INIFile Object passing in a File name and Path,
|
||||
/// as well as an enum that lists all the Categories and Keys.
|
||||
///
|
||||
/// An example *You can mix and match Categories and Keys as needed *:
|
||||
/// public enum INICatsNKeys
|
||||
/// {
|
||||
/// App_Settings__Load_XML_At_StartUp,
|
||||
/// App_Settings__Allow_Command_Line_to_override_INI,
|
||||
/// App_Settings__Default_User,
|
||||
/// App_Settings__Default_Server,
|
||||
/// Runtime_Debug__Error_Debug_Level,
|
||||
/// Data_Access__Read_Only,
|
||||
/// Settings__Program_Folder,
|
||||
/// Settings__User1_Default,
|
||||
/// Recent_File_List__File1,
|
||||
/// Recent_File_List__File2,
|
||||
/// Recent_File_List__File3,
|
||||
/// Recent_File_List__File4,
|
||||
/// }
|
||||
///
|
||||
/// The '__' Character signifies a category to Key change
|
||||
/// the '_' will be replaced by ' ', when actually writing to the Ini File.
|
||||
/// </remarks>
|
||||
public class INIFile
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private string _IniPathNFileName = String.Empty;
|
||||
private Type _IniKeysNCategories = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an INIFile object with a valid path and FileName to write/read from.
|
||||
/// Also pass in an Enum Type that contains Category and Key Information. This Enum will be used
|
||||
/// to read and write to the INIFile (to determine which Section/Key to read/write from/to)
|
||||
/// </summary>
|
||||
/// <param name="IniPathNFileName">Pass in the full file name and path to use * Creates Directory, if it does not exits *</param>
|
||||
/// <param name="IniKeysNCategories">Pass in an Enum that specifies the Categories and Keys</param>
|
||||
/// <exception cref="ArgumentException">Thrown if an invalid Enum is passed in via IniKeysNCategories</exception>
|
||||
public INIFile(string IniPathNFileName, Type IniKeysNCategories)
|
||||
{
|
||||
// Check and ensure Enum Accuracy
|
||||
if (IniKeysNCategories.IsEnum && EnumTool.EnumType_HasCategoryNKey(IniKeysNCategories))
|
||||
{
|
||||
_IniKeysNCategories = IniKeysNCategories;
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("IniKeysNCategories is not an Enum or not all Enums contain Key and Category Information");
|
||||
|
||||
// Ensure Directory Existence
|
||||
if (!Directory.Exists(Path.GetDirectoryName(IniPathNFileName)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(IniPathNFileName));
|
||||
_IniPathNFileName = IniPathNFileName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Ini File Used by IniFile
|
||||
/// </summary>
|
||||
public string IniFile { get { return _IniPathNFileName; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Ini Key Reader / Writer Functions
|
||||
|
||||
/// <summary>
|
||||
/// Use this to directly set a key to any string value
|
||||
/// </summary>
|
||||
/// <param name="cKey">Specify Key and category set Directly</param>
|
||||
/// <param name="Value">value to set</param>
|
||||
/// <exception cref="ArgumentException">If cKey is not a valid Category/Key Pair Enum</exception>
|
||||
public void SetKeyValue<T>(Enum cKey, T Value)
|
||||
{
|
||||
if (EnumTool.Enum_HasCategoryNKey(cKey))
|
||||
{
|
||||
string Category;
|
||||
string Key;
|
||||
EnumTool.Enum_ToCategoryNKey(cKey, out Category, out Key);
|
||||
string ValueStr = ObjTool.ConvertObjToString<T>(Value);
|
||||
SetKeyValueString(Category, Key, ValueStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("cKey must have both Category and Key Information");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to directly retrieve a key
|
||||
/// </summary>
|
||||
/// <param name="cKey">Specify Key and category set Directly</param>
|
||||
/// <param name="defaultValue">default value to return, if not found</param>
|
||||
/// <returns>value retrieved or default value</returns>
|
||||
/// <exception cref="ArgumentException">If cKey is not a valid Category/Key Pair Enum</exception>
|
||||
public T GetKeyValue<T>(Enum cKey, T defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (EnumTool.Enum_HasCategoryNKey(cKey))
|
||||
{
|
||||
string Category;
|
||||
string Key;
|
||||
EnumTool.Enum_ToCategoryNKey(cKey, out Category, out Key);
|
||||
|
||||
// Get Key and verify that something was found
|
||||
string defaultValueStr = ObjTool.ConvertObjToString<T>(defaultValue);
|
||||
string KeyValue = GetKeyValueString(Category, Key, defaultValueStr);
|
||||
bool bHasAValue = (KeyValue.Trim().Length != 0);
|
||||
|
||||
// always write the value back out to ini
|
||||
SetKeyValue(cKey, bHasAValue ? KeyValue : defaultValueStr);
|
||||
|
||||
// Return value
|
||||
if (bHasAValue)
|
||||
{
|
||||
return ObjTool.ConvertStringToObj<T>(KeyValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("cKey must have both Category and Key Information");
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Generic Ini Key Reader / Writer Functions
|
||||
|
||||
/// <summary>
|
||||
/// Set a value for the specified Key and for the specified category
|
||||
/// </summary>
|
||||
/// <param name="category">specify category</param>
|
||||
/// <param name="key">specify key</param>
|
||||
/// <param name="value">specify a value to set</param>
|
||||
private void SetKeyValueString(string category, string key, string value)
|
||||
{
|
||||
bool bSuccess = Kernel32.WritePrivateProfileString(category, key, value, IniFile);
|
||||
Debug.Assert(bSuccess);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the value for a specified Key and for a specified category
|
||||
/// </summary>
|
||||
/// <param name="category">specify category</param>
|
||||
/// <param name="key">specify key</param>
|
||||
/// <param name="defaultValue">specify default value, returned when no value found</param>
|
||||
/// <returns>the value for the Key, or default value if no value found</returns>
|
||||
private string GetKeyValueString(string category, string key, string defaultValue)
|
||||
{
|
||||
StringBuilder returnString = new StringBuilder(1024);
|
||||
Kernel32.GetPrivateProfileString(category, key, defaultValue, returnString, 1024, IniFile);
|
||||
return returnString.ToString().Split('\0')[0];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Generic Ini File Readers (Not Used)
|
||||
|
||||
/// <summary>
|
||||
/// Use this to return all the categories in an INI File
|
||||
/// </summary>
|
||||
/// <returns>a list with Gategory Items, or 0 length list is none found</returns>
|
||||
private List<string> GetAllCategories()
|
||||
{
|
||||
StringBuilder returnString = new StringBuilder(65536);
|
||||
uint returnValue = Kernel32.GetPrivateProfileString(null, null, null, returnString, 65536, IniFile);
|
||||
List<string> result = new List<string>(returnString.ToString().Split('\0'));
|
||||
result.RemoveRange(result.Count - 2, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to return the Keys from a category from an INI File
|
||||
/// </summary>
|
||||
/// <returns>a list with Key Items, or 0 length list is none found</returns>
|
||||
private List<string> GetAllKeysInCategory(string category)
|
||||
{
|
||||
StringBuilder returnString = new StringBuilder(32768);
|
||||
Kernel32.GetPrivateProfileString(category, null, null, returnString, 32768, IniFile);
|
||||
List<string> result = new List<string>(returnString.ToString().Split('\0'));
|
||||
result.RemoveRange(result.Count - 2, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
185
File/ISReadWrite.cs
Normal file
185
File/ISReadWrite.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum ISScope
|
||||
{
|
||||
User,
|
||||
Machine,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class allows reading and writing to isolated Storage
|
||||
/// </summary>
|
||||
public class ISReadWrite
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private string _ISOLATED_STORAGE_FILENAME = "";
|
||||
private bool _bFileInIsoStoreExists = false;
|
||||
private Xml.XSerializer _XSerializer = null;
|
||||
private IsolatedStorageScope _scope = IsolatedStorageScope.None;
|
||||
private IsolatedStorageFile _isoStore = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ISFileName"></param>
|
||||
public ISReadWrite(string ISFileName) : this(ISFileName, ISScope.Machine) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ISFileName"></param>
|
||||
/// <param name="scope"></param>
|
||||
public ISReadWrite(string ISFileName, ISScope scope)
|
||||
{
|
||||
_ISOLATED_STORAGE_FILENAME = ISFileName;
|
||||
|
||||
if (String.IsNullOrEmpty(_ISOLATED_STORAGE_FILENAME))
|
||||
throw new ArgumentNullException("ISFileName can not be empty.");
|
||||
#if NET4
|
||||
if (!IsolatedStorageFile.IsEnabled)
|
||||
throw new Exception("Isolated Storage not enabled");
|
||||
#endif
|
||||
_scope = ConvertISScopeToIsolatedStorageScope(scope);
|
||||
_isoStore = IsolatedStorageFile.GetStore(_scope, typeof(System.Security.Policy.Url), typeof(System.Security.Policy.Url));
|
||||
_bFileInIsoStoreExists = (_isoStore.GetFileNames(ISFileName).Length > 0);
|
||||
_XSerializer = new Xml.XSerializer();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Read / Write Methods
|
||||
|
||||
public string ReadFromIS()
|
||||
{
|
||||
using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(_ISOLATED_STORAGE_FILENAME, FileMode.OpenOrCreate, _isoStore))
|
||||
using (StreamReader reader = new StreamReader(fs))
|
||||
{
|
||||
_bFileInIsoStoreExists = true;
|
||||
string strFileContents = reader.ReadToEnd();
|
||||
if (!String.IsNullOrEmpty(strFileContents))
|
||||
return strFileContents;
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T ReadFromIS<T>()
|
||||
{
|
||||
using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(_ISOLATED_STORAGE_FILENAME, FileMode.OpenOrCreate, _isoStore))
|
||||
using (StreamReader reader = new StreamReader(fs))
|
||||
{
|
||||
_bFileInIsoStoreExists = true;
|
||||
string strFileContents = reader.ReadToEnd();
|
||||
if (!String.IsNullOrEmpty(strFileContents))
|
||||
{
|
||||
T t = _XSerializer.ReadFromString<T>(strFileContents);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="SerializableObject"></param>
|
||||
public void WriteToIS<T>(T XMLSerializableObject) where T : new()
|
||||
{
|
||||
using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(_ISOLATED_STORAGE_FILENAME, FileMode.Create, _isoStore))
|
||||
using (StreamWriter writer = new StreamWriter(fs))
|
||||
{
|
||||
_bFileInIsoStoreExists = true;
|
||||
string strFileContentsToWrite = _XSerializer.WriteToString<T>(XMLSerializableObject);
|
||||
if(!String.IsNullOrEmpty(strFileContentsToWrite))
|
||||
writer.Write(strFileContentsToWrite);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteToIS(string Content)
|
||||
{
|
||||
using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(_ISOLATED_STORAGE_FILENAME, FileMode.Create, _isoStore))
|
||||
using (StreamWriter writer = new StreamWriter(fs))
|
||||
{
|
||||
_bFileInIsoStoreExists = true;
|
||||
string strFileContentsToWrite = Content;
|
||||
if (!String.IsNullOrEmpty(strFileContentsToWrite))
|
||||
writer.Write(strFileContentsToWrite);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Delete()
|
||||
{
|
||||
if (_bFileInIsoStoreExists)
|
||||
{
|
||||
_isoStore.DeleteFile(_ISOLATED_STORAGE_FILENAME);
|
||||
_bFileInIsoStoreExists = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public bool Exists
|
||||
{
|
||||
get { return _bFileInIsoStoreExists; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="scope"></param>
|
||||
/// <returns></returns>
|
||||
private IsolatedStorageScope ConvertISScopeToIsolatedStorageScope(ISScope scope)
|
||||
{
|
||||
switch (scope)
|
||||
{
|
||||
case ISScope.User:
|
||||
return IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly;
|
||||
|
||||
case ISScope.Machine:
|
||||
return IsolatedStorageScope.Machine | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly;
|
||||
}
|
||||
return IsolatedStorageScope.Application;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
172
File/LineReplacer.cs
Normal file
172
File/LineReplacer.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using IO = System.IO;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
#region Rule Definitions
|
||||
|
||||
/// <summary>
|
||||
/// Comparer Modifier used when looking at the line
|
||||
/// </summary>
|
||||
public enum LineReplace_ComparerModifier
|
||||
{
|
||||
None,
|
||||
toLower,
|
||||
toUpper,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rule Used to determine which line to replace
|
||||
/// ~Replace Line with contains the new line to put instead
|
||||
/// </summary>
|
||||
public struct LineReplace_Rule
|
||||
{
|
||||
public string Contains;
|
||||
public string StartsWith;
|
||||
public string EndsWith;
|
||||
public LineReplace_ComparerModifier Comparer;
|
||||
public string ReplaceLineWith;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Useful for replacing lines in a text file.
|
||||
/// It reads in a text file line by line and compares the lines.
|
||||
/// Using the rules you can replace a line or multiple lines and write out to the text file.
|
||||
/// </summary>
|
||||
public class LineReplacer
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private Dictionary<String, LineReplace_Rule> _RulesDictionary = new Dictionary<string, LineReplace_Rule>();
|
||||
private string _fileNameNPath = "";
|
||||
private Encoding _encoding = Encoding.UTF8;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Allows for easy line replacing of a text file
|
||||
/// </summary>
|
||||
/// <param name="FileNameNPath">Full File Name and Path to a file that exists</param>
|
||||
/// <exception cref="ArgumentException">Thrown when File does not exist</exception>
|
||||
public LineReplacer(string FileNameNPath, Encoding encoding)
|
||||
{
|
||||
if (String.IsNullOrEmpty(FileNameNPath) || !IO.File.Exists(FileNameNPath))
|
||||
throw new ArgumentException("Line Replace makes only sense on Files that exist already");
|
||||
|
||||
_fileNameNPath = FileNameNPath;
|
||||
_encoding = encoding;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Add/Update Line Replacing Rules into here BEFORE calling ReplaceLines()
|
||||
/// </summary>
|
||||
/// <param name="RuleName">unique name of the rule</param>
|
||||
/// <param name="rule">Rule Definition</param>
|
||||
/// <returns>true if successfully added, false otherwise</returns>
|
||||
public bool AddUpdateRule(string RuleName, LineReplace_Rule rule)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(RuleName))
|
||||
{
|
||||
// We must be able to match on something
|
||||
if (String.IsNullOrEmpty(rule.StartsWith) && String.IsNullOrEmpty(rule.EndsWith) &&
|
||||
String.IsNullOrEmpty(rule.Contains))
|
||||
return false;
|
||||
|
||||
// We must be able to replace with something
|
||||
if (String.IsNullOrEmpty(rule.ReplaceLineWith))
|
||||
return false;
|
||||
|
||||
// Rule is good, add it
|
||||
_RulesDictionary[RuleName] = rule;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this Function to Replace all the Lines of the Text Files that
|
||||
/// match a specific Rule
|
||||
/// </summary>
|
||||
public void ReplaceLines()
|
||||
{
|
||||
if (_RulesDictionary.Count <= 0)
|
||||
return;
|
||||
|
||||
// # Readin and Process all Lines
|
||||
List<string> ReadInLines = new List<string>();
|
||||
using (IO.FileStream fs = new IO.FileStream(_fileNameNPath, IO.FileMode.Open))
|
||||
using (IO.StreamReader reader = new IO.StreamReader(fs, _encoding))
|
||||
{
|
||||
// # Iterate thru all the lines in the File
|
||||
for (string Line = reader.ReadLine(); Line != null; Line = reader.ReadLine())
|
||||
{
|
||||
FoundRuleMathAndPerformedAction(ref Line);
|
||||
ReadInLines.Add(Line);
|
||||
}
|
||||
}
|
||||
|
||||
// # Write out all the Lines
|
||||
using (IO.FileStream fs = new IO.FileStream(_fileNameNPath, IO.FileMode.Create))
|
||||
using (IO.StreamWriter writer = new IO.StreamWriter(fs, _encoding))
|
||||
{
|
||||
foreach (string Line in ReadInLines)
|
||||
writer.WriteLine(Line);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for finding a match between a line and a rule and
|
||||
/// performing the action
|
||||
/// </summary>
|
||||
/// <param name="Line">Line to find a match for</param>
|
||||
/// <returns>true, if match was found/action was done, false otherwise</returns>
|
||||
private bool FoundRuleMathAndPerformedAction(ref string Line)
|
||||
{
|
||||
if (String.IsNullOrEmpty(Line))
|
||||
return false;
|
||||
|
||||
bool bFoundMatch = false;
|
||||
// Iterate foreach rule for a line
|
||||
foreach (LineReplace_Rule rule in _RulesDictionary.Values)
|
||||
{
|
||||
// Make sure to use the proper comparer Modifier for the rule
|
||||
string line = Line;
|
||||
if (rule.Comparer == LineReplace_ComparerModifier.toLower)
|
||||
line = Line.ToLower();
|
||||
else if (rule.Comparer == LineReplace_ComparerModifier.toUpper)
|
||||
line = Line.ToUpper();
|
||||
|
||||
// Now let's match on the actual Rule
|
||||
if (!bFoundMatch && !String.IsNullOrEmpty(rule.StartsWith))
|
||||
bFoundMatch = line.StartsWith(rule.StartsWith);
|
||||
if (!bFoundMatch && !String.IsNullOrEmpty(rule.EndsWith))
|
||||
bFoundMatch = line.StartsWith(rule.EndsWith);
|
||||
if (!bFoundMatch && !String.IsNullOrEmpty(rule.Contains))
|
||||
bFoundMatch = line.StartsWith(rule.Contains);
|
||||
if (bFoundMatch)
|
||||
{
|
||||
Line = rule.ReplaceLineWith;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bFoundMatch;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
176
File/LoggerQuick.cs
Normal file
176
File/LoggerQuick.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Yaulw.Assembly;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <summary>
|
||||
/// Easy Class for quick and dirty logging *that can automatically on a daily basis*
|
||||
/// </summary>
|
||||
public class LoggerQuick
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
/// <summary>
|
||||
/// FileWriter Object
|
||||
/// </summary>
|
||||
private Yaulw.File.FileWriter _fileWriter = null;
|
||||
|
||||
/// <summary>
|
||||
/// Current Directory
|
||||
/// </summary>
|
||||
private string _curPath = "";
|
||||
|
||||
/// <summary>
|
||||
/// Log Debug Messages
|
||||
/// </summary>
|
||||
private bool _LogDebug = false;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the Log (also serves as RegKey)
|
||||
/// </summary>
|
||||
private string LogName = "";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Quick Logger (which can clear itself daily and has no dependencies)
|
||||
/// quick n' dirty logs in the current directory from which it is called
|
||||
/// </summary>
|
||||
/// <param name="LogName">Name of the Log file</param>
|
||||
/// <param name="bLogDebugMessages">true to spit out DebugMessages, false otherwise</param>
|
||||
public LoggerQuick(string LogName, bool bLogDebugMessages)
|
||||
{
|
||||
if(String.IsNullOrEmpty(LogName))
|
||||
throw new ArgumentException("LogName can't be empty");
|
||||
|
||||
// Log Name, which will also server as the registry key name
|
||||
this.LogName = Path.GetFileName(LogName);
|
||||
|
||||
// Log Debug Messages?
|
||||
_LogDebug = bLogDebugMessages;
|
||||
|
||||
// Get the current running directory
|
||||
if (String.IsNullOrEmpty(_curPath))
|
||||
_curPath = Path.GetDirectoryName(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileNameNPath(AssemblyW.AssemblyST.Executing));
|
||||
|
||||
// Set up FileWriter
|
||||
if (_fileWriter == null)
|
||||
_fileWriter = new Yaulw.File.FileWriter(LogName, "log", _curPath, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick Logger (which can clear itself daily and has no dependencies)
|
||||
/// quick n' dirty logs in the current directory from which it is called
|
||||
/// </summary>
|
||||
/// <param name="LogName">Name of the Log file</param>
|
||||
/// <param name="bLogDebugMessages">true to spit out DebugMessages, false otherwise</param>
|
||||
/// <param name="path">path to log to</param>
|
||||
public LoggerQuick(string LogName, bool bLogDebugMessages, string path)
|
||||
{
|
||||
if (String.IsNullOrEmpty(LogName))
|
||||
throw new ArgumentException("LogName can't be empty");
|
||||
|
||||
// Log Name, which will also server as the registry key name
|
||||
this.LogName = Path.GetFileName(LogName);
|
||||
|
||||
// Log Debug Messages?
|
||||
_LogDebug = bLogDebugMessages;
|
||||
|
||||
// make sure path is valid
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
|
||||
// Get the current running directory
|
||||
if (String.IsNullOrEmpty(_curPath) && String.IsNullOrEmpty(path))
|
||||
_curPath = Path.GetDirectoryName(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileNameNPath(AssemblyW.AssemblyST.Executing));
|
||||
else
|
||||
_curPath = path;
|
||||
|
||||
// Set up FileWriter
|
||||
if (_fileWriter == null)
|
||||
_fileWriter = new Yaulw.File.FileWriter(LogName, "log", _curPath, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Log Methods
|
||||
|
||||
/// <summary>
|
||||
/// Debug Logging only logs when _LogDebug is set
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="args"></param>
|
||||
public void Debug(string line, params object[] args)
|
||||
{
|
||||
if (_LogDebug)
|
||||
Log("Debug: ", line, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Info Logging
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="args"></param>
|
||||
public void Info(string line, params object[] args)
|
||||
{
|
||||
Log("Info: ", line, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error Logging
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="args"></param>
|
||||
public void Error(string line, params object[] args)
|
||||
{
|
||||
Log("Error: ", line, args);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Log Methods
|
||||
|
||||
/// <summary>
|
||||
/// Used for logging * Medisoft people * crack me up
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="ars"></param>
|
||||
private void Log(string prePrend, string line, params object[] args)
|
||||
{
|
||||
if (_fileWriter != null)
|
||||
{
|
||||
// Clear the log once a day automatically - yeah!
|
||||
DateTime LastLogged = Yaulw.Registry.RegKey.GetKey<DateTime>("LoggerQuick", LogName, DateTime.MinValue);
|
||||
if (LastLogged != DateTime.MinValue && LastLogged.Day != DateTime.Now.Day)
|
||||
_fileWriter.DeleteFile();
|
||||
|
||||
// Always set the DT Stamp, for every log
|
||||
Yaulw.Registry.RegKey.SetKey<DateTime>("LoggerQuick", LogName, DateTime.Now);
|
||||
|
||||
// Now let's start Logging
|
||||
line = prePrend + line;
|
||||
if (args != null)
|
||||
_fileWriter.WriteLineA(String.Format(line, args));
|
||||
else
|
||||
_fileWriter.WriteLineA(line);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
391
File/Logging.cs
Normal file
391
File/Logging.cs
Normal file
@@ -0,0 +1,391 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Diag = System.Diagnostics;
|
||||
|
||||
// Log4Net Declarations
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Layout;
|
||||
using log4net.Config;
|
||||
using log4net;
|
||||
using Yaulw.Other;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <summary>
|
||||
/// Logging Detail
|
||||
/// </summary>
|
||||
public enum Logging_Detail
|
||||
{
|
||||
NONE,
|
||||
ERROR,
|
||||
INFO,
|
||||
DEBUG
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to Configure a Logger Instance in the Logging Class via AddGlobalLoggerConfiguration()
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// Logging_Configuration config;
|
||||
/// config.LogFileNameNPath = "c:\\LogFile.log";
|
||||
/// config.Detail = Logging_Detail.Error;
|
||||
/// config.UseExclusiveFileLock = false;
|
||||
/// config.maxFileSizeInMB = 4;
|
||||
/// config.numOfBackupLogFiles = 3;
|
||||
/// config.Log4NetDetailPatternLayout = "%date{dd MMM HH:mm:ss,fff} [%thread] %level - %message%newline"; (Default)
|
||||
/// "%date{dd MMM yyyy HH:mm:ss,fff} [%thread] %level %logger - %message%newline";
|
||||
/// config.LogCallingTypeAndCallingFunction = true;
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public struct Logging_Configuration
|
||||
{
|
||||
public string LogFileNameNPath;
|
||||
public Logging_Detail Detail;
|
||||
public bool UseExclusiveFileLock;
|
||||
public int maxFileSizeInMB;
|
||||
public int numOfBackupLogFiles;
|
||||
public string Log4NetDetailPatternLayout;
|
||||
public bool LogCallingType;
|
||||
public bool LogCallingFunction;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Is a Wrapper Object around Log4Net's Rolling File Appender.
|
||||
/// Use it by calling AddGlobalLoggerConfiguration() with a valid Logging Configuration.
|
||||
/// You can configure multipe Logger Instances distinguished by Name.
|
||||
/// subsequent calls can call GetLogger() with the named Logger instance to receive a valid logger object
|
||||
/// </remarks>
|
||||
public class Logging
|
||||
{
|
||||
#region Private Static Members
|
||||
|
||||
private static Dictionary<string, Logging_Configuration> _loggerConfigurationMap = new Dictionary<string, Logging_Configuration>();
|
||||
private static Dictionary<string, ILog> _loggerObjects = new Dictionary<string, ILog>();
|
||||
|
||||
// If this process is hosted in VS then it changes the stack frame
|
||||
private static bool s_IsVSHosted = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Construction
|
||||
|
||||
/// <summary>
|
||||
/// Private Constructor should only be called by static GetLogger() Function
|
||||
/// </summary>
|
||||
/// <param name="bLogCallingTypeAndCallingFunction">if true, will log calling type and Calling Function</param>
|
||||
private Logging(bool bLogCallingType, bool bLogCallingFunction)
|
||||
{
|
||||
s_IsVSHosted = Diag.Process.GetCurrentProcess().ProcessName.Contains("vshost");
|
||||
_LogCallingType = bLogCallingType;
|
||||
_LogCallingFunction = bLogCallingFunction;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Members
|
||||
|
||||
// Initialized by GetLogger()
|
||||
internal ILog _Log4NetLog = null;
|
||||
|
||||
// Initialized by GetLogger()
|
||||
internal bool _LogCallingType = false;
|
||||
|
||||
// Initialized by GetLogger()
|
||||
internal bool _LogCallingFunction = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Log Methods
|
||||
|
||||
/// <summary>
|
||||
/// Log Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Info(string message, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Info(MessageHeader() + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Info(string message, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Info(MessageHeader(nPlusMinus) + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Info(string message, Exception exception, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Info(MessageHeader() + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Info(string message, Exception exception, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Info(MessageHeader(nPlusMinus) + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Debug Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Debug(string message, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Debug(MessageHeader() + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Debug Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Debug(string message, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Debug(MessageHeader(nPlusMinus) + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Debug Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Debug(string message, Exception exception, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Debug(MessageHeader() + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Debug Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Debug(string message, Exception exception, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Debug(MessageHeader(nPlusMinus) + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Error(string message, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Error(MessageHeader() + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Error(string message, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Error(MessageHeader(nPlusMinus) + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Error(string message, Exception exception, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Error(MessageHeader() + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Error(string message, Exception exception, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Error(MessageHeader(nPlusMinus) + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Fatal Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Fatal(string message, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Fatal(MessageHeader() + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Fatal Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Fatal(string message, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Fatal(MessageHeader(nPlusMinus) + String.Format(message, args)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Fatal Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Fatal(string message, Exception exception, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Fatal(MessageHeader() + String.Format(message, args), exception); } }
|
||||
|
||||
/// <summary>
|
||||
/// Log Fatal Error Information
|
||||
/// </summary>
|
||||
/// <param name="message">Message to write</param>
|
||||
/// <param name="exception">Exception to Log</param>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
/// <param name="args">arguments to pass to String.Format</param>
|
||||
public void Fatal(string message, Exception exception, int nPlusMinus, params object[] args) { if (_Log4NetLog != null) { _Log4NetLog.Fatal(MessageHeader(nPlusMinus) + String.Format(message, args), exception); } }
|
||||
|
||||
/// <returns>
|
||||
/// Message Header to be shown on every log message
|
||||
/// </returns>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
private string MessageHeader(int nPlusMinus = 0)
|
||||
{
|
||||
// When Running this from via VS it behaves differently then when
|
||||
// running it outside of it, when running it regularly, each foreach loop
|
||||
if (s_IsVSHosted)
|
||||
{
|
||||
if (_LogCallingType && _LogCallingFunction)
|
||||
return StackWalker.GetTypeFromStack(nPlusMinus + 1) + " - " + StackWalker.GetMethodNameFromStack(nPlusMinus + 1) + "()- ";
|
||||
else if (_LogCallingFunction)
|
||||
return StackWalker.GetMethodNameFromStack(nPlusMinus + 1) + "()- ";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_LogCallingType && _LogCallingFunction)
|
||||
return StackWalker.GetTypeFromStack(nPlusMinus) + " - " + StackWalker.GetMethodNameFromStack(nPlusMinus) + "()- ";
|
||||
else if (_LogCallingFunction)
|
||||
return StackWalker.GetMethodNameFromStack(nPlusMinus) + "()- ";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Configuration and Logger Creation Methods
|
||||
|
||||
/// <summary>
|
||||
/// Used to add a new Configuration and Logger Instance onto a Static Map.
|
||||
/// Will create one logger instance per unique name.
|
||||
/// </summary>
|
||||
/// <param name="Name">a name for the logger instance</param>
|
||||
/// <param name="Configuration">a valid configuration to use on the instance</param>
|
||||
/// <returns>a logging object that can be used to log</returns>
|
||||
public static Logging AddGlobalLoggerConfiguration(string Name, Logging_Configuration Configuration)
|
||||
{
|
||||
// Must have a Valid Input
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
throw new ArgumentException("Name Is Invalid");
|
||||
|
||||
if (!_loggerObjects.Keys.Contains(Name.ToLower()))
|
||||
{
|
||||
// Create the Repository
|
||||
log4net.Repository.ILoggerRepository repository = LogManager.CreateRepository(Name.ToLower());
|
||||
|
||||
// Create FileAppender Configuration
|
||||
RollingFileAppender appender = RollingFileAppenderCreator(Configuration);
|
||||
|
||||
// Run the Configuration against the Repository
|
||||
BasicConfigurator.Configure(repository, appender);
|
||||
|
||||
// Add Configuration to our Static Map
|
||||
_loggerConfigurationMap[Name.ToLower()] = Configuration;
|
||||
|
||||
// Last, but not least, Create the new Logging Instance Object and Store it
|
||||
_loggerObjects[Name.ToLower()] = LogManager.GetLogger(Name.ToLower(), Name.ToLower());
|
||||
}
|
||||
|
||||
// Let the Caller get the Logging Object
|
||||
return GetLogger(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to retrieve a named logging instance that has already been created via a previous call
|
||||
/// to AddGlobalLoggerConfiguration().
|
||||
/// </summary>
|
||||
/// <param name="Name">a name for a previously created Logging instance</param>
|
||||
/// <returns>a Logging object that can be used to log</returns>
|
||||
public static Logging GetLogger(string Name)
|
||||
{
|
||||
if (_loggerObjects.Keys.Contains(Name.ToLower()) && _loggerConfigurationMap.Keys.Contains(Name.ToLower()))
|
||||
{
|
||||
bool bLogCallingType = _loggerConfigurationMap[Name.ToLower()].LogCallingType;
|
||||
bool bLogCallingFunction = _loggerConfigurationMap[Name.ToLower()].LogCallingFunction;
|
||||
Logging logger = new Logging(bLogCallingType, bLogCallingFunction);
|
||||
logger._Log4NetLog = _loggerObjects[Name.ToLower()];
|
||||
return logger;
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("Must call AddGlobalLoggerConfiguration() with a Configuration Before calling this Function");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Static Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Log4Net RollingFileAppender with the specified configuration
|
||||
/// </summary>
|
||||
/// <param name="config">a valid configuration</param>
|
||||
/// <returns>a Log4Net RollingFileAppender Object</returns>
|
||||
private static RollingFileAppender RollingFileAppenderCreator(Logging_Configuration config)
|
||||
{
|
||||
#region Input Validation
|
||||
|
||||
if (config.maxFileSizeInMB <= 0)
|
||||
throw new ArgumentException("Logging_Configuration - Invalid maxFileSizeInMB");
|
||||
|
||||
if (config.numOfBackupLogFiles < 0)
|
||||
throw new ArgumentException("Logging_Configuration - Invalid numOfBackupLogFiles");
|
||||
|
||||
if (String.IsNullOrEmpty(config.LogFileNameNPath))
|
||||
throw new Exception("Logging_Configuration - Invalid LogFileNameNPath");
|
||||
|
||||
if (!Directory.Exists(Path.GetDirectoryName(config.LogFileNameNPath)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(config.LogFileNameNPath));
|
||||
|
||||
#endregion
|
||||
|
||||
// Create and Set Layout for FileAppender
|
||||
RollingFileAppender rfAppender = new RollingFileAppender();
|
||||
|
||||
// Set Layout
|
||||
if (!String.IsNullOrEmpty(config.Log4NetDetailPatternLayout))
|
||||
rfAppender.Layout = new PatternLayout(config.Log4NetDetailPatternLayout);
|
||||
else
|
||||
rfAppender.Layout = new PatternLayout("%date{dd MMM HH:mm:ss,fff} [%thread] %level - %message%newline");
|
||||
|
||||
// Locking Minimal allows us to run Log4Net from multiple processes
|
||||
if (config.UseExclusiveFileLock)
|
||||
rfAppender.LockingModel = new FileAppender.ExclusiveLock();
|
||||
else
|
||||
rfAppender.LockingModel = new FileAppender.MinimalLock();
|
||||
|
||||
// Configure FileName and always set Appent to true
|
||||
rfAppender.File = config.LogFileNameNPath;
|
||||
rfAppender.AppendToFile = true;
|
||||
|
||||
// According to the listings on the blog site
|
||||
// http://blog.aggregatedintelligence.com/2009/08/log4net-logging-levels-available.html
|
||||
// Error, will log Error, Fatal
|
||||
// Info, will log Info, Error, and Fatal
|
||||
// Debug, will log Info, Error, Fatal and Debug
|
||||
if (config.Detail == Logging_Detail.NONE)
|
||||
rfAppender.Threshold = Level.Off;
|
||||
else if (config.Detail == Logging_Detail.ERROR)
|
||||
rfAppender.Threshold = Level.Error;
|
||||
else if (config.Detail == Logging_Detail.INFO)
|
||||
rfAppender.Threshold = Level.Info;
|
||||
else if (config.Detail == Logging_Detail.DEBUG)
|
||||
rfAppender.Threshold = Level.Debug;
|
||||
|
||||
rfAppender.MaximumFileSize = String.Format("{0}MB", config.maxFileSizeInMB);
|
||||
rfAppender.MaxSizeRollBackups = config.numOfBackupLogFiles;
|
||||
|
||||
// Setting to RollingMode.Size will make MaxSizeRollBackups work
|
||||
rfAppender.RollingStyle = RollingFileAppender.RollingMode.Size;
|
||||
rfAppender.ActivateOptions();
|
||||
return rfAppender;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
190
File/Tail.cs
Normal file
190
File/Tail.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Yaulw.File
|
||||
{
|
||||
/// <remarks>
|
||||
/// A File SystemWatcher utility that functions like the infamous unix tail utility,
|
||||
/// with a callback when the file get's created or updated.
|
||||
/// </remarks>
|
||||
public class Tail
|
||||
{
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// Event Delegate for the Incoming Data Event
|
||||
/// </summary>
|
||||
/// <param name="sender">object reference to the sending Tail Object</param>
|
||||
/// <param name="newData">change data / or full data if bIsNewFile is true</param>
|
||||
/// <param name="bIsNewFile">true if a new file was created</param>
|
||||
public delegate void IncomingDataHandler(object sender, string newData, bool bIsNewFile);
|
||||
|
||||
/// <summary>
|
||||
/// Caller must subscribe to the Incoming Data Event
|
||||
/// </summary>
|
||||
public event IncomingDataHandler IncomingData = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
private string _FileNameNPath = "";
|
||||
private FileSystemWatcher _fileSystemWatcher = null;
|
||||
private long _previousSeekPosition = 0;
|
||||
private object _lockingObj = new Object();
|
||||
private const int MAX_BYTE_TO_READ_IN_ONE_TIME = 1024 * 16;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Tail Object to monitor the specified file
|
||||
/// </summary>
|
||||
/// <param name="FileNameNPath">File to Monitor with Tail</param>
|
||||
public Tail(string FileNameNPath)
|
||||
{
|
||||
_previousSeekPosition = 0;
|
||||
_FileNameNPath = FileNameNPath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Start Monitoring the File
|
||||
/// </summary>
|
||||
public void StartMonitoring()
|
||||
{
|
||||
// Get File Information * Setup System Watcher *
|
||||
FileInfo targetFile = new FileInfo(_FileNameNPath);
|
||||
_fileSystemWatcher = new FileSystemWatcher();
|
||||
_fileSystemWatcher.IncludeSubdirectories = false;
|
||||
_fileSystemWatcher.Path = targetFile.DirectoryName;
|
||||
_fileSystemWatcher.Filter = targetFile.Name;
|
||||
_fileSystemWatcher.Created += new FileSystemEventHandler(TargetFile_Created);
|
||||
_fileSystemWatcher.Changed += new FileSystemEventHandler(TargetFile_Changed);
|
||||
|
||||
// Perform an Initial read, if the file exists
|
||||
if (targetFile.Exists)
|
||||
TargetFile_Created(null, null);
|
||||
|
||||
// Start up File System Watcher
|
||||
_fileSystemWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop Monitoring the File
|
||||
/// </summary>
|
||||
/// <param name="bDispose">set to false, if you are running into trouble during a shutdown</param>
|
||||
public void StopMonitoring(bool bDispose = true)
|
||||
{
|
||||
_fileSystemWatcher.EnableRaisingEvents = false;
|
||||
if(bDispose)
|
||||
_fileSystemWatcher.Dispose();
|
||||
_fileSystemWatcher = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To read a file from Beginning to End. Call this function,
|
||||
/// if you want to reset the position counter and start reading again from the beginning.
|
||||
/// </summary>
|
||||
/// <returns>the Contents of the File</returns>
|
||||
public StringBuilder ReadFromBeginningToEndOfFile()
|
||||
{
|
||||
_previousSeekPosition = 0;
|
||||
return ReadFileContentsTillEndStartingFromPreviousSeekPosition();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Handled File System Watcher's Created Callback
|
||||
/// </summary>
|
||||
/// <param name="source">SystemWatcher object</param>
|
||||
/// <param name="e">SystemWatcher event args</param>
|
||||
private void TargetFile_Created(object source, FileSystemEventArgs e)
|
||||
{
|
||||
// Read the File Contents
|
||||
StringBuilder sb = ReadFromBeginningToEndOfFile();
|
||||
|
||||
//call delegate with the string
|
||||
if (IncomingData != null && sb.Length > 0)
|
||||
IncomingData(this, sb.ToString(), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handled File System Watcher's Changed Callback
|
||||
/// </summary>
|
||||
/// <param name="source">SystemWatcher object</param>
|
||||
/// <param name="e">SystemWatcher event args</param>
|
||||
private void TargetFile_Changed(object source, FileSystemEventArgs e)
|
||||
{
|
||||
// File size size changed to less! ~someone must have
|
||||
// changed content inside of it
|
||||
FileInfo targetFile = new FileInfo(_FileNameNPath);
|
||||
bool bIsNew = false;
|
||||
if (targetFile.Length < _previousSeekPosition)
|
||||
{
|
||||
_previousSeekPosition = 0;
|
||||
bIsNew = true;
|
||||
}
|
||||
|
||||
// Read the File Contents
|
||||
StringBuilder sb = ReadFileContentsTillEndStartingFromPreviousSeekPosition();
|
||||
|
||||
//call delegate with the string
|
||||
if(IncomingData != null && sb.Length > 0)
|
||||
IncomingData(this, sb.ToString(), bIsNew);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper Function to read a file from _previousSeekPosition to End.
|
||||
/// </summary>
|
||||
/// <returns>contents of file starting from _previousSeekPosition</returns>
|
||||
private StringBuilder ReadFileContentsTillEndStartingFromPreviousSeekPosition()
|
||||
{
|
||||
lock (_lockingObj)
|
||||
{
|
||||
// Open the file
|
||||
FileStream fs = new FileStream(_FileNameNPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Read File Contents into a StringBuilder
|
||||
StringBuilder sb = new StringBuilder();
|
||||
bool bReadOrContinueReadingFile = true;
|
||||
while (bReadOrContinueReadingFile)
|
||||
{
|
||||
// Position the file
|
||||
_previousSeekPosition = (int)fs.Seek(_previousSeekPosition, SeekOrigin.Begin);
|
||||
|
||||
//read from current seek position to end of file
|
||||
byte[] bytesRead = new byte[MAX_BYTE_TO_READ_IN_ONE_TIME];
|
||||
int numBytes = fs.Read(bytesRead, 0, MAX_BYTE_TO_READ_IN_ONE_TIME);
|
||||
_previousSeekPosition += numBytes;
|
||||
|
||||
// Append Data to the String Builder
|
||||
for (int i = 0; i < numBytes; i++)
|
||||
sb.Append((char)bytesRead[i]);
|
||||
|
||||
// If we have read up to MAX_BYTE_TO_READ_IN_ONE_TIME, then there could be more data...
|
||||
bReadOrContinueReadingFile = (numBytes == MAX_BYTE_TO_READ_IN_ONE_TIME);
|
||||
}
|
||||
|
||||
// Close File
|
||||
fs.Dispose();
|
||||
fs = null;
|
||||
|
||||
// Return SB object
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user