/// <summary> /// Initializes the library. /// </summary> public static void Initialize() { if (!Signature.IsActivated) { return; } if (Files.Count != 0) { Log.Debug("Library data loaded; checking to see if files still exist."); foreach (var ep in Files) { var files = ep.Value.ToList(); foreach (var file in files) { try { if (!File.Exists(file)) { ep.Value.Remove(file); } } catch { } } } } _stmr = new Timer { AutoReset = false, Interval = 3000 }; _stmr.Elapsed += (sender, args) => { try { SaveList(); } catch (Exception ex) { Log.Warn("Error while saving library.", ex); } if (UPnP.IsRunning) { try { UPnP.RebuildList(); } catch (Exception ex) { Log.Warn("Error while rebuilding UPnP/DLNA library.", ex); } } }; SearchForFiles(); }
/// <summary> /// Propagates data changes. /// </summary> /// <param name="delaySave">if set to <c>true</c> the database commit will be delayed for 3 seconds.</param> private static void DataChanged(bool delaySave = true) { try { if (MainWindow.Active != null && MainWindow.Active.activeGuidesPage != null && MainWindow.Active.activeGuidesPage._activeShowID != 0) { MainWindow.Active.Run(MainWindow.Active.activeGuidesPage.Refresh); } } catch { } if (delaySave) { if (_stmr.Enabled) { _stmr.Stop(); } _stmr.Start(); } else { try { SaveList(); } catch (Exception ex) { Log.Warn("Error while saving library.", ex); } if (UPnP.IsRunning) { try { UPnP.RebuildList(); } catch (Exception ex) { Log.Warn("Error while rebuilding UPnP/DLNA library.", ex); } } } }
/// <summary> /// Checks for open files on the specified processes and marks them if recognized. /// </summary> public static void CheckOpenFiles() { if (!Settings.Get("Monitor Processes", true)) { return; } Log.Debug("Checking for open files..."); var alt = Settings.Get("Process Monitoring Method", "Internal") == "WindowTitle"; var netmon = Settings.Get <bool>("Monitor Network Shares"); if (!alt && !Utils.IsAdmin) { Log.Info("You are not running with administrator rights but requested file handle monitoring."); } var procs = new List <string>(); procs.AddRange(Settings.Get <List <string> >("Processes to Monitor")); try { procs.AddRange(Utils.GetDefaultVideoPlayers().Select(Path.GetFileName)); } catch (Exception ex) { Log.Warn("Error while getting list of default video players.", ex); } if (Log.IsTraceEnabled) { Log.Trace("Requested processes:", procs); } if (!procs.Any() && !netmon && !UPnP.IsRunning) { Log.Debug("No processes specified to monitor and network share monitoring is disabled."); return; } var pids = GetPIDs(procs).Distinct().ToList(); if (Log.IsTraceEnabled) { Log.Trace("Running PIDs:", pids); } if (!pids.Any() && !netmon && !UPnP.IsRunning) { Log.Debug("Unable to get at least one PID for the specified processes and network share monitoring is disabled."); return; } var files = new List <FileInfo>(); var titles = new List <string>(); if (pids.Any()) { if (!alt) { using (var mre = new ManualResetEvent(false)) { var thd = new Thread(() => { try { files.AddRange(GetHandleList(pids)); } finally { mre.Set(); } }) { IsBackground = true }; thd.Start(); if (!mre.WaitOne(TimeSpan.FromMinutes(3))) { Log.Error("Process monitoring method timed out after 3 minutes. Please consider switching implementations from the Settings menu."); try { thd.Interrupt(); thd.Abort(); } catch { } } } if (files.Count != 0) { Log.Debug(Utils.FormatNumber(files.Count, "file handle", true) + " open for the PID" + (pids.Count != 1 ? "s" : string.Empty) + ": " + string.Join(", ", pids).TrimEnd(", ".ToCharArray()) + "."); } } else { titles.AddRange(GetWindownTitles(pids)); if (titles.Count != 0) { Log.Debug(Utils.FormatNumber(files.Count, "window title", true) + " found for the PID" + (pids.Count != 1 ? "s" : string.Empty) + ": " + string.Join(", ", pids).TrimEnd(", ".ToCharArray()) + "."); } if (Log.IsTraceEnabled) { Log.Trace("Window titles:", titles); } } } if (Signature.IsActivated && UPnP.IsRunning) { try { var cnt = files.Count; files.AddRange(UPnP.GetActiveTransfers()); if (files.Count != cnt) { Log.Debug(Utils.FormatNumber(files.Count - cnt, "file handle", true) + " open through the UPnP/DLNA server."); } } catch (Exception ex) { Log.Warn("Cannot get active transfer list from the UPnP/DLNA server due to an exception.", ex); } } if (Signature.IsActivated && netmon) { try { var cnt = files.Count; files.AddRange(NetworkShares.GetActiveTransfers()); if (files.Count != cnt) { Log.Debug(Utils.FormatNumber(files.Count - cnt, "file handle", true) + " open through Windows file sharing."); } } catch (Exception ex) { Log.Warn("Cannot get active network share transfer list from Windows due to an exception.", ex); } } if (Log.IsTraceEnabled) { Log.Trace("Open file handles:", files.Select(fi => fi.FullName)); } if (files.Count == 0 && titles.Count == 0) { Log.Debug("No " + (alt ? "window titles" : "file handles open") + " for the specified processes (" + (pids.Count == 0 ? "none running" : "PID" + (pids.Count != 1 ? "s" : string.Empty) + ": " + string.Join(", ", pids).TrimEnd(", ".ToCharArray())) + ") and services."); return; } foreach (var show in Database.TVShows) { var titleRegex = Parser.GenerateTitleRegex(show.Value.Title, show.Value); var releaseExpr = string.Empty; var releaseRegex = show.Value.Data.TryGetValue("regex", out releaseExpr) && !string.IsNullOrWhiteSpace(releaseExpr) ? new Regex(releaseExpr) : null; foreach (var file in files) { if (Parser.IsMatch(file.DirectoryName + @"\" + file.Name, titleRegex) || (releaseRegex != null && Parser.IsMatch(file.DirectoryName + @"\" + file.Name, releaseRegex))) { var pf = FileNames.Parser.ParseFile(file.Name, file.DirectoryName.Split(Path.DirectorySeparatorChar), false); if (pf.Success && show.Value.Title == pf.Show) { Log.Debug("Identified open file " + file.Name + " as " + pf + "."); if (!OpenFiles.Contains(file.ToString())) { // add to open files list // 5 minutes later we'll check again, and if it's still open we'll mark it as seen // the reason for this is that an episode will be marked as seen only if you're watching it for more than 10 minutes (5 minute checks twice) OpenFiles.Add(file.ToString()); } else { MarkAsSeen(show.Value.ID, pf); } } } } foreach (var title in titles) { if (Parser.IsMatch(title, titleRegex, null, false) || (releaseRegex != null && Parser.IsMatch(title, releaseRegex, null, false))) { var pf = FileNames.Parser.ParseFile(title, null, false); if (pf.Success && show.Value.Title == pf.Show) { Log.Debug("Identified window title " + title + " as " + pf + "."); if (!OpenFiles.Contains(pf.ToString())) { OpenFiles.Add(pf.ToString()); } else { MarkAsSeen(show.Value.ID, pf); } } } } } }