public void DoAddTasks(bool abStartup) { // Do this at most once per minute to avoid running the same task twice in rapid succession. if ( !abStartup && (!moProfile.ContainsKey("-AddTasks") || DateTime.Now < mdtPreviousAddTasksStarted.AddMinutes(1)) ) return; mdtPreviousAddTasksStarted = DateTime.Now; try { if ( null == moAddTasksProfile ) { moAddTasksProfile = moProfile.oProfile("-AddTasks").oOneKeyProfile("-Task"); moAddTasksProcessArray = new Process[moAddTasksProfile.Count]; } for (int i=0; i < moAddTasksProfile.Count; ++i) { // Convert the current task from a command-line string to a profile oject. tvProfile loAddTask = new tvProfile(moAddTasksProfile[i].ToString()); bool lbDoTask = false; if ( abStartup ) { lbDoTask = loAddTask.bValue("-OnStartup", false); // Reset pause timer to allow other tasks to run without delay after startup. mdtPreviousAddTasksStarted = DateTime.Now.AddMinutes(-1); } else { DateTime ldtTaskStartTime = loAddTask.dtValue("-StartTime", DateTime.MinValue); string lsTaskDaysOfWeek = loAddTask.sValue("-StartDays", ""); // If -StartTime is within the current minute, start the task. // If -StartDays is specified, run the task on those days only. lbDoTask = DateTime.MinValue != ldtTaskStartTime && (int)mdtPreviousAddTasksStarted.TimeOfDay.TotalMinutes == (int)ldtTaskStartTime.TimeOfDay.TotalMinutes && ("" == lsTaskDaysOfWeek || this.bListIncludesDay(lsTaskDaysOfWeek, mdtPreviousAddTasksStarted)); } if ( lbDoTask ) { string lsCommandEXE = loAddTask.sValue("-CommandEXE", "add task -CommandEXE missing"); Process loProcess = new Process(); loProcess.ErrorDataReceived += new DataReceivedEventHandler(this.BackupProcessOutputHandler); loProcess.OutputDataReceived += new DataReceivedEventHandler(this.BackupProcessOutputHandler); loProcess.StartInfo.FileName = lsCommandEXE; loProcess.StartInfo.Arguments = loAddTask.sValue("-CommandArgs", ""); loAddTask.bValue("-UnloadOnExit", false); // The following subset of parameters are overridden when -TimeoutMinutes is set. This is // necessary to guarantee IO redirection is handled properly (ie. output goes to the log). bool lbWaitForExitOverride = (loAddTask.iValue("-TimeoutMinutes", 0) > 0); loProcess.StartInfo.CreateNoWindow = lbWaitForExitOverride | loAddTask.bValue("-CreateNoWindow", false); loProcess.StartInfo.UseShellExecute = !lbWaitForExitOverride & loAddTask.bValue("-UseShellExecute", true); loProcess.StartInfo.RedirectStandardInput = lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardInput", false); loProcess.StartInfo.RedirectStandardError = lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardError", false); loProcess.StartInfo.RedirectStandardOutput = lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardOutput", false); moAddTasksProcessArray[i] = loProcess; try { if ( !loAddTask.bValue("-OnStartup", false) ) { this.LogIt(String.Format("Starting Task: {0}", loAddTask.sCommandLine())); loProcess.Start(); // Start output to console also. if ( loProcess.StartInfo.RedirectStandardError ) loProcess.BeginErrorReadLine(); if ( loProcess.StartInfo.RedirectStandardOutput ) loProcess.BeginOutputReadLine(); if ( lbWaitForExitOverride ) { // Wait the timeout period, then call "WaitForExit()" to flush the output steams. if ( loProcess.WaitForExit(60000 * loAddTask.iValue("-TimeoutMinutes", 0)) ) loProcess.WaitForExit(); // Stop output to console. if ( loProcess.StartInfo.RedirectStandardError ) loProcess.CancelErrorRead(); if ( loProcess.StartInfo.RedirectStandardOutput ) loProcess.CancelOutputRead(); loProcess.Close(); } } else { bool lbFound = false; string lsWindowTitle = loAddTask.sValue("-CommandWindowTitle", ""); Process[] loProcessesArray = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(loProcess.StartInfo.FileName)); // If there's exactly one matching process and no given window title to compare, we're done. lbFound = (1 == loProcessesArray.Length && "" == lsWindowTitle ); // If no window title has been given to compare, there's nothing else to do. if ( !lbFound && "" != lsWindowTitle ) { // If no matching processes have been found so far, get them all to compare. if ( 0 == loProcessesArray.Length ) loProcessesArray = Process.GetProcesses(); // Since a window title has been provided, it must be compared to the process(es) found. // Wildcards are permitted, but only at the end of titles. We stop at the first match. foreach (Process loProcessEntry in loProcessesArray) if ( loProcessEntry.MainWindowTitle.StartsWith(lsWindowTitle.Replace("*", "")) ) { lbFound = true; break; } } // Don't start -OnStartup processes that have already been started. if ( lbFound ) { // The process has "already started" if there is only one with the // same EXE or multiple EXEs with one having the same window title. this.LogIt(String.Format("Already running, task not started: {0}", loAddTask.sCommandLine())); } else { this.LogIt(String.Format("Starting Task: {0}", loAddTask.sCommandLine())); loProcess.Start(); // Start output to console also. if ( loProcess.StartInfo.RedirectStandardError ) loProcess.BeginErrorReadLine(); if ( loProcess.StartInfo.RedirectStandardOutput ) loProcess.BeginOutputReadLine(); if ( lbWaitForExitOverride ) { // Wait the timeout period, then call "WaitForExit()" to flush the output steams. if ( loProcess.WaitForExit(60000 * loAddTask.iValue("-TimeoutMinutes", 0)) ) loProcess.WaitForExit(); // Stop output to console. if ( loProcess.StartInfo.RedirectStandardError ) loProcess.CancelErrorRead(); if ( loProcess.StartInfo.RedirectStandardOutput ) loProcess.CancelOutputRead(); loProcess.Close(); } } } } catch (Exception ex) { this.ShowError(ex.Message, String.Format("Failed starting task: {0}", lsCommandEXE)); } } } } catch (Exception ex) { this.ShowError(ex.Message, "Add Tasks Failed"); } }
/// <summary> /// Deletes files greater than the given age /// days and of the given file specifications. /// </summary> public bool CleanupFiles() { // Return if cleanup is disabled. if ( !moProfile.bValue("-CleanupFiles", true) ) { this.LogIt(""); this.LogIt("Cleanup files is disabled."); return true; } // Return if backup is enabled and it was stopped. if ( moProfile.bValue("-BackupFiles", true) && this.bMainLoopStopped ) return true; else this.bMainLoopStopped = false; bool lbCleanupFiles = true; this.LogIt(""); this.LogIt("File cleanup started ..."); // Write the deleted file list header to disk. string lsDeletedFileListOutputPathFile = moProfile.sRelativeToProfilePathFile(this.sDeletedFileListOutputPathFile); if ( !File.Exists(lsDeletedFileListOutputPathFile) ) { // Get the column header array. string[] lsColumnHeaderArray = moProfile.sValue("-DeletedFileListOutputColumnHeaderArray", "Deleted File Time,File Size,Former File Location").Split(','); StreamWriter loStreamWriter = null; try { loStreamWriter = new StreamWriter(lsDeletedFileListOutputPathFile, false); // First, output the file header. loStreamWriter.WriteLine(string.Format(moProfile.sValue("-DeletedFileListOutputHeader" , "{0, -10:MM-dd-yyyy} File Cleanup List"), DateTime.Today)); loStreamWriter.WriteLine(); // Next output the column headers properly formatted to match the forthcoming data rows. loStreamWriter.WriteLine(string.Format( moProfile.sValue("-DeletedFileListOutputColumnFormat", "{0, -22:MM-dd-yyyy hh:mm:ss tt} {1, 13:#,#} {2}") , lsColumnHeaderArray[0], lsColumnHeaderArray[1], lsColumnHeaderArray[2])); loStreamWriter.WriteLine(); } catch (Exception ex) { this.ShowError(string.Format("File Write Failure: \"{0}\"\r\n" , lsDeletedFileListOutputPathFile) + ex.Message , "Failed Writing File" ); } finally { if ( null != loStreamWriter ) loStreamWriter.Close(); } } try { // This is used elsewhere to warn users if the software // has not been properly configured for file cleanups. this.mbHasNoDeletionGroups = true; if ( !moProfile.ContainsKey("-CleanupSet") ) { // Create the default file cleanup sets. // Get the primary backup set (ie. the 1st). tvProfile loBackupSet1Profile = new tvProfile(moProfile.sValue("-BackupSet", "(not set)")); string lsBackupOutputPathFileBase = this.sBackupOutputPathFileBase(loBackupSet1Profile); string lsBackupOutputPath = Path.GetDirectoryName(lsBackupOutputPathFileBase); string lsBackupOutputFilenameNoExt = Path.GetFileNameWithoutExtension(lsBackupOutputPathFileBase); // Initially set the cleanup of primary backups to "no cleanup" (ie. 1000 years). // The deletion limit prevents old file removal without new files to replace them. moProfile.Add("-CleanupSet", string.Format(@" -AgeDays=365000 -FilesToDelete={0}*{1} " , Path.Combine(lsBackupOutputPath, lsBackupOutputFilenameNoExt) , Path.GetExtension(lsBackupOutputPathFileBase) )); // Set the cleanup of temporary backup files to 0 days. // This is necessary to cleanup after killed processes. moProfile.Add("-CleanupSet", string.Format(@" -AgeDays=0 -FilesToDelete={0}.tmp* " , Path.Combine(this.sArchivePath(), "*" + Path.GetExtension(lsBackupOutputPathFileBase)) )); // Set the cleanup of file lists and backup / cleanup log files to 30 days. moProfile.Add("-CleanupSet", string.Format(@" -AgeDays=30 -FilesToDelete={0} -FilesToDelete={1} " , Path.Combine(Path.GetDirectoryName(this.sZipToolFileListPathFileBase) , "*" + Path.GetExtension(this.sZipToolFileListPathFileBase)) , Path.Combine(Path.GetDirectoryName(this.sLogPathFileBase) , "*" + Path.GetExtension(this.sLogPathFileBase)) )); } // Get all cleanup sets. tvProfile loCleanupSetsProfile = moProfile.oOneKeyProfile("-CleanupSet"); foreach (DictionaryEntry loEntry in loCleanupSetsProfile) { System.Windows.Forms.Application.DoEvents(); if ( this.bMainLoopStopped ) break; // Convert the current cleanup set from a command-line string to a profile oject. tvProfile loCurrentCleanupSet = new tvProfile(loEntry.Value.ToString()); // The default "LastWriteTime" is the last modified datetime. FileDateTimeTypes leFileDateTimeType; switch (loCurrentCleanupSet.sValue("-DeletedFileListDateTimeType", "LastWriteTime")) { case "CreationTime": leFileDateTimeType = FileDateTimeTypes.CreationTime; break; case "LastAccessTime": leFileDateTimeType = FileDateTimeTypes.LastAccessTime; break; default: leFileDateTimeType = FileDateTimeTypes.LastWriteTime; break; } // Use 1000 years as the default file age. int liAgeDays = loCurrentCleanupSet.iValue("-AgeDays", 365000); liAgeDays = 0 == liAgeDays ? -1 : liAgeDays; // "0" means "delete everything." -1 makes that happen. DateTime ldtOlderThan = DateTime.Now.AddDays(-liAgeDays); // Get the list of path\file specifications to delete. tvProfile loFilesToDeleteProfile = loCurrentCleanupSet.oOneKeyProfile("-FilesToDelete"); foreach (DictionaryEntry loPathFilesEntry in loFilesToDeleteProfile) { System.Windows.Forms.Application.DoEvents(); if ( this.bMainLoopStopped ) break; // Being here means there is at least one set of files to delete. this.mbHasNoDeletionGroups = false; if ( lbCleanupFiles ) lbCleanupFiles = this.CleanupPathFileSpec( moProfile.sRelativeToProfilePathFile(loPathFilesEntry.Value.ToString()) , ldtOlderThan , leFileDateTimeType , loCurrentCleanupSet ); } } if ( lbCleanupFiles ) this.DisplayDeletedFileList(); } catch (Exception ex) { this.ShowError(ex.Message, "Unanticipated Error"); lbCleanupFiles = false; } if ( this.bMainLoopStopped ) { this.LogIt("Cleanup process stopped."); this.bMainLoopStopped = false; lbCleanupFiles = false; } else { if ( lbCleanupFiles ) this.LogIt("File cleanup finished."); else this.LogIt("File cleanup failed."); } return lbCleanupFiles; }
public static tvMessageBoxResults Show( Window aoWindow , string asMessageText , string asMessageCaption , tvMessageBoxButtons aeTvMessageBoxButtons , tvMessageBoxIcons aeTvMessageBoxIcon , bool abShowModeless , tvMessageBoxCheckBoxTypes aeTvMessageBoxCheckBoxType , tvProfile aoProfile , string asProfilePromptKey , tvMessageBoxResults aeTvMessageBoxResultsOverride ) { tvMessageBoxResults liTvMessageBoxResult = tvMessageBoxResults.None; string lsPromptAnswerKey = null; bool lbUseCheckBox = tvMessageBoxCheckBoxTypes.None != aeTvMessageBoxCheckBoxType; if ( lbUseCheckBox ) { // Insert the prompt key prefix if it's not already there. A common prefix // is necessary to allow for the removal of all prompt keys as needed. if ( !asProfilePromptKey.StartsWith(msProfilePromptKeyPrefix) ) { // Strip leading hyphen. if ( asProfilePromptKey.StartsWith("-") ) asProfilePromptKey = asProfilePromptKey.Substring(1, asProfilePromptKey.Length - 1); // Insert prefix. asProfilePromptKey = msProfilePromptKeyPrefix + asProfilePromptKey; } // Make the answer key from the prompt key and the prompt key suffix. lsPromptAnswerKey = asProfilePromptKey + msProfilePromptKeySuffix; // Only the first display of a modeless dialog can contain a checkbox. // Why? Because the first prompt is not modeless. That's the only way // to capture the checkbox value. BTW, "lbUseCheckBox" is reset here // for use outside of this block to avoid the default setting next. if ( abShowModeless ) lbUseCheckBox = !aoProfile.ContainsKey(asProfilePromptKey); if ( !aoProfile.bValue(asProfilePromptKey, false) && aoProfile.ContainsKey(lsPromptAnswerKey) ) { // Do not prompt. Return the previous stored answer instead. return (tvMessageBoxResults)aoProfile.iValue( lsPromptAnswerKey, (int)tvMessageBoxResults.None); } } if ( null == asMessageCaption ) { // No caption provided. Let's try to get one another way. if ( null != aoWindow ) // Try window title first. asMessageCaption = aoWindow.Title; else if ( null != Application.Current ) // Next try for application name. asMessageCaption = Application.Current.MainWindow.Name; } if ( null != aoWindow ) aoWindow.Cursor = null; // Turn off wait cursor in parent window. tvMessageBox loMsgBox = new tvMessageBox(); loMsgBox.MessageText.Text = asMessageText; // Use some parent window attributes, if available. if ( null != aoWindow ) { // Use the parent window's icon. loMsgBox.Icon = aoWindow.Icon; // Use the given asMessageCaption as the MsgBox title, if not null. // Otherwise use the parent window title with an added question mark. loMsgBox.Title = null != asMessageCaption ? asMessageCaption : aoWindow.Title + "?"; } // Display the MsgBox header / title (ie. the caption), if provided. if ( null != asMessageCaption ) { loMsgBox.MessageTitle.Content = asMessageCaption; loMsgBox.MessageTitle.Visibility = Visibility.Visible; } loMsgBox.SelectButtons(aeTvMessageBoxButtons); loMsgBox.SelectIcon(aeTvMessageBoxIcon); if ( lbUseCheckBox ) { switch (aeTvMessageBoxCheckBoxType) { case tvMessageBoxCheckBoxTypes.DontAsk: loMsgBox.chkDontAsk.Visibility = Visibility.Visible; break; case tvMessageBoxCheckBoxTypes.SkipThis: loMsgBox.chkSkipThis.Visibility = Visibility.Visible; break; } } if ( !abShowModeless ) { loMsgBox.ShowDialog(); } else { // It can only be modeless after the checkbox has been stored. if ( lbUseCheckBox ) loMsgBox.ShowDialog(); else loMsgBox.Show(); } if ( lbUseCheckBox ) { bool lbCheckBoxValue = false; switch (aeTvMessageBoxCheckBoxType) { case tvMessageBoxCheckBoxTypes.DontAsk: lbCheckBoxValue = (bool)loMsgBox.chkDontAsk.IsChecked; break; case tvMessageBoxCheckBoxTypes.SkipThis: lbCheckBoxValue = (bool)loMsgBox.chkSkipThis.IsChecked; break; } // Use the answer override whenever not "none". This value is // necessary for certain stored answers that don't make sense // in a given context (eg. both "skip this" and "cancel" selected). if ( tvMessageBoxResults.None == aeTvMessageBoxResultsOverride ) aeTvMessageBoxResultsOverride = loMsgBox.eTvMessageBoxResult; // Reverse the boolean. "Don't ask" or "Skip this" means "Don't prompt". aoProfile[asProfilePromptKey] = !lbCheckBoxValue; aoProfile[lsPromptAnswerKey] = (int)aeTvMessageBoxResultsOverride; aoProfile.Save(); } liTvMessageBoxResult = loMsgBox.eTvMessageBoxResult; return liTvMessageBoxResult; }
internal static void ModelessMessageBox(tvProfile aoProfile, string asNamespace, string asTitle, string asMessage) { String lcsMsgBoxExeName = "MessageBox.exe"; System.Diagnostics.Process[] loProcessArray = System.Diagnostics.Process.GetProcessesByName( System.IO.Path.GetFileNameWithoutExtension(lcsMsgBoxExeName)); if ( loProcessArray.Length < aoProfile.iValue("-ModelessMessageBoxMaxCount", 3) ) { string lsMsgExePathFile = Path.Combine( Path.GetDirectoryName(aoProfile.sExePathFile), lcsMsgBoxExeName); tvFetchResource.ToDisk(asNamespace, lcsMsgBoxExeName, lsMsgExePathFile); if ( File.Exists(lsMsgExePathFile) ) System.Diagnostics.Process.Start(lsMsgExePathFile, String.Format( "-Title=\"{0}: {1}\" -Message=\"{2}\"" , asNamespace.Replace("\"", "'") , asTitle.Replace("\"", "'") , asMessage.Replace("\"", "'") )); } }