public void Sync_Requested(object sender = null, EventArgs e = null) { ManualForceCompare = false; if (sender != null && sender.GetType().ToString().EndsWith("Timer")) //Automated sync { Forms.Main.Instance.NotificationTray.UpdateItem("delayRemove", enabled: false); if (Forms.Main.Instance.bSyncNow.Text == "Start Sync") { Timer aTimer = sender as Timer; log.Info("Scheduled sync started (" + aTimer.Tag.ToString() + ")."); if (aTimer.Tag.ToString() == "PushTimer") { Sync.Engine.Instance.Start(updateSyncSchedule: false); } else if (aTimer.Tag.ToString() == "AutoSyncTimer") { Sync.Engine.Instance.Start(updateSyncSchedule: true); } } else if (Forms.Main.Instance.bSyncNow.Text == "Stop Sync") { log.Warn("Automated sync triggered whilst previous sync is still running. Ignoring this new request."); if (bwSync == null) { log.Debug("Background worker is null somehow?!"); } else { log.Debug("Background worker is busy? A:" + bwSync.IsBusy.ToString()); } } } else //Manual sync { if (Forms.Main.Instance.bSyncNow.Text == "Start Sync" || Forms.Main.Instance.bSyncNow.Text == "Start Full Sync") { log.Info("Manual sync requested."); if (SyncingNow) { log.Info("Already busy syncing, cannot accept another sync request."); MessageBox.Show("A sync is already running. Please wait for it to complete and then try again.", "Sync already running", MessageBoxButtons.OK, MessageBoxIcon.Hand); return; } if (Control.ModifierKeys == Keys.Shift) { if (Settings.Instance.SyncDirection == Direction.Bidirectional) { MessageBox.Show("Forcing a full sync is not allowed whilst in 2-way sync mode.\r\nPlease temporarily chose a direction to sync in first.", "2-way full sync not allowed", MessageBoxButtons.OK, MessageBoxIcon.Stop); return; } log.Info("Shift-click has forced a compare of all items"); ManualForceCompare = true; } Sync.Engine.Instance.Start(updateSyncSchedule: false); } else if (Forms.Main.Instance.bSyncNow.Text == "Stop Sync") { GoogleOgcs.Calendar.Instance.Authenticator.CancelTokenSource.Cancel(); if (!SyncingNow) { return; } if (!bwSync.CancellationPending) { Forms.Main.Instance.Console.Update("Sync cancellation requested.", Console.Markup.warning); bwSync.CancelAsync(); } else { Forms.Main.Instance.Console.Update("Repeated cancellation requested - forcefully aborting sync!", Console.Markup.warning); try { bwSync.Abort(); bwSync.Dispose(); bwSync = null; } catch { } } } } }
public void Start(Boolean updateSyncSchedule = true) { Forms.Main mainFrm = Forms.Main.Instance; try { DateTime syncStarted = DateTime.Now; String cacheNextSync = mainFrm.lNextSyncVal.Text; mainFrm.Console.Clear(); if (Settings.Instance.UseGoogleCalendar == null || Settings.Instance.UseGoogleCalendar.Id == null || Settings.Instance.UseGoogleCalendar.Id == "") { MessageBox.Show("You need to select a Google Calendar first on the 'Settings' tab."); return; } if (Settings.Instance.MuteClickSounds) { Console.MuteClicks(true); } //Check network availability if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) { mainFrm.Console.Update("There does not appear to be any network available! Sync aborted.", Console.Markup.error, notifyBubble: true); setNextSync(syncStarted, false, updateSyncSchedule, cacheNextSync); return; } //Check if Outlook is Online try { if (OutlookOgcs.Calendar.Instance.IOutlook.Offline() && Settings.Instance.AddAttendees) { mainFrm.Console.Update("<p>You have selected to sync attendees but Outlook is currently offline.</p>" + "<p>Either put Outlook online or do not sync attendees.</p>", Console.Markup.error, notifyBubble: true); setNextSync(syncStarted, false, updateSyncSchedule, cacheNextSync); return; } } catch (System.Exception ex) { mainFrm.Console.UpdateWithError(null, ex, notifyBubble: true); OGCSexception.Analyse(ex, true); return; } GoogleOgcs.Calendar.APIlimitReached_attendee = false; Forms.Main.Instance.SyncNote(Forms.Main.SyncNotes.QuotaExhaustedInfo, null, false); Forms.Main.Instance.bSyncNow.Text = "Stop Sync"; Forms.Main.Instance.NotificationTray.UpdateItem("sync", "&Stop Sync"); Forms.Main.Instance.lNextSyncVal.Text = "In progress..."; StringBuilder sb = new StringBuilder(); Forms.Main.Instance.Console.BuildOutput("Sync version: " + System.Windows.Forms.Application.ProductVersion, ref sb); Forms.Main.Instance.Console.BuildOutput((ManualForceCompare ? "Full s" : "S") + "ync started at " + syncStarted.ToString(), ref sb); Forms.Main.Instance.Console.BuildOutput("Syncing from " + Settings.Instance.SyncStart.ToShortDateString() + " to " + Settings.Instance.SyncEnd.ToShortDateString(), ref sb); mainFrm.Console.BuildOutput(Settings.Instance.SyncDirection.Name, ref sb); //Make the clock emoji show the right time int minsPastHour = DateTime.Now.Minute; minsPastHour = (int)minsPastHour - (minsPastHour % 30); sb.Insert(0, ":clock" + DateTime.Now.ToString("hh").TrimStart('0') + (minsPastHour == 00 ? "" : "30") + ":"); mainFrm.Console.Update(sb); if (Settings.Instance.OutlookPush) { OutlookOgcs.Calendar.Instance.DeregisterForPushSync(); } SyncResult syncResult = SyncResult.Fail; int failedAttempts = 0; Social.TrackSync(); try { GoogleOgcs.Calendar.Instance.GetCalendarSettings(); } catch (System.AggregateException ae) { OGCSexception.AnalyseAggregate(ae); syncResult = SyncResult.AutoRetry; } catch (System.Exception ex) { log.Warn(ex.Message); syncResult = SyncResult.AutoRetry; } while (syncResult == SyncResult.Fail) { if (failedAttempts > 0) { if (MessageBox.Show("The synchronisation failed - check the Sync tab for further details.\r\nDo you want to try again?", "Sync Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.No) { syncResult = SyncResult.Abandon; break; } else { log.Info("User opted to retry sync straight away."); } } //Set up a separate thread for the sync to operate in. Keeps the UI responsive. bwSync = new AbortableBackgroundWorker(); //Don't need thread to report back. The logbox is updated from the thread anyway. bwSync.WorkerReportsProgress = false; bwSync.WorkerSupportsCancellation = true; //Kick off the sync in the background thread bwSync.DoWork += new DoWorkEventHandler( delegate(object o, DoWorkEventArgs args) { BackgroundWorker b = o as BackgroundWorker; try { syncResult = synchronize(); } catch (System.Exception ex) { sb = new StringBuilder(); mainFrm.Console.BuildOutput("The following error was encountered during sync:-", ref sb); if (ex.Data.Count > 0 && ex.Data.Contains("OGCS")) { mainFrm.Console.BuildOutput(ex.Data["OGCS"].ToString(), ref sb); mainFrm.Console.Update(sb, Console.Markup.error, notifyBubble: true); if (ex.Data["OGCS"].ToString().Contains("Please try again")) { syncResult = SyncResult.AutoRetry; } } else { OGCSexception.Analyse(ex, true); mainFrm.Console.UpdateWithError(null, ex, notifyBubble: true); syncResult = SyncResult.Fail; } } } ); bwSync.RunWorkerAsync(); while (bwSync != null && (bwSync.IsBusy || bwSync.CancellationPending)) { System.Windows.Forms.Application.DoEvents(); System.Threading.Thread.Sleep(100); } try { //Get Logbox text - this is a little bit dirty! if (syncResult != SyncResult.OK && mainFrm.Console.DocumentText.Contains("The RPC server is unavailable.")) { mainFrm.Console.Update("Attempting to reconnect to Outlook..."); try { OutlookOgcs.Calendar.Instance.Reset(); } catch { } } } finally { failedAttempts += (syncResult != SyncResult.OK) ? 1 : 0; } } if (syncResult == SyncResult.OK) { Settings.Instance.CompletedSyncs++; consecutiveSyncFails = 0; mainFrm.Console.Update("Sync finished with success!", Console.Markup.checkered_flag); } else if (syncResult == SyncResult.AutoRetry) { consecutiveSyncFails++; mainFrm.Console.Update("Sync encountered a problem and did not complete successfully.<br/>" + consecutiveSyncFails + " consecutive syncs failed.", Console.Markup.error, notifyBubble: true); } else { consecutiveSyncFails += failedAttempts; mainFrm.Console.Update("Operation aborted after " + failedAttempts + " failed attempts!", Console.Markup.error); } setNextSync(syncStarted, syncResult == SyncResult.OK, updateSyncSchedule, cacheNextSync); mainFrm.CheckSyncMilestone(); } finally { mainFrm.bSyncNow.Text = "Start Sync"; mainFrm.NotificationTray.UpdateItem("sync", "&Sync Now"); if (Settings.Instance.MuteClickSounds) { Console.MuteClicks(false); } if (Settings.Instance.OutlookPush) { OutlookOgcs.Calendar.Instance.RegisterForPushSync(); } //Release Outlook reference if GUI not available. //Otherwise, tasktray shows "another program is using outlook" and it doesn't send and receive emails OutlookOgcs.Calendar.Instance.Disconnect(onlyWhenNoGUI: true); } }