private static bool ProgramRecording(int bufferMinutes) { var expireTime = DateTime.Now + TimeSpan.FromHours(MaximumRecordingWaitHours); const int intervalMinutes = 1; var intervalCheck = 0; do { var active = WmcStore.DetermineRecordingsInProgress() || WmcRegistries.NextScheduledRecording() - TimeSpan.FromMinutes(bufferMinutes) < DateTime.Now; if (!active && intervalCheck > 0) { Thread.Sleep(30000); active = WmcStore.DetermineRecordingsInProgress() || WmcRegistries.NextScheduledRecording() - TimeSpan.FromMinutes(bufferMinutes) < DateTime.Now; } if (!active || expireTime < DateTime.Now) { WmcStore.Close(); return(active); } Helper.SendPipeMessage($"Importing|Waiting for recordings to end...|Will check again at {DateTime.Now + TimeSpan.FromMinutes(intervalMinutes):HH:mm:ss}"); if (intervalCheck++ % (60 / intervalMinutes) == 0) { Logger.WriteInformation($"There is a recording in progress or the next scheduled recording is within {bufferMinutes} minutes. Delaying garbage collection and/or import."); } Thread.Sleep(intervalMinutes * 60000); } while (true); }
private static int Main(string[] args) { // setup catch to fatal program crash AppDomain.CurrentDomain.UnhandledException += MyUnhandledException; Application.ThreadException += MyThreadException; // filter out mcupdate calls that may be redirected var arguments = string.Join(" ", args); switch (arguments) { case "-u -nogc": // opening WMC case "-uf -nogc": Logger.WriteVerbose($"**** Intercepted \"mcupdate.exe {arguments}\" call. Ignored. ****"); Logger.Close(); return(0); case "-u -manual -nogc -p 0": // guide update case "-manual -nogc -p 0": var startTime = DateTime.Now; var startInfo = new ProcessStartInfo() { FileName = "schtasks.exe", Arguments = "/run /tn \"epg123_update\"", UseShellExecute = false, CreateNoWindow = true, }; // begin update var proc = Process.Start(startInfo); proc?.WaitForExit(); Logger.WriteInformation("**** Attempted to kick off the epg123_update task on demand. ****"); Logger.Close(); // monitor the task status until it is complete var ts = new epgTaskScheduler(); while (true) { // looks like WMC may have a 30000 ms timeout for the update action // no reason to continue with the mcupdate run if it is going to be ignored if (DateTime.Now - startTime > TimeSpan.FromMinutes(5.0)) { return(0); } ts.QueryTask(true); if (ts.StatusString.ToLower().Contains("running")) { Thread.Sleep(100); } else { break; } } // kick off mcupdate so it can fail but signal WMC that update is complete startInfo = new ProcessStartInfo() { FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\ehome\mcupdate.exe"), Arguments = arguments }; proc = Process.Start(startInfo); proc?.WaitForExit(); return(0); } // evaluate arguments bool nologo, import, force, showGui, advanced, nogc, verbose, noverify; var match = nologo = import = force = showGui = advanced = nogc = verbose = noverify = false; if (File.Exists($"{Helper.Epg123ProgramDataFolder}\\nogc.txt")) { File.Delete($"{Helper.Epg123ProgramDataFolder}\\nogc.txt"); nogc = true; } if (args.Length > 0) { for (var i = 0; i < args.Length; ++i) { switch (args[i].ToLower()) { case "-match": match = true; break; case "-nologo": nologo = true; break; case "-i": if (i + 1 < args.Length) { filename = args[++i].Replace("EPG:", "http:"); if (filename.StartsWith("http")) { statusLogo.MxfFile = Helper.Epg123MxfPath; import = true; break; } if (!File.Exists(filename)) { var err = $"File \"{filename}\" does not exist."; Logger.WriteError(err); return(-1); } filename = new FileInfo(filename).FullName.ToLower(); var testNewFile = filename.Replace("\\epg123.mxf", "\\output\\epg123.mxf"); if (File.Exists(testNewFile)) { Logger.WriteWarning($"It appears the MXF file to import is incorrect. Changing the import file from \"{filename}\" to \"{testNewFile}\". Delete and re-create your Scheduled Task."); filename = testNewFile; } statusLogo.MxfFile = filename; } else { Logger.WriteError("Missing input filename and path."); return(-1); } import = true; break; case "-f": force = true; break; case "-p": showProgress = true; break; case "-x": advanced = true; showGui = true; break; case "-nogc": nogc = true; break; case "-verbose": verbose = true; break; case "-noverify": noverify = true; break; default: Logger.WriteVerbose($"**** Invalid arguments for epg123Client.exe; \"{arguments}\" ****"); Logger.Close(); return(-1); } } } else { showGui = true; } // create a mutex and keep alive until program exits using (var mutex = !showGui && showProgress ? new Mutex(false, $"Global\\{AppGuid}") : Helper.GetProgramMutex($"Global\\{AppGuid}", !showGui)) { // check for an instance already running if (mutex == null) { return(-1); } Logger.WriteMessage("==============================================================================="); Logger.WriteMessage($" {(showGui ? "Activating the epg123 client GUI." : "Beginning epg123 client execution.")} version {Helper.Epg123Version}"); Logger.WriteMessage("==============================================================================="); Logger.WriteMessage($"*** {Helper.GetOsDescription()} ***"); Logger.WriteMessage($"*** {Helper.GetWmcDescription()} ***"); // show gui if needed if (showGui) { var client = new clientForm(advanced); client.ShowDialog(); GC.Collect(); if (client.RestartClientForm) { // start a new process _ = Process.Start(new ProcessStartInfo { FileName = Helper.Epg123ClientExePath, WorkingDirectory = Helper.ExecutablePath, UseShellExecute = true, Verb = client.RestartAsAdmin ? "runas" : null }); } client.Dispose(); } else { // prevent machine from entering sleep mode var prevThreadState = NativeMethods.SetThreadExecutionState( (uint)ExecutionFlags.ES_CONTINUOUS | (uint)ExecutionFlags.ES_SYSTEM_REQUIRED | (uint)ExecutionFlags.ES_AWAYMODE_REQUIRED); Logger.WriteVerbose($"Import: {import} , Match: {match} , NoLogo: {nologo} , Force: {force} , ShowProgress: {showProgress} , NoGC: {force || nogc} , NoVerify: {noverify} , Verbose: {verbose}"); var startTime = DateTime.UtcNow; if (import) { // check if garbage cleanup is needed if (!nogc && !force && WmcRegistries.IsGarbageCleanupDue() && !ProgramRecording(60)) { _ = WmcUtilities.PerformGarbageCleanup(); } // ensure no recordings are active if importing if (!force && ProgramRecording(10)) { Logger.WriteError($"A program recording is still in progress after {MaximumRecordingWaitHours} hours. Aborting the mxf file import."); goto CompleteImport; } WmcStore.Close(); // import mxf file if (!ImportMxfFile(filename)) { Logger.WriteError("Failed to import .mxf file. Exiting."); goto CompleteImport; } // perform verification if (!noverify) { _ = new VerifyLoad(filename, verbose); } // get lineup and configure lineup type and devices if (!WmcStore.ActivateEpg123LineupsInStore() || !WmcRegistries.ActivateGuide()) { Logger.WriteError("Failed to locate any lineups from EPG123."); goto CompleteImport; } } // remove all channel logos if (nologo) { WmcStore.ClearLineupChannelLogos(); } // perform automatch if (match) { try { WmcStore.AutoMapChannels(); Logger.WriteInformation("Completed the automatch of lineup stations to tuner channels."); } catch (Exception ex) { Logger.WriteError($"{ex.Message}"); Logger.WriteError("Failed to perform the automatch of lineup stations to tuner channels task."); } } // import success if (import) { // refresh the lineups after import using (var mergedLineups = new MergedLineups(WmcStore.WmcObjectStore)) { foreach (MergedLineup mergedLineup in mergedLineups) { _ = mergedLineup.Refresh(); } } Logger.WriteInformation("Completed lineup refresh."); // reindex database _ = WmcUtilities.ReindexPvrSchedule(); _ = WmcUtilities.ReindexDatabase(); } // import complete CompleteImport: if (import) { // update status logo statusLogo.StatusImage(); // signal the notification tray to update the icon Helper.SendPipeMessage("Import Complete"); } WmcStore.Close(); // all done Logger.WriteInformation("Completed EPG123 client execution."); Logger.WriteVerbose($"EPG123 client execution time was {DateTime.UtcNow - startTime}."); Logger.Close(); NativeMethods.SetThreadExecutionState(prevThreadState | (uint)ExecutionFlags.ES_CONTINUOUS); } } Environment.Exit(0); return(0); }
private void btnExit_Click(object sender, EventArgs e) { WmcStore.Close(); Close(); }