namespace SeleniumBrowser { using Newtonsoft.Json; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using SeleniumBrowser.Command; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; public class Commander { [DllImport("User32.dll")] static extern int SetForegroundWindow(IntPtr point); public const string FFMPEG_FILE = "ffmpeg.exe"; public const string RECORD_FILE = "Record.mp4"; private IWebDriver InitBrowser(BrowserInfo i_bi) { IWebDriver iwd = null; if (i_bi.Name.ToLower() == "chrome") { ChromeOptions options = new ChromeOptions(); i_bi.Parameters.ForEach(sPara => options.AddArgument(sPara)); iwd = new ChromeDriver(Environment.CurrentDirectory, options); } return iwd; } public string RunAction(BrowserInfo i_bi, List i_laiCmds, [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0, [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = null, [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = null) { string sMsg = null; CommanderGlobalData cgd = new CommanderGlobalData(); if (!Directory.Exists(cgd.StotrFolder)) { Directory.CreateDirectory(cgd.StotrFolder); } // Start Recording ProcessStartInfo startInfo = new ProcessStartInfo(FFMPEG_FILE) { WindowStyle = ProcessWindowStyle.Minimized }; string sRecordPath = Path.Combine(cgd.StotrFolder, RECORD_FILE); // https://stackoverflow.com/questions/6766333/capture-windows-screen-with-ffmpeg // ffmpeg -y -rtbufsize 100M -f gdigrab -t 00:00:30 -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p c:/video_comapre2.mp4 startInfo.Arguments = makeRecordCommand(i_laiCmds.Sum(f => 2 + f.SleepAfterEvent), sRecordPath); Process.Start(startInfo); IWebDriver iwdBrowser = null; try { do { iwdBrowser = InitBrowser(i_bi); if (iwdBrowser == null) { sMsg = "NO_BROWSER"; break; } ConcurrentDictionary cdGlobalData = new ConcurrentDictionary(); foreach (CommandInfo ai in i_laiCmds) { ai.BatchProcessData = cgd; #if DEBUG System.Diagnostics.Debug.WriteLine($"Command={ai.Command} Target={ai.Target} title={iwdBrowser.CurrentWindowHandle}"); #endif sMsg = ai.Process(iwdBrowser, ref cdGlobalData); if (sMsg != null) { break; } cgd.CommandCount++; } } while (false); } catch (Exception ex) { sMsg = $"{nameof(RunAction)} unhandle exception !. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine})."; #if DEBUG sMsg += ex.Message; #endif } #if DEBUG if (sMsg != null) { System.Diagnostics.Debug.WriteLine(sMsg); } #endif if (iwdBrowser != null) { try { iwdBrowser.Close(); iwdBrowser.Quit(); } catch { // Ignore } } return sMsg; } public string RunAction(BrowserInfo i_bi, string i_sJsonCommands, [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0, [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = null, [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = null) { return RunAction(i_bi, JsonConvert.DeserializeObject>(i_sJsonCommands), i_nCodeLine, i_sMemberName, i_sSourcePath); } protected string makeRecordCommand(int nRecordTime, string sRecordPath) { int nRecordSecondMod = nRecordTime % 60; int nRecordMinute = nRecordTime / 60; int nRecordMinuteMod = nRecordMinute % 60; int nHour = nRecordMinute / 60; return $"-y -rtbufsize 100M -f gdigrab -t {nHour:00}:{nRecordMinuteMod:00}:{nRecordSecondMod:00} -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p {sRecordPath}"; } } }