random-file-runner/MainForm.cs

612 lines
17 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2021-10-30 02:21:45 +00:00
using System.ComponentModel;
2021-10-24 16:16:37 +00:00
using System.Diagnostics;
2021-10-24 15:49:48 +00:00
using System.IO;
using System.Linq;
2021-10-30 23:40:58 +00:00
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
2021-10-24 15:49:48 +00:00
using System.Windows.Forms;
using RyzStudio.IO;
using RyzStudio.Runtime.InteropServices;
using RyzStudio.Windows.Forms;
using Application = System.Windows.Forms.Application;
2021-10-24 15:49:48 +00:00
namespace RandomFileRunner
{
public partial class MainForm : Form
{
private readonly Random _randy;
private readonly FileSearcher _fileSearcher;
private CancellationTokenSource _cancellationToken = new CancellationTokenSource();
2021-10-30 02:21:45 +00:00
private bool _isBusy = false;
2021-10-30 02:21:45 +00:00
private List<string> _searchPaths = new List<string>();
private List<string> _foundFiles = new List<string>();
private Process _currentProcess = null;
2021-10-30 02:21:45 +00:00
public MainForm()
{
InitializeComponent();
2021-10-24 15:49:48 +00:00
textBox2.SetIcon("search");
textBox2.TextBox.ReadOnly = true;
2021-10-24 15:49:48 +00:00
_randy = new Random();
_fileSearcher = new FileSearcher();
_fileSearcher.OnDirectoryFound += fileSearcher_OnDirectoryFound;
_fileSearcher.OnFileFound += fileSearcher_OnFileFound;
_fileSearcher.OnSearchCompleted += fileSearcher_OnSearchCompleted;
}
2021-10-24 15:49:48 +00:00
protected override void OnLoad(EventArgs e)
2021-10-24 15:49:48 +00:00
{
base.OnLoad(e);
2021-10-24 15:49:48 +00:00
this.ClearSession();
2021-10-24 15:49:48 +00:00
}
2021-10-31 03:23:25 +00:00
protected async override void OnShown(EventArgs e)
{
base.OnShown(e);
var args = RyzStudio.Windows.Forms.Application.GetCommandLine();
2021-10-31 03:23:25 +00:00
string jsonfigFilename = args.Where(x => (x.Key.Equals("o") || x.Key.Equals("open"))).Select(x => x.Value).FirstOrDefault();
if (string.IsNullOrWhiteSpace(jsonfigFilename))
{
jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig");
}
2021-10-31 03:23:25 +00:00
if (!string.IsNullOrWhiteSpace(jsonfigFilename) && System.IO.File.Exists(jsonfigFilename))
2021-10-31 03:23:25 +00:00
{
await LoadSessionFile(jsonfigFilename);
}
}
2021-10-30 02:21:45 +00:00
protected override void OnClosing(CancelEventArgs e)
2021-10-24 15:49:48 +00:00
{
2021-10-30 02:21:45 +00:00
base.OnClosing(e);
2021-10-24 15:49:48 +00:00
if (this.IsBusy)
{
e.Cancel = true;
return;
}
if (this.CurrentSession.ClosePrevOnNext)
{
CloseCurrentProcess(_currentProcess);
}
2021-10-30 02:21:45 +00:00
if (this.CurrentSession.NextHotKey != null)
{
if (this.CurrentSession.NextHotKey.KeyCode != Keys.None)
{
//#if !DEBUG
User32.UnregisterHotKey((IntPtr)Handle, 1);
//#endif
2021-10-30 02:21:45 +00:00
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case User32.WM_HOTKEY:
if (m.WParam.ToInt32() == 1)
{
button5_MouseClick(null, null);
}
2021-10-30 02:21:45 +00:00
break;
//case WM_QUERYENDSESSION:
// requestExit = true;
// //this.Close();
// Application.Exit();
// break;
default:
break;
2021-10-30 02:21:45 +00:00
}
base.WndProc(ref m);
2021-10-24 15:49:48 +00:00
}
public bool IsBusy
{
get => _isBusy;
2021-10-24 15:49:48 +00:00
set
{
_isBusy = value;
UIControl.SetValue(pictureBox1, (_isBusy ? UIResource.loading_block : null));
UIControl.SetEnable(textBox1, !_isBusy);
button2.LabelText = (_isBusy ? "&Cancel" : "&Search");
UIControl.SetEnable(button5, !_isBusy);
UIControl.SetEnable(button4, !_isBusy);
2021-10-24 15:49:48 +00:00
}
}
public AppSession CurrentSession { get; set; } = new AppSession();
public List<string> SearchPaths
{
get => _searchPaths;
set
{
_searchPaths = value;
textBox2.Text = string.Join(", ", _searchPaths.ToArray());
}
}
#region Main Menu
2021-10-30 22:44:44 +00:00
/// <summary>
/// New
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void newToolStripMenuItem_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
if (this.IsBusy)
{
return;
}
2021-10-30 22:44:44 +00:00
if (this.CurrentSession.ClosePrevOnNext)
{
CloseCurrentProcess(_currentProcess);
}
2021-10-30 22:44:44 +00:00
2021-10-30 23:40:58 +00:00
ClearSession();
2021-10-30 22:44:44 +00:00
});
}
/// <summary>
/// Open
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-10-30 23:40:58 +00:00
private async void openToolStripMenuItem_Click(object sender, EventArgs e)
2021-10-30 22:44:44 +00:00
{
if (this.IsBusy)
{
return;
}
2021-10-30 22:44:44 +00:00
2021-10-30 23:40:58 +00:00
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
await LoadSessionFile(openFileDialog2.FileName);
}
2021-10-30 22:44:44 +00:00
}
/// <summary>
/// Save as
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-10-30 23:40:58 +00:00
private async void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
2021-10-30 22:44:44 +00:00
{
if (this.IsBusy)
{
return;
}
saveFileDialog1.Title = "Save session";
saveFileDialog1.Filter = "Session files (*.jsonfig)|*.jsonfig";
saveFileDialog1.DefaultExt = "jsonfig";
2021-10-30 22:44:44 +00:00
2021-10-30 23:40:58 +00:00
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
await SaveSessionFile(saveFileDialog1.FileName);
}
2021-10-30 22:44:44 +00:00
}
/// <summary>
/// Close
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void exitToolStripMenuItem2_Click(object sender, EventArgs e)
{
this.Close();
}
2021-10-30 02:21:45 +00:00
/// <summary>
/// Options
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
2021-10-30 02:21:45 +00:00
var optionsForm = new OptionsForm(this.CurrentSession);
2021-10-30 02:21:45 +00:00
if (optionsForm.ShowDialog() == DialogResult.OK)
{
this.CurrentSession = optionsForm.Session;
InvalidateHotKey();
}
}
2021-10-30 22:44:44 +00:00
/// <summary>
/// Help
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e)
{
RyzStudio.Diagnostics.Process.Execute(AppResource.AppHelpURL);
2021-10-30 22:44:44 +00:00
}
/// <summary>
/// About
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
2021-10-30 02:21:45 +00:00
#region Search Engine
private async Task fileSearcher_OnFileFound(FileSearcher sender, string searchPath, string fileName)
2021-10-24 15:49:48 +00:00
{
await Task.Run(() =>
{
_foundFiles.Add(fileName);
UIControl.SetText(label3, Path.GetFileName(fileName));
progressBar2.Maximum = (sender.FileCount + sender.NoAccessFileCount);
progressBar2.Value = sender.FileCount;
});
}
2021-10-24 15:49:48 +00:00
private async Task fileSearcher_OnDirectoryFound(FileSearcher sender, string searchPath, string directoryName)
{
await Task.Run(() =>
{
UIControl.SetText(label4, Path.GetFileName(directoryName));
progressBar1.Maximum = sender.DirectoryCount;
progressBar1.Value = sender.BufferLevel;
});
}
private async Task fileSearcher_OnSearchCompleted(FileSearcher sender, TimeSpan elapsedTime)
{
await Task.Run(() =>
{
UIControl.SetText(label4, $"Done in {Math.Floor(elapsedTime.TotalMinutes)}m {elapsedTime.Seconds}s");
UIControl.SetText(label3, ((_foundFiles.Count <= 0) ? "0" : _foundFiles.Count.ToString("#,#", System.Globalization.CultureInfo.CurrentCulture)) + " File" + ((_foundFiles.Count == 1) ? "" : "s") + " Found");
progressBar1.Value = sender.BufferLevel;
progressBar2.Value = sender.FileCount;
});
}
#endregion
private void textBox2_OnButtonClick(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
var form = new MemoBoxForm();
form.Lines = SearchPaths;
2021-10-24 15:49:48 +00:00
if (form.ShowDialog() == DialogResult.OK)
2021-10-24 15:49:48 +00:00
{
SearchPaths = form.Lines;
2021-10-24 15:49:48 +00:00
}
}
/// <summary>
/// Search
2021-10-24 15:49:48 +00:00
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button2_MouseClick(object sender, MouseEventArgs e)
2021-10-24 15:49:48 +00:00
{
if (this.IsBusy)
2021-10-24 15:49:48 +00:00
{
button2.LabelText = "&Cancelling...";
_cancellationToken.Cancel();
return;
2021-10-24 15:49:48 +00:00
}
this.IsBusy = true;
2021-10-24 15:49:48 +00:00
progressBar1.ShowProgressText = true;
progressBar2.ShowProgressText = true;
2021-10-24 15:49:48 +00:00
_foundFiles = new List<string>();
_cancellationToken = new CancellationTokenSource();
_currentProcess = null;
_fileSearcher.FileSearchPattern = textBox1.Text;
_fileSearcher.SearchPath = new List<string>();
await Task.Run(() =>
2021-10-24 16:16:37 +00:00
{
foreach (var item in SearchPaths)
2021-10-24 16:16:37 +00:00
{
if (_cancellationToken.IsCancellationRequested)
{
break;
}
if (System.IO.File.Exists(item))
{
_foundFiles.Add(item);
continue;
}
if (System.IO.Directory.Exists(item))
{
_fileSearcher.SearchPath.Add(item);
continue;
}
2021-10-24 16:16:37 +00:00
}
2021-10-24 15:49:48 +00:00
UIControl.SetText(label3, ((_foundFiles.Count <= 0) ? "0" : _foundFiles.Count.ToString("#,#", System.Globalization.CultureInfo.CurrentCulture)) + " File" + ((_foundFiles.Count == 1) ? "" : "s") + " Found");
});
2021-10-24 15:49:48 +00:00
if (_fileSearcher.SearchPath.Count > 0)
2021-10-24 16:16:37 +00:00
{
await _fileSearcher.Search(_cancellationToken.Token);
2021-10-24 16:16:37 +00:00
}
this.IsBusy = false;
_cancellationToken = new CancellationTokenSource();
2021-10-24 16:16:37 +00:00
}
/// <summary>
/// Run next
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-10-30 02:21:45 +00:00
private async void button5_MouseClick(object sender, MouseEventArgs e)
2021-10-24 16:16:37 +00:00
{
if (this.IsBusy)
2021-10-30 02:21:45 +00:00
{
return;
}
2021-10-24 16:16:37 +00:00
if (_foundFiles.Count <= 0)
{
return;
}
await Task.Run(() =>
{
2021-10-30 02:21:45 +00:00
//this.IsBusy = true;
if (this.CurrentSession == null)
{
this.CurrentSession = new AppSession();
}
2021-10-30 02:21:45 +00:00
if (this.CurrentSession.ClosePrevOnNext)
{
CloseCurrentProcess(_currentProcess);
}
2021-10-30 02:21:45 +00:00
string filename = null;
// retry 8 times
for (int i = 0; i < this.CurrentSession.RetryOnError; i++)
{
filename = _foundFiles[_randy.Next(0, (_foundFiles.Count - 1))];
if (System.IO.File.Exists(filename))
2021-10-30 02:21:45 +00:00
{
continue;
}
filename = null;
}
if (!string.IsNullOrWhiteSpace(filename))
{
_currentProcess = RyzStudio.Diagnostics.Process.Execute(filename);
2021-10-30 02:21:45 +00:00
}
//this.IsBusy = false;
});
2021-10-24 16:16:37 +00:00
}
/// <summary>
/// Save File List
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button4_MouseClick(object sender, MouseEventArgs e)
2021-10-24 16:16:37 +00:00
{
if (this.IsBusy)
{
return;
}
2021-10-24 15:49:48 +00:00
if (_foundFiles.Count <= 0)
{
return;
}
saveFileDialog1.Title = "Save File List";
saveFileDialog1.Filter = "Text files (*.txt)|*.txt";
saveFileDialog1.DefaultExt = "txt";
2021-10-30 02:21:45 +00:00
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
await System.IO.File.WriteAllTextAsync(saveFileDialog1.FileName, string.Join(Environment.NewLine, _foundFiles.ToArray()));
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Save File List");
}
}
}
2021-10-30 02:21:45 +00:00
/// <summary>
/// Close
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_MouseClick(object sender, MouseEventArgs e)
{
this.Close();
2021-10-30 02:21:45 +00:00
}
2021-10-30 02:21:45 +00:00
private void CloseCurrentProcess(Process p)
{
if (p == null)
{
return;
}
2021-10-30 02:21:45 +00:00
try
{
p.CloseMainWindow();
}
catch (Exception)
{
// do nothing
}
}
private void InvalidateHotKey()
{
//#if !DEBUG
UIControl.Invoke(this, (x) =>
2021-10-30 02:21:45 +00:00
{
User32.UnregisterHotKey((IntPtr)Handle, 1);
});
//#endif
2021-10-30 02:21:45 +00:00
if (this.CurrentSession.NextHotKey != null)
{
if (this.CurrentSession.NextHotKey.KeyCode != Keys.None)
{
//#if !DEBUG
UIControl.Invoke(this, (x) =>
2021-10-30 02:21:45 +00:00
{
User32.RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.NextHotKey.ModifierCode, this.CurrentSession.NextHotKey.Key);
});
//#endif
2021-10-30 02:21:45 +00:00
}
}
}
2021-10-30 23:40:58 +00:00
private void ClearSession()
{
_foundFiles = new List<string>();
_currentProcess = null;
2021-10-30 23:40:58 +00:00
textBox1.Text = "*.*";
progressBar1.Clear(0, 0, 0);
progressBar2.Clear(0, 0, 0);
UIControl.SetText(label4, "");
UIControl.SetText(label3, "");
2021-10-30 23:40:58 +00:00
}
protected async Task LoadSessionFile(string filename)
{
await Task.Run(() =>
{
this.CurrentSession = RyzStudio.Text.Json.JsonSerialiser.DeserialiseFile<AppSession>(filename) ?? new AppSession();
2021-10-30 23:40:58 +00:00
ClearSession();
textBox1.Text = (string.IsNullOrWhiteSpace(this.CurrentSession.SearchFilePattern) ? "*" : this.CurrentSession.SearchFilePattern?.Trim());
SearchPaths = this.CurrentSession?.SearchItems ?? new List<string>();
2021-10-30 23:40:58 +00:00
// hotkey
InvalidateHotKey();
});
}
protected async Task SaveSessionFile(string filename)
2021-10-31 03:23:25 +00:00
{
if (string.IsNullOrWhiteSpace(filename))
2021-10-31 03:23:25 +00:00
{
return;
2021-10-31 03:23:25 +00:00
}
if (this.CurrentSession == null)
2021-10-31 03:23:25 +00:00
{
this.CurrentSession = new AppSession();
2021-10-31 03:23:25 +00:00
}
2021-10-30 23:40:58 +00:00
await Task.Run(() =>
{
this.CurrentSession.SearchFilePattern = textBox1.Text;
this.CurrentSession.SearchItems = new List<string>();
foreach (var item in SearchPaths)
2021-10-30 23:40:58 +00:00
{
if (string.IsNullOrWhiteSpace(item))
2021-10-30 23:40:58 +00:00
{
continue;
2021-10-30 23:40:58 +00:00
}
this.CurrentSession.SearchItems.Add(item.Trim());
2021-10-30 23:40:58 +00:00
}
string sourceCode = null;
try
{
sourceCode = JsonSerializer.Serialize(this.CurrentSession);
}
catch (Exception)
{
MessageBox.Show("Unable to write session", "Save session");
return;
}
try
{
System.IO.File.WriteAllText(filename, sourceCode);
2021-10-30 23:40:58 +00:00
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Save session");
return;
}
});
}
2021-10-30 02:21:45 +00:00
2021-10-24 15:49:48 +00:00
}
}