/* * Schedules Tab * */ private void runSchedules_TimedEvent(Object source, EventArgs e) { // Only run on one minute after every 15 if (DateTime.Now.Minute == 1 || DateTime.Now.Minute == 16 || DateTime.Now.Minute == 31 || DateTime.Now.Minute == 46) { this.logger.Log("Schedule checks begin"); this.scheduledEmailsStatus.Text = "Scheduled Emails are running"; try { // Read the schedules that are currently in the repository, to update the active schedule queue TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.logger; NpgsqlDataReader dr = rep.query_inactive_subscription_schedules_for_next_run_time(); if (dr.HasRows == true) { using (StreamWriter active_schedules_file = new StreamWriter(this.active_schedules_queue_filename, false, new UTF8Encoding())) { while (dr.Read()) { string sched_name = dr.GetString(0); string sched_next_run_time; //Although server time is usually UTC, the time is later compared with current time converted to UTC too. DateTime serverTime = dr.GetDateTime(1); sched_next_run_time = serverTime.ToString(); this.logger.Log(String.Format("Next scheduled run time (UTC) is {0}", sched_next_run_time)); // Only add if the sched_name is in the checked schedules int num_checked_items = availableSchedulesList.CheckedItems.Count; string[] checked_schedule_names = new string[num_checked_items]; var k = 0; foreach (object itemChecked in availableSchedulesList.CheckedItems) { checked_schedule_names[k] = itemChecked.ToString(); k++; } string[] sched = new string[2] { sched_name, sched_next_run_time }; bool schedule_exists_in_queue = false; foreach (string[] queued_sched in this.active_schedules) { if (queued_sched[0] == sched_name && queued_sched[1] == sched_next_run_time) { schedule_exists_in_queue = true; this.logger.Log(String.Format("Schedule {0} at {1} already exists in queue", sched_name, sched_next_run_time)); } } if (schedule_exists_in_queue == false) { // Only add checked schedule names if (checked_schedule_names.Any(sched.Contains) == true) { this.active_schedules.Add(sched); this.logger.Log(String.Format("Schedule {0} at {1} added to the queue", sched_name, sched_next_run_time)); active_schedules_file.WriteLine(String.Format("{0}|{1}", sched_name, sched_next_run_time)); } } } } } dr.Close(); } catch (NpgsqlException ne) { this.logger.Log("Connecting to repository to update the active queue failed. Ignoring for now, will update at next interval"); this.logger.Log(ne.Message); } // Look at the Active Queue and determine if anything is past it's due date foreach (string[] queued_sched in this.active_schedules.Reverse <string[]>()) { if (DateTime.Now.ToUniversalTime() > DateTime.Parse(queued_sched[1])) { this.logger.Log(String.Format("Schedule {0} at {1} is now eligible to be run.", queued_sched[0], queued_sched[1])); bool result = send_email(queued_sched[0]); if (result == true) { this.logger.Log(String.Format("Schedule {0} at {1} has run successfully. Removing from queue", queued_sched[0], queued_sched[1])); } else { //Suppose a schedule contains multiple subscriptions and one of them fails, the original app will send pdf to everyone else every 15 minutes. //This prevents it by removing unsuccessful sessions. this.logger.Log(String.Format("Schedule {0} at {1} failed (maybe partially). Removing from queue", queued_sched[0], queued_sched[1])); } // Write completed schedules into the schedule_run log this.completed_schedules_file.WriteLine(String.Format("{0}|{1}", queued_sched[0], queued_sched[1])); this.active_schedules.Remove(queued_sched); } } // Write the queues to the active_schedules files using (StreamWriter active_schedules_file = new StreamWriter(this.active_schedules_queue_filename, false, new UTF8Encoding())) { foreach (string[] queued_sched in this.active_schedules) { active_schedules_file.WriteLine(String.Format("{0}|{1}", queued_sched[0], queued_sched[1])); } } this.logger.Log("Schedule check completed successfully"); this.scheduledEmailsStatus.Text = "Waiting to Run Next Scheduled Emails"; } }
private void loadSubscriptionsFromRepository() { try { TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.logger; NpgsqlDataReader dr = rep.query_inactive_subscription_schedules(); Dictionary <string, int> input_box_schedules = new Dictionary <string, int>(); int rowCount = 0; availableSchedulesList.Items.Clear(); if (dr.HasRows == true) { while (dr.Read()) { availableSchedulesList.Items.Add(dr.GetString(1)); input_box_schedules[dr.GetString(1)] = rowCount; rowCount++; } } dr.Close(); // Check the selected schedules from the configs StringCollection checked_schedules = Configurator.GetConfigCollection("selected_schedule_names"); if (checked_schedules != null) { foreach (String sched_name in checked_schedules) { availableSchedulesList.SetItemChecked(input_box_schedules[sched_name], true); } } } catch (NpgsqlException ne) { this.logger.Log("Error with repository while loading the available schedules. Press reload button to try again. Going with existing checked schedules for now"); this.logger.Log(ne.Message); // Fill in the checkbox list based on the existing selected schedules StringCollection checked_schedules = Configurator.GetConfigCollection("selected_schedule_names"); if (checked_schedules != null) { var i = 0; Dictionary <string, int> input_box_schedules = new Dictionary <string, int>(); availableSchedulesList.Items.Clear(); foreach (String sched_name in checked_schedules) { availableSchedulesList.Items.Add(sched_name); input_box_schedules[sched_name] = i; availableSchedulesList.SetItemChecked(input_box_schedules[sched_name], true); i++; } } } catch (ConfigurationException ce) { this.logger.Log("Incorrect credentials for repository readonly user. Cannot connect to repository."); MessageBox.Show("Credentials were not correct for the Repository \"readonly\" user. Please fix"); this.logger.Log(String.Format("Configuration Exception: {0}", ce)); } }
private string fillInPowerpoint(uint activityId) { // Copy to the new file string ExportArchiveFolderPath = null; if (!String.IsNullOrEmpty(Configurator.GetConfig("export_archive_folder"))) { ExportArchiveFolderPath = Configurator.GetConfig("export_archive_folder"); } // Cancel action if no archive folder exists else { MessageBox.Show("Please configure the local save folder", "No Local Configuration", MessageBoxButtons.OK, MessageBoxIcon.Error); throw new ConfigurationException("Please configure the local save folder"); } // Add check for .PPT in the name before final string[] filenameNoExtension = powerPointExportFileName.Text.Split('.'); var finalFilename = ExportArchiveFolderPath + filenameNoExtension[0] + ".pptx"; // Create the new file try { this.Logger.Log(String.Format("Copying template from {1} to filename {0}", finalFilename, powerPointFilename.Text)); File.Copy(powerPointFilename.Text, finalFilename, true); } catch (Exception e) { this.Logger.Log(e.Message); } // Reset the sending messages foreach (DataGridViewRow row in powerPointStatusView.Rows) { row.Cells["Status"].Value = ""; } // Run through and send the e-mails int rowCount = 0; // Catch exception? this.Logger.Log("Opening the PowerPointer object"); var powerpointer = new PowerPointer(finalFilename, this.Logger); this.Logger.Log("Opened the PowerPointer object"); foreach (DataGridViewRow row in powerPointStatusView.Rows) { row.Cells["Status"].Value = "Processing..."; row.Selected = true; string rawSlideNumber = (string)row.Cells["Slide Number"].Value.ToString(); if (rawSlideNumber == null) { row.Cells["Status"].Value = "Invalid"; WriteToActivityGrid(String.Format("Skipped row {0} due to missing Slide Number field", rowCount), activityId); continue; } int slideNumber = Int32.Parse(rawSlideNumber); string viewLocation = (string)row.Cells["View Location"].Value.ToString(); string site = (string)row.Cells["Site"].Value.ToString(); // Skip if there is no view location or site if (viewLocation == "" || site == "") { row.Cells["Status"].Value = "Invalid"; row.Selected = false; WriteToActivityGrid(String.Format("Skipped row {0} due to missing View Location or Site", rowCount), activityId); continue; } Dictionary <string, string> filters_dict = new Dictionary <string, string>(); // Up to 25 filters (no one would realistically go this high) int j = 1; while (j <= 25) { string filterFieldKey = String.Format("Filter Field Name {0}", j.ToString()); string filterValuesKey = String.Format("Filter Values {0}", j.ToString()); if (!powerPointStatusView.Columns.Contains(filterFieldKey) || !powerPointStatusView.Columns.Contains(filterValuesKey)) { break; } if (row.Cells[filterFieldKey].ValueType != typeof(DBNull)) { string filterFieldName = (string)row.Cells[filterFieldKey].Value.ToString(); string filterValuesListRaw = (string)row.Cells[filterValuesKey].Value.ToString(); // Swap the semi-colons for commas as needed in the dict string[] filterValuesList = filterValuesListRaw.Split(';'); // Skip if there's nothing in the first split value if (filterValuesList[0] == "") { j++; continue; } string[] encodedFilters = new string[filterValuesList.Length]; for (int i = 0; i < filterValuesList.Length; i++) { // Gotta double the % sign because batch files use %2 as a replacement token. encodedFilters[i] = Uri.EscapeUriString(filterValuesList[i]).Replace("%", "%%"); } // Figure out how not to add if empty string finalValueParam = String.Join(",", encodedFilters); filters_dict.Add(filterFieldName, finalValueParam); } j++; } // Open PowerPointer object on newly copied file // Save the Presentation try { var slidePart = powerpointer.FindSlidePartBySlideNumber(slideNumber); // Generate the image file this.Logger.Log("Generating the image file to swap in"); var tempImageFileName = String.Format("Image {0}", rowCount); this.GenerateSingleExport(site, powerPointUserToGenerateAs.Text, viewLocation, "png", tempImageFileName, filters_dict); this.Logger.Log("PNG file generated"); var finalImageFileName = ExportArchiveFolderPath + tempImageFileName + ".png"; this.Logger.Log("Replacing the image in the slide"); var replacementSuccess = powerpointer.ReplaceImageInSlide(slidePart, finalImageFileName); this.Logger.Log("Replaced the image in the slide"); File.Delete(finalImageFileName); if (replacementSuccess) { row.Cells["Status"].Value = "Replaced Successfully"; } else { row.Cells["Status"].Value = "No Replacement"; } } catch (NotFoundException) { row.Cells["Status"].Value = "Invalid Slide Number"; } row.Selected = false; rowCount++; } powerpointer.SavePresentation(); powerpointer.ClosePresentation(); EnablePowerpointButtons(); return("Finished filling in PowerPoint template file"); }
private void button1_Click(object sender, EventArgs e) { Configurator.EncryptConfig(); }
public static void SaveConfig() { Configurator.EncryptConfig(); Properties.Settings.Default.Save(); }
public bool SendEmail(string scheduleName) { try { BeholdEmailer tabemailer = this.CreateBeholdEmailerFromConfig(); Watermarker wm = this.CreateWatermarkerFromConfig(); try { bool result; if (scheduleName != "") { tabemailer.ExportArchiveFolderPath = Configurator.GetConfig("export_archive_folder"); result = tabemailer.GenerateEmailsFromNamedScheduleInRepository(scheduleName, Configurator.GetConfig("email_sender"), wm); } else { result = tabemailer.GenerateEmailFromView(Configurator.GetConfig("email_sender"), new string[1] { testEmailRecipient.Text }, new string[0] { }, new string[0] { }, testEmailSubject.Text, "Please see attached file", singleUsernameForImpersonation.Text, singleViewLocation.Text, ExportTypeIndexMap[Int32.Parse(Configurator.GetConfig("single_export_type_index"))], new Dictionary <String, String>(), wm); } return(result); } catch (ConfigurationException ce) { this.Logger.Log(ce.Message); return(false); } } // From Repository Failing catch (ConfigurationException ce) { this.Logger.Log(ce.Message); return(false); } }
private BeholdEmailer CreateBeholdEmailerFromConfig() { return(this.CreateBeholdEmailerFromConfig(Configurator.GetConfig("single_export_site"))); }
public ConfigureLocalSettings() { InitializeComponent(); exportArchiveFolder.Text = Configurator.GetConfig("export_archive_folder"); }
private void updateSchedulesQueue() { var activityId = this.nextActivityId; this.nextActivityId++; WriteToActivityGrid("Checking for schedules to run in the repository", activityId); this.Logger.Log("Schedule checks begin"); try { // Read the schedules that are currently in the repository, to update the active schedule queue TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.Logger; //this.Logger.Log("Starting to read from the repository"); NpgsqlDataReader dr = rep.QueryInactiveSubscriptionSchedulesForNextRunTime(); if (dr.HasRows == true) { //this.Logger.Log("Opening the active schedules queue file"); using (StreamWriter activeSchedulesQueueFileWriter = new StreamWriter(this.ActiveSchedulesQueueFilename, false, new UTF8Encoding())) { //this.Logger.Log("Reading from the result set "); while (dr.Read()) { // this.Logger.Log("Working inside the result set "); string scheduleName = dr.GetString(0); string scheduleNextRunTime = dr.GetDateTime(1).ToString(); //this.Logger.Log(String.Format("Schedule here {0} {1}", scheduleName, scheduleNextRunTime)); // Because the selections are stored instantly, load from the saved collectionr rather than the control // It is possible the control has not been redrawn at the time List <string> selectedScheduleNames = new List <string>() { }; StringCollection savedSchedules = Configurator.GetConfigCollection("selected_schedule_names"); if (savedSchedules != null) { foreach (String savedScheduleName in savedSchedules) { selectedScheduleNames.Add(savedScheduleName); } } string[] scheduleInfo = new string[2] { scheduleName, scheduleNextRunTime }; bool doesScheduleExistInQueue = false; // See if what is in the activeSchedulesQueue file is a checked schedule still foreach (string[] activeSchedule in this.ActiveSchedules) { if (activeSchedule[0] == scheduleName && activeSchedule[1] == scheduleNextRunTime) { this.Logger.Log(String.Format("Schedule {0} at {1} already in the schedules queue", scheduleName, scheduleNextRunTime)); doesScheduleExistInQueue = true; } } if (doesScheduleExistInQueue == false) { // Only add checked schedule names if (selectedScheduleNames.Any(scheduleInfo.Contains) == true) { this.ActiveSchedules.Add(scheduleInfo); WriteToActivityGrid(String.Format("Schedule {0} at {1} added to the schedules queue", scheduleName, scheduleNextRunTime), activityId); this.Logger.Log(String.Format("Schedule {0} at {1} added to the schedules queue", scheduleName, scheduleNextRunTime)); activeSchedulesQueueFileWriter.WriteLine(String.Format("{0}|{1}", scheduleName, scheduleNextRunTime)); } else { this.Logger.Log(String.Format("Schedule {0} at {1} not added to schedules queue because it is not selected", scheduleName, scheduleNextRunTime)); } } } } } else { this.Logger.Log("No rows found in the query for new schedules"); } dr.Close(); } catch (NpgsqlException ne) { this.Logger.Log("Connecting to repository to update the active queue failed. Ignoring for now, will update at next interval"); this.Logger.Log(ne.Message); } WriteToActivityGrid("Completed checking for new schedules", activityId); // Look at the Active Queue and determine if anything is past it's due date foreach (string[] queuedSchedule in this.ActiveSchedules.Reverse <string[]>()) { if (DateTime.Now.ToUniversalTime() > DateTime.Parse(queuedSchedule[1])) { activityId = this.nextActivityId; this.nextActivityId++; this.Logger.Log(String.Format("Schedule {0} at {1} is now eligible to be run.", queuedSchedule[0], queuedSchedule[1])); WriteToActivityGrid(String.Format("Schedule {0} at {1} is now eligible to be run. Queuing to run.", queuedSchedule[0], queuedSchedule[1]), activityId); // Add to the actionQueue at the top asyncActionQueue.Insert(0, () => { var queuedScheduleName = queuedSchedule[0]; var queuedScheduleRunTime = queuedSchedule[1]; WriteToActivityGrid(String.Format("Running Schedule {0} at {1}.", queuedSchedule[0], queuedSchedule[1]), activityId); bool result = SendEmail(queuedScheduleName); // Even if failure, remove from active schedules queue this.Logger.Log(String.Format("Removing {0} at {1} from active schedules queue", queuedSchedule[0], queuedSchedule[1])); this.ActiveSchedules.Remove(queuedSchedule); // Write the remaining queues. using (StreamWriter activeSchedulesQueueFileWriter = new StreamWriter(this.ActiveSchedulesQueueFilename, false, new UTF8Encoding())) { foreach (string[] currentlyQueuedSchedules in this.ActiveSchedules) { activeSchedulesQueueFileWriter.WriteLine(String.Format("{0}|{1}", currentlyQueuedSchedules[0], currentlyQueuedSchedules[1])); } } if (result) { WriteToActivityGrid(String.Format("Completed Schedule {0} at {1}.", queuedScheduleName, queuedScheduleRunTime), activityId); return(String.Format("Completed Schedule {0} at {1}.", queuedScheduleName, queuedScheduleRunTime)); } else { this.ActiveSchedules.Remove(queuedSchedule); WriteToActivityGrid(String.Format("Schedule {0} at {1} failed, see log.", queuedScheduleName, queuedScheduleRunTime), activityId); return(String.Format("Schedule {0} at {1} failed, see log.", queuedScheduleName, queuedScheduleRunTime)); } } ); // Launch the next action in the queue, if possible try { actionQueueBackgroundWorker.RunWorkerAsync(asyncActionQueue[0]); } // The queue response will launch the next action once it is finished catch (InvalidOperationException) { this.Logger.Log("Action queued but other action currently running"); } } } }