using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using RyzStudio.IO; using RyzStudio.Runtime.InteropServices; using RyzStudio.Windows.Forms; using Application = System.Windows.Forms.Application; namespace RandomFileRunner { public partial class MainForm : Form { private readonly Random _randy; private readonly FileSearcher _fileSearcher; private CancellationTokenSource _cancellationToken = new CancellationTokenSource(); private bool _isBusy = false; private List _searchPaths = new List(); private List _foundFiles = new List(); private Process _currentProcess = null; public MainForm() { InitializeComponent(); textBox2.SetIcon("search"); textBox2.TextBox.ReadOnly = true; _randy = new Random(); _fileSearcher = new FileSearcher(); _fileSearcher.OnDirectoryFound += fileSearcher_OnDirectoryFound; _fileSearcher.OnFileFound += fileSearcher_OnFileFound; _fileSearcher.OnSearchCompleted += fileSearcher_OnSearchCompleted; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.ClearSession(); } protected async override void OnShown(EventArgs e) { base.OnShown(e); var args = RyzStudio.Windows.Forms.Application.GetCommandLine(); 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"); } if (!string.IsNullOrWhiteSpace(jsonfigFilename) && System.IO.File.Exists(jsonfigFilename)) { await LoadSessionFile(jsonfigFilename); } } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); if (this.IsBusy) { e.Cancel = true; return; } if (this.CurrentSession.ClosePrevOnNext) { CloseCurrentProcess(_currentProcess); } if (this.CurrentSession.NextHotKey != null) { if (this.CurrentSession.NextHotKey.KeyCode != Keys.None) { //#if !DEBUG User32.UnregisterHotKey((IntPtr)Handle, 1); //#endif } } } protected override void WndProc(ref Message m) { switch (m.Msg) { case User32.WM_HOTKEY: if (m.WParam.ToInt32() == 1) { button5_MouseClick(null, null); } break; //case WM_QUERYENDSESSION: // requestExit = true; // //this.Close(); // Application.Exit(); // break; default: break; } base.WndProc(ref m); } public bool IsBusy { get => _isBusy; 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); } } public AppSession CurrentSession { get; set; } = new AppSession(); public List SearchPaths { get => _searchPaths; set { _searchPaths = value; textBox2.Text = string.Join(", ", _searchPaths.ToArray()); } } #region Main Menu /// /// New /// /// /// private async void newToolStripMenuItem_Click(object sender, EventArgs e) { await Task.Run(() => { if (this.IsBusy) { return; } if (this.CurrentSession.ClosePrevOnNext) { CloseCurrentProcess(_currentProcess); } ClearSession(); }); } /// /// Open /// /// /// private async void openToolStripMenuItem_Click(object sender, EventArgs e) { if (this.IsBusy) { return; } if (openFileDialog2.ShowDialog() == DialogResult.OK) { await LoadSessionFile(openFileDialog2.FileName); } } /// /// Save as /// /// /// private async void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { if (this.IsBusy) { return; } saveFileDialog1.Title = "Save session"; saveFileDialog1.Filter = "Session files (*.jsonfig)|*.jsonfig"; saveFileDialog1.DefaultExt = "jsonfig"; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { await SaveSessionFile(saveFileDialog1.FileName); } } /// /// Close /// /// /// private void exitToolStripMenuItem2_Click(object sender, EventArgs e) { this.Close(); } /// /// Options /// /// /// private void optionsToolStripMenuItem_Click(object sender, EventArgs e) { if (this.IsBusy) { return; } var optionsForm = new OptionsForm(this.CurrentSession); if (optionsForm.ShowDialog() == DialogResult.OK) { this.CurrentSession = optionsForm.Session; InvalidateHotKey(); } } /// /// Help /// /// /// private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e) { RyzStudio.Diagnostics.Process.Execute(AppResource.AppHelpURL); } /// /// About /// /// /// private void aboutToolStripMenuItem1_Click(object sender, EventArgs e) { MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information); } #endregion #region Search Engine private async Task fileSearcher_OnFileFound(FileSearcher sender, string searchPath, string fileName) { await Task.Run(() => { _foundFiles.Add(fileName); UIControl.SetText(label3, Path.GetFileName(fileName)); progressBar2.Maximum = (sender.FileCount + sender.NoAccessFileCount); progressBar2.Value = sender.FileCount; }); } 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; if (form.ShowDialog() == DialogResult.OK) { SearchPaths = form.Lines; } } /// /// Search /// /// /// private async void button2_MouseClick(object sender, MouseEventArgs e) { if (this.IsBusy) { button2.LabelText = "&Cancelling..."; _cancellationToken.Cancel(); return; } this.IsBusy = true; progressBar1.ShowProgressText = true; progressBar2.ShowProgressText = true; _foundFiles = new List(); _cancellationToken = new CancellationTokenSource(); _currentProcess = null; _fileSearcher.FileSearchPattern = textBox1.Text; _fileSearcher.SearchPath = new List(); await Task.Run(() => { foreach (var item in SearchPaths) { 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; } } UIControl.SetText(label3, ((_foundFiles.Count <= 0) ? "0" : _foundFiles.Count.ToString("#,#", System.Globalization.CultureInfo.CurrentCulture)) + " File" + ((_foundFiles.Count == 1) ? "" : "s") + " Found"); }); if (_fileSearcher.SearchPath.Count > 0) { await _fileSearcher.Search(_cancellationToken.Token); } this.IsBusy = false; _cancellationToken = new CancellationTokenSource(); } /// /// Run next /// /// /// private async void button5_MouseClick(object sender, MouseEventArgs e) { if (this.IsBusy) { return; } if (_foundFiles.Count <= 0) { return; } await Task.Run(() => { //this.IsBusy = true; if (this.CurrentSession == null) { this.CurrentSession = new AppSession(); } if (this.CurrentSession.ClosePrevOnNext) { CloseCurrentProcess(_currentProcess); } 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)) { continue; } filename = null; } if (!string.IsNullOrWhiteSpace(filename)) { _currentProcess = RyzStudio.Diagnostics.Process.Execute(filename); } //this.IsBusy = false; }); } /// /// Save File List /// /// /// private async void button4_MouseClick(object sender, MouseEventArgs e) { if (this.IsBusy) { return; } if (_foundFiles.Count <= 0) { return; } saveFileDialog1.Title = "Save File List"; saveFileDialog1.Filter = "Text files (*.txt)|*.txt"; saveFileDialog1.DefaultExt = "txt"; 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"); } } } /// /// Close /// /// /// private void button1_MouseClick(object sender, MouseEventArgs e) { this.Close(); } private void CloseCurrentProcess(Process p) { if (p == null) { return; } try { p.CloseMainWindow(); } catch (Exception) { // do nothing } } private void InvalidateHotKey() { //#if !DEBUG UIControl.Invoke(this, (x) => { User32.UnregisterHotKey((IntPtr)Handle, 1); }); //#endif if (this.CurrentSession.NextHotKey != null) { if (this.CurrentSession.NextHotKey.KeyCode != Keys.None) { //#if !DEBUG UIControl.Invoke(this, (x) => { User32.RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.NextHotKey.ModifierCode, this.CurrentSession.NextHotKey.Key); }); //#endif } } } private void ClearSession() { _foundFiles = new List(); _currentProcess = null; textBox1.Text = "*.*"; progressBar1.Clear(0, 0, 0); progressBar2.Clear(0, 0, 0); UIControl.SetText(label4, ""); UIControl.SetText(label3, ""); } protected async Task LoadSessionFile(string filename) { await Task.Run(() => { this.CurrentSession = RyzStudio.Text.Json.JsonSerialiser.DeserialiseFile(filename) ?? new AppSession(); ClearSession(); textBox1.Text = (string.IsNullOrWhiteSpace(this.CurrentSession.SearchFilePattern) ? "*" : this.CurrentSession.SearchFilePattern?.Trim()); SearchPaths = this.CurrentSession?.SearchItems ?? new List(); // hotkey InvalidateHotKey(); }); } protected async Task SaveSessionFile(string filename) { if (string.IsNullOrWhiteSpace(filename)) { return; } if (this.CurrentSession == null) { this.CurrentSession = new AppSession(); } await Task.Run(() => { this.CurrentSession.SearchFilePattern = textBox1.Text; this.CurrentSession.SearchItems = new List(); foreach (var item in SearchPaths) { if (string.IsNullOrWhiteSpace(item)) { continue; } this.CurrentSession.SearchItems.Add(item.Trim()); } 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); } catch (Exception exc) { MessageBox.Show(exc.Message, "Save session"); return; } }); } } }