793 lines
28 KiB
C#
793 lines
28 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
using IronPython.Hosting;
|
|
using IronPython.Runtime;
|
|
using Microsoft.Scripting;
|
|
using Microsoft.Scripting.Hosting;
|
|
|
|
using Microsoft.Win32;
|
|
|
|
namespace FileWatcher
|
|
{
|
|
public partial class FileGroupTab : UserControl
|
|
{
|
|
/// <summary>
|
|
/// Used for catching output from the Python runtime
|
|
/// </summary>
|
|
private EventRaisingStreamWriter m_LogStream = null;
|
|
private EventRaisingStreamWriter m_ErrorStream = null;
|
|
private MemoryStream m_MemoryStream = new MemoryStream();
|
|
private delegate void SetTextCallback(object sender, MyEvtArgs<string> e);
|
|
private delegate void SetStringCallback(string e);
|
|
|
|
// TODO: Push the updated files to a multiprocessing queue that I create inside of the scope of the script
|
|
private ScriptEngine pyEngine = null;
|
|
private ScriptRuntime pyRuntime = null;
|
|
private ScriptScope pyScope = null;
|
|
|
|
BindingList<string> m_FolderList = new BindingList<string>();
|
|
|
|
List<FileSystemWatcher> m_FileWatchers = new List<FileSystemWatcher>();
|
|
List<string> m_UpdatedFiles = new List<string>();
|
|
|
|
TimerPlus m_Timer = new TimerPlus();
|
|
System.Timers.Timer m_TickCounter = new System.Timers.Timer();
|
|
|
|
|
|
private FileGroupSettings m_Settings = null;
|
|
|
|
private static Regex regexSpaces = new Regex(@"^([a-zA-Z0-9_]*\*?[a-zA-Z0-9_]*(\.(\*|[a-zA-Z0-9]+))\s?)+$");
|
|
|
|
private static Regex regexMS = new Regex(@"^\d+ms$");
|
|
private static Regex regexS = new Regex(@"^\d+s$");
|
|
private static Regex regexM = new Regex(@"^\d+m$");
|
|
private static Regex regexH = new Regex(@"^\d+h$");
|
|
private static Regex regexTime = new Regex(@"^(\d+(ms|s|m|h)\s?)+$");
|
|
|
|
private static Regex regexAbsolutePath = new Regex(@"^[a-zA-Z]\:\\$");
|
|
private static Regex regexNetworkPath = new Regex(@"^\\\\$");
|
|
|
|
public FileGroupTab()
|
|
{
|
|
InitializeComponent();
|
|
|
|
m_Timer.Enabled = false;
|
|
m_Timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Tick);
|
|
|
|
m_TickCounter.Enabled = false;
|
|
m_TickCounter.Elapsed += new System.Timers.ElapsedEventHandler(timer_TickCountdown);
|
|
|
|
if (pyEngine == null)
|
|
{
|
|
Dictionary<string, object> options = new Dictionary<string, object>();
|
|
options["Debug"] = true;
|
|
pyEngine = Python.CreateEngine(options);
|
|
pyScope = pyEngine.CreateScope();
|
|
|
|
m_LogStream = new EventRaisingStreamWriter(m_MemoryStream);
|
|
m_LogStream.StringWritten += new EventHandler<MyEvtArgs<string>>(script_StringWritten);
|
|
pyEngine.Runtime.IO.SetOutput(m_MemoryStream, m_LogStream);
|
|
|
|
m_ErrorStream = new EventRaisingStreamWriter(m_MemoryStream);
|
|
m_ErrorStream.StringWritten += new EventHandler<MyEvtArgs<string>>(script_ErrorStringWritten);
|
|
pyEngine.Runtime.IO.SetErrorOutput(m_MemoryStream, m_ErrorStream);
|
|
}
|
|
foldersListBox.DataSource = m_FolderList;
|
|
m_FolderList.ListChanged += new ListChangedEventHandler(foldersListBox_ListChanged);
|
|
|
|
toolStripTextBox1_TextChanged(this, null);
|
|
}
|
|
|
|
public List<string> GetPaths()
|
|
{
|
|
List<string> paths = new List<string>();
|
|
|
|
foreach (string str in foldersListBox.Items)
|
|
{
|
|
paths.Add(str);
|
|
}
|
|
|
|
return paths;
|
|
}
|
|
|
|
public bool AreExtenionsValid()
|
|
{
|
|
return regexSpaces.Matches(FileExtensionsToolBox.Text).Count != 0;
|
|
}
|
|
|
|
public string ExtensionString
|
|
{
|
|
get { return FileExtensionsToolBox.Text; }
|
|
set { FileExtensionsToolBox.Text = value; }
|
|
}
|
|
|
|
public string[] Extensions
|
|
{
|
|
get { return FileExtensionsToolBox.Text.Split(' '); }
|
|
set { FileExtensionsToolBox.Text = string.Join(" ", value); }
|
|
}
|
|
|
|
public string ScriptPath
|
|
{
|
|
get { return scriptPathTextBox.Text; }
|
|
set { scriptPathTextBox.Text = value; }
|
|
}
|
|
|
|
public string GetScriptAbsolutePath()
|
|
{
|
|
bool match1 = regexAbsolutePath.Matches(ScriptPath).Count > 0;
|
|
bool match2 = regexNetworkPath.Matches(ScriptPath).Count > 0;
|
|
|
|
if (match1 == false && match2 == false)
|
|
{
|
|
// Path is not an absolute path, make it one
|
|
return Path.GetFullPath(Path.Combine(new FileInfo(Application.ExecutablePath).DirectoryName, ScriptPath));
|
|
} return ScriptPath;
|
|
}
|
|
|
|
public string Delay
|
|
{
|
|
get { return toolStripTextBox1.Text; }
|
|
set { toolStripTextBox1.Text = value; }
|
|
}
|
|
|
|
public FileGroupSettings Settings
|
|
{
|
|
get
|
|
{
|
|
if (null == m_Settings || m_Settings.IsDisposed)
|
|
{
|
|
m_Settings = new FileGroupSettings();
|
|
//m_Settings.Text = "";
|
|
} return m_Settings;
|
|
}
|
|
}
|
|
|
|
public List<string> Directories
|
|
{
|
|
get { return m_FolderList.Cast<String>().ToList(); }
|
|
set
|
|
{
|
|
m_FolderList.Clear();
|
|
|
|
foldersListBox.DataSource = null;
|
|
foldersListBox.SelectionMode = SelectionMode.None;
|
|
|
|
foreach (string i in value)
|
|
m_FolderList.Add(i);
|
|
|
|
foldersListBox.DataSource = m_FolderList;
|
|
foldersListBox.SelectionMode = SelectionMode.MultiExtended;
|
|
}
|
|
}
|
|
|
|
static public string GetPythonDir()
|
|
{
|
|
// if you want better debugging information, return the iron python path
|
|
String ironPythonDir = "C:\\Program Files (x86)\\IronPython 2.7";
|
|
if (Directory.Exists(ironPythonDir))
|
|
{
|
|
return ironPythonDir;
|
|
}
|
|
|
|
// Use the Libs folder in the local path (and let there be an error if it's not there)
|
|
return new FileInfo(Application.ExecutablePath).DirectoryName;
|
|
|
|
// Iron Python doesn't seem properly compatible with Python, don't use the Python libs.
|
|
/*string[] paths = Environment.GetEnvironmentVariable("PATH").Split(';');
|
|
foreach (string s in paths)
|
|
{
|
|
if (s.ToLower().IndexOf("python") != -1 && File.Exists(Path.Combine(s, "python.exe")))
|
|
{
|
|
return s;
|
|
}
|
|
}
|
|
|
|
return null;*/
|
|
}
|
|
|
|
private bool CompileSourceAndExecute()
|
|
{
|
|
string code = "";
|
|
|
|
string pythonDir = GetPythonDir();
|
|
if (pythonDir == null)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "Could not find your Python path, try adding it to your system PATH and try again.";
|
|
|
|
Logger.LogError("Could not find your Python path, try adding it to your system PATH and try again.");
|
|
return false;
|
|
}
|
|
string pythonLibs = Path.Combine(pythonDir, "Lib");
|
|
|
|
if (Directory.Exists(pythonLibs))
|
|
{
|
|
code += "import sys" + Environment.NewLine + "if '" + pythonLibs + "' not in sys.path: sys.path.append('" + pythonLibs + "')" + Environment.NewLine;
|
|
}
|
|
else
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "Could not find your Python Lib path in '" + pythonLibs + "'. Good luck.";
|
|
|
|
Logger.LogError("Could not find your Python Lib path in '" + pythonLibs + "'. Good luck.");
|
|
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
// TODO: backup list of unprocessed files and move it to the new scope
|
|
|
|
// WARNING: for some reason the dependencies that are loaded from the
|
|
// previous script do not get reloaded, even though they should be in
|
|
// the scope that we're disposing and not in the new scope. Will have
|
|
// to consider destroying the Python Engine and recreating that as well.
|
|
|
|
pyScope = pyEngine.CreateScope();
|
|
pyEngine.Execute(code.Replace("\\", "\\\\"), pyScope);
|
|
pyEngine.ExecuteFile(GetScriptAbsolutePath(),pyScope);
|
|
|
|
//ScriptSource source = pyEngine.CreateScriptSourceFromString(code);
|
|
// object result = source.Execute(pyScope);
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
if (e is Microsoft.Scripting.SyntaxErrorException)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "There is a syntax error: '" + e.Message + "' on line " + ((Microsoft.Scripting.SyntaxErrorException)e).Line;
|
|
|
|
Logger.LogError("There is a syntax error in '" + Path.GetFileName(ScriptPath) + "': " + e.Message + "' on line " + ((Microsoft.Scripting.SyntaxErrorException)e).Line);
|
|
return false;
|
|
}
|
|
else if (e is System.Reflection.TargetInvocationException)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "There is an invokation error: '" + e.Message + "'" + Environment.NewLine + e.StackTrace;
|
|
|
|
Logger.LogError("There is an invokation error in '" + Path.GetFileName(ScriptPath) + "': " + e.Message + "'" + Environment.NewLine + e.StackTrace);
|
|
return false;
|
|
}
|
|
else if (e is System.ArgumentException)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "There is an argument error: '" + e.Message + "'" + Environment.NewLine + e.StackTrace;
|
|
|
|
Logger.LogError("There is an argument error in '" + Path.GetFileName(ScriptPath) + "': " + e.Message + "'" + Environment.NewLine + e.StackTrace);
|
|
return false;
|
|
}
|
|
else if (e is IronPython.Runtime.Exceptions.ImportException)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "There is an import error: '" + e.Message + "'" + Environment.NewLine + e.StackTrace;
|
|
|
|
Logger.LogError("There is an import error in '" + Path.GetFileName(ScriptPath) + "': " + e.Message + "'" + Environment.NewLine + e.StackTrace);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "There is an unknown error: '" + e.Message + "'" + Environment.NewLine + e.StackTrace;
|
|
|
|
Logger.LogError("There is an unknown error in '" + Path.GetFileName(ScriptPath) + "': " + e.Message + "'" + Environment.NewLine + e.StackTrace);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
Func<List<string>, bool> updated = pyScope.GetVariable<Func<List<string>, bool>>("process_updated_files");
|
|
}
|
|
catch (System.MissingMemberException)
|
|
{
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "The function 'process_updated_files' is missing, it accepts a list of files.";
|
|
|
|
Logger.LogError("'" + Path.GetFileName(ScriptPath) + "' is missing the function 'process_updated_files', which accepts a list of files. ");
|
|
|
|
return false;
|
|
}
|
|
|
|
Logger.Log("Loaded and compiled '" + Path.GetFileName(ScriptPath) + "'");
|
|
|
|
SetInterval();
|
|
|
|
return true;
|
|
}
|
|
|
|
private void toolStripButton5_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void toolStripButton7_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
public void AddWatchPath(string path )
|
|
{
|
|
foldersListBox.DataSource = null;
|
|
foldersListBox.SelectionMode = SelectionMode.None;
|
|
|
|
m_FolderList.Add(path);
|
|
|
|
foldersListBox.DataSource = m_FolderList;
|
|
foldersListBox.SelectionMode = SelectionMode.MultiExtended;
|
|
}
|
|
|
|
public void RemoveWatchPath(string path)
|
|
{
|
|
foldersListBox.DataSource = null;
|
|
foldersListBox.SelectionMode = SelectionMode.None;
|
|
|
|
m_FolderList.Remove(path);
|
|
|
|
foldersListBox.DataSource = m_FolderList;
|
|
foldersListBox.SelectionMode = SelectionMode.MultiExtended;
|
|
}
|
|
|
|
private void toolStripButton5_Click_1(object sender, EventArgs e)
|
|
{
|
|
//Form1.s_FolderDialogue.InitialDirectory = Environment.CurrentDirectory;
|
|
if (Form1.s_FolderDialogue.ShowDialog())
|
|
{
|
|
AddWatchPath(Form1.s_FolderDialogue.FileName);
|
|
Form1.Instance.AutoSave();
|
|
}
|
|
}
|
|
|
|
private void toolStripButton6_Click(object sender, EventArgs e)
|
|
{
|
|
while (foldersListBox.SelectedItems.Count > 0)
|
|
{
|
|
RemoveWatchPath((string)foldersListBox.SelectedItems[0]);
|
|
}
|
|
Form1.Instance.AutoSave();
|
|
}
|
|
|
|
private void toolStripButton7_Click_1(object sender, EventArgs e)
|
|
{
|
|
Process myProcess = new Process();
|
|
|
|
myProcess.StartInfo.FileName = Preferences.Instance.GetDefaultEditor(); //not the full application path
|
|
if (String.IsNullOrEmpty(myProcess.StartInfo.FileName))
|
|
{
|
|
MessageBox.Show("Your selected default and backup text editors cannot be found, please open up preferences ( Ctrl + P ) and select an editor that can be found on the local computer.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
// TODO: check if directory is relative or not
|
|
myProcess.StartInfo.Arguments = GetScriptAbsolutePath();
|
|
myProcess.Start();
|
|
}
|
|
|
|
|
|
private void FileExtensionsToolBox_TextChanged(object sender, EventArgs e)
|
|
{
|
|
bool isMatch = regexSpaces.IsMatch(FileExtensionsToolBox.Text);
|
|
extensionWarning.Visible = isMatch == false;
|
|
UpdateFileWatchers();
|
|
}
|
|
|
|
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void toolStripButton1_Click(object sender, EventArgs e)
|
|
{
|
|
// TODO: check if directory is relative or not
|
|
openFileDialog1.InitialDirectory = Path.GetDirectoryName(GetScriptAbsolutePath());
|
|
openFileDialog1.FileName = Path.GetFileName(ScriptPath);
|
|
if (openFileDialog1.ShowDialog() == DialogResult.OK)
|
|
{
|
|
scriptPathTextBox.Text = Utils.MakeRelativePath(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), openFileDialog1.FileName);
|
|
LoadScript();
|
|
}
|
|
}
|
|
|
|
private void toolStripButton2_Click(object sender, EventArgs e)
|
|
{
|
|
Settings.ShowDialog(this);
|
|
}
|
|
|
|
public void SetDelayCountDownText(string str)
|
|
{
|
|
if (toolStrip.InvokeRequired)
|
|
{
|
|
SetStringCallback d = new SetStringCallback(SetDelayCountDownText);
|
|
this.Invoke(d, new object[] { str });
|
|
}
|
|
else
|
|
{
|
|
delayCountDownLabel.Text = str;
|
|
}
|
|
}
|
|
|
|
private void script_StringWritten(object sender, MyEvtArgs<string> e)
|
|
{
|
|
if (richTextBox1.InvokeRequired)
|
|
{
|
|
SetTextCallback d = new SetTextCallback(script_StringWritten);
|
|
this.Invoke(d, new object[] { sender, e });
|
|
}
|
|
else
|
|
{
|
|
richTextBox1.AppendText(e.Value, Color.Black);
|
|
richTextBox1.SelectionStart = richTextBox1.Text.Length;
|
|
richTextBox1.ScrollToCaret();
|
|
}
|
|
}
|
|
|
|
private void script_ErrorStringWritten(object sender, MyEvtArgs<string> e)
|
|
{
|
|
if (richTextBox1.InvokeRequired)
|
|
{
|
|
SetTextCallback d = new SetTextCallback(script_ErrorStringWritten);
|
|
this.Invoke(d, new object[] { sender, e });
|
|
}
|
|
else
|
|
{
|
|
richTextBox1.AppendText(e.Value, Color.Maroon);
|
|
richTextBox1.SelectionStart = richTextBox1.Text.Length;
|
|
richTextBox1.ScrollToCaret();
|
|
}
|
|
}
|
|
|
|
private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// DO NOT check to see if equal to directory
|
|
if ((File.GetAttributes(e.FullPath) & FileAttributes.Directory) == FileAttributes.Directory)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (m_Timer.Enabled == false || Settings.restartDelayCB.Checked)
|
|
{
|
|
m_Timer.Stop();
|
|
m_TickCounter.Stop();
|
|
|
|
m_Timer.Enabled = false;
|
|
m_TickCounter.Enabled = false;
|
|
SetInterval();
|
|
m_Timer.Enabled = true;
|
|
m_TickCounter.Enabled = true;
|
|
|
|
m_Timer.Start();
|
|
m_TickCounter.Start();
|
|
}
|
|
|
|
if (Settings.stopScriptCB.Checked)
|
|
{
|
|
scriptWorker.CancelAsync();
|
|
}
|
|
|
|
// TODO: check to see if the path is relative or absolute
|
|
string fullPath = Path.Combine(new FileInfo(Application.ExecutablePath).DirectoryName, e.FullPath);
|
|
|
|
if (false == m_UpdatedFiles.Contains(fullPath))
|
|
{
|
|
m_UpdatedFiles.Add(fullPath);
|
|
}
|
|
}
|
|
|
|
private void scriptPathTextBox_TextChanged(object sender, EventArgs e)
|
|
{
|
|
LoadScript();
|
|
}
|
|
|
|
void UpdateFileWatchers()
|
|
{
|
|
if (false == AreExtenionsValid())
|
|
{
|
|
return;
|
|
}
|
|
foreach (FileSystemWatcher fsw in m_FileWatchers)
|
|
{
|
|
fsw.Dispose();
|
|
}
|
|
m_FileWatchers.Clear();
|
|
foreach (string s in Directories)
|
|
{
|
|
string path = Path.Combine(new FileInfo(Application.ExecutablePath).DirectoryName, s);
|
|
foreach (string ext in Extensions)
|
|
{
|
|
if (false == Directory.Exists(path)) continue;
|
|
|
|
FileSystemWatcher fileWatcher = new FileSystemWatcher();
|
|
|
|
// TODO: check to see if the path is relative
|
|
fileWatcher.Path = path;
|
|
|
|
fileWatcher.Filter = ext;
|
|
|
|
fileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
|
|
|
|
fileWatcher.Created += fileSystemWatcher1_Changed;
|
|
fileWatcher.Changed += fileSystemWatcher1_Changed;
|
|
fileWatcher.Renamed += fileSystemWatcher1_Changed;
|
|
fileWatcher.Deleted += fileSystemWatcher1_Changed;
|
|
|
|
// TODO: handle deleted files differently
|
|
|
|
fileWatcher.EnableRaisingEvents = true;
|
|
fileWatcher.IncludeSubdirectories = true;
|
|
|
|
m_FileWatchers.Add(fileWatcher);
|
|
}
|
|
}
|
|
}
|
|
|
|
void foldersListBox_ListChanged(object sender, ListChangedEventArgs e)
|
|
{
|
|
switch (e.ListChangedType)
|
|
{
|
|
case ListChangedType.ItemMoved:
|
|
case ListChangedType.ItemAdded:
|
|
case ListChangedType.ItemChanged:
|
|
case ListChangedType.ItemDeleted:
|
|
UpdateFileWatchers();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void timer_Tick(object sender, EventArgs e)
|
|
{
|
|
SetDelayCountDownText("--ms");
|
|
m_Timer.Stop();
|
|
m_Timer.Enabled = false;
|
|
m_TickCounter.Stop();
|
|
m_TickCounter.Enabled = false;
|
|
|
|
|
|
Form1.Instance.notifyIcon1.ShowBalloonTip(1000, "Script Running", "Running '" + ScriptPath + "'", ToolTipIcon.Info);
|
|
|
|
//scriptWorker.RunWorkerAsync(m_UpdatedFiles);
|
|
|
|
// run script in separate thread
|
|
Func<List<string>, bool> updated = pyScope.GetVariable<Func<List<string>, bool>>("process_updated_files");
|
|
|
|
try
|
|
{
|
|
var updateFiles = m_UpdatedFiles;
|
|
m_UpdatedFiles.Clear();
|
|
|
|
updated(updateFiles);
|
|
|
|
Logger.Log("Just finished running '" + ScriptPath + "'");
|
|
|
|
Form1.Instance.notifyIcon1.ShowBalloonTip(500, "Script Ran", "Finished running '" + ScriptPath + "'", ToolTipIcon.Info);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Logger.LogError("'" + ScriptPath + "' finished running with errors");
|
|
|
|
Form1.Instance.notifyIcon1.ShowBalloonTip(500, "Script Error", "'" + ScriptPath + "' finished running with errors", ToolTipIcon.Error);
|
|
|
|
if (ex is IronPython.Runtime.Exceptions.ImportException)
|
|
{
|
|
Logger.Log("Import exception in '" + ScriptPath + "':" + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine + ex.TargetSite);
|
|
}
|
|
else if (ex is System.MissingMemberException)
|
|
{
|
|
Logger.Log("Missing member exception in '" + ScriptPath + "':" + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine + ex.TargetSite);
|
|
}
|
|
else if (ex is System.IO.DirectoryNotFoundException)
|
|
{
|
|
Logger.Log("Directory not found exception in '" + ScriptPath + "':" + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine + ex.TargetSite);
|
|
}
|
|
else if (ex is System.ArgumentException)
|
|
{
|
|
Logger.Log("Directory not found exception in '" + ScriptPath + "':" + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine + ex.TargetSite);
|
|
}
|
|
else
|
|
{
|
|
Logger.Log("Error running '" + ScriptPath + "':" + ex.Message + Environment.NewLine + ex.StackTrace);
|
|
}
|
|
}
|
|
|
|
SetInterval();
|
|
}
|
|
|
|
private void timer_TickCountdown(object sender, EventArgs e)
|
|
{
|
|
string time_elapsed = "";
|
|
|
|
const double one_hour_to_ms = 3600000;
|
|
const double one_minute_to_ms = 60000;
|
|
const double one_second_to_ms = 1000.0;
|
|
|
|
double ms = m_Timer.TimeRemaining.TotalMilliseconds;
|
|
|
|
int hours = 0;
|
|
while (ms > one_hour_to_ms)
|
|
{
|
|
ms -= one_hour_to_ms;
|
|
++hours;
|
|
}
|
|
|
|
int minutes = 0;
|
|
while (ms > one_minute_to_ms)
|
|
{
|
|
ms -= one_minute_to_ms;
|
|
++minutes;
|
|
}
|
|
|
|
int seconds = 0;
|
|
while (ms > one_second_to_ms)
|
|
{
|
|
ms -= one_second_to_ms;
|
|
++seconds;
|
|
}
|
|
|
|
// round up
|
|
if (ms > 0)
|
|
{
|
|
++seconds;
|
|
}
|
|
|
|
if (hours > 0)
|
|
{
|
|
time_elapsed += hours + "h";
|
|
}
|
|
|
|
if (minutes > 0)
|
|
{
|
|
time_elapsed += (time_elapsed.Length > 0 ? " " : "") + minutes + "m";
|
|
}
|
|
|
|
if (seconds > 0)
|
|
{
|
|
time_elapsed += (time_elapsed.Length > 0 ? " " : "") + seconds + "s";
|
|
}
|
|
|
|
SetDelayCountDownText(time_elapsed);
|
|
}
|
|
|
|
bool SetInterval()
|
|
{
|
|
// disable timer before setting interval
|
|
if (m_Timer.Enabled) return false;
|
|
|
|
bool matches = regexTime.IsMatch(toolStripTextBox1.Text);
|
|
toolStripLabel2.Visible = matches == false;
|
|
toolStripLabel2.ToolTipText = "Invalid delay";
|
|
|
|
if (matches)
|
|
{
|
|
int interval = 0;
|
|
|
|
string[] values = toolStripTextBox1.Text.Split(' ');
|
|
foreach (string val in values)
|
|
{
|
|
if (val.Length == 0) continue;
|
|
|
|
if (regexMS.IsMatch(val))
|
|
{
|
|
interval += Convert.ToInt32(Regex.Match(val, @"\d+").Value);
|
|
}
|
|
else if (regexS.IsMatch(val))
|
|
{
|
|
interval += Convert.ToInt32(Regex.Match(val, @"\d+").Value) * 1000;
|
|
}
|
|
else if (regexM.IsMatch(val))
|
|
{
|
|
interval += Convert.ToInt32(Regex.Match(val, @"\d+").Value) * 1000 * 60;
|
|
}
|
|
else if (regexH.IsMatch(val))
|
|
{
|
|
interval += Convert.ToInt32(Regex.Match(val, @"\d+").Value) * 1000 * 60 * 24;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Unexpected format");
|
|
}
|
|
}
|
|
|
|
if (interval != 0)
|
|
{
|
|
m_Timer.Interval = interval;
|
|
m_TickCounter.Interval = 1000;
|
|
return true;
|
|
}
|
|
|
|
toolStripLabel2.Visible = true;
|
|
toolStripLabel2.ToolTipText = "Cannot have a value of 0";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void toolStripTextBox1_TextChanged(object sender, EventArgs e)
|
|
{
|
|
SetInterval();
|
|
}
|
|
|
|
public void ToggleScriptUpdate(bool enabled)
|
|
{
|
|
if (enabled)
|
|
{
|
|
scriptMonitorButton.Image = Properties.Resources.drop_box;
|
|
scriptMonitorButton.Enabled = true;
|
|
scriptMonitorButton.ToolTipText = "Script updated, press to reload it";
|
|
}
|
|
else
|
|
{
|
|
scriptMonitorButton.Image = Properties.Resources.block;
|
|
scriptMonitorButton.Enabled = false;
|
|
scriptMonitorButton.ToolTipText = "Script Monitor (when script is updated check here to reload script)";
|
|
}
|
|
}
|
|
|
|
public bool LoadScript()
|
|
{
|
|
ToggleScriptUpdate(false);
|
|
|
|
string absolutePath = GetScriptAbsolutePath();
|
|
|
|
if ( false == File.Exists(absolutePath))
|
|
{
|
|
scriptWatcher1.EnableRaisingEvents = false;
|
|
|
|
scriptWarning.Visible = true;
|
|
scriptWarning.ToolTipText = "The source file '" + absolutePath + "' could not be found.";
|
|
|
|
Logger.Log("The source file '" + absolutePath + "' could not be found.");
|
|
|
|
return false;
|
|
}
|
|
|
|
scriptWatcher1.Path = new FileInfo(absolutePath).DirectoryName;
|
|
scriptWatcher1.Filter = Path.GetFileName(absolutePath);
|
|
scriptWatcher1.Changed += scriptWatcher1_Changed;
|
|
scriptWatcher1.EnableRaisingEvents = true;
|
|
|
|
if (false == CompileSourceAndExecute())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
scriptWarning.Visible = false;
|
|
scriptWarning.ToolTipText = "";
|
|
return true;
|
|
}
|
|
|
|
private void scriptWatcher1_Changed(object sender, FileSystemEventArgs e)
|
|
{
|
|
// script updated
|
|
ToggleScriptUpdate(true);
|
|
}
|
|
|
|
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void scriptMonitorButton_Click(object sender, EventArgs e)
|
|
{
|
|
LoadScript();
|
|
}
|
|
}
|
|
}
|