using System; using System.Drawing; using System.Windows.Forms; using System.Threading; using NaGet.SubCommands; using NaGet.Net; namespace AppliStation.Util { /// /// Description of ExecutionProgressViewer. /// public partial class ExecutionProgressViewer : Form { private NaGetTaskSet taskSet; private Thread tasksetRunningThread = null; /// /// 終了時に何を行うかのフラグ /// private enum ActionOnDoneFlags { None = 0, FlashWindow = 1, AutoCloseOnSuccess = 2, } /// /// 終了時に何を行うか /// private ActionOnDoneFlags ActionOnDone = ActionOnDoneFlags.FlashWindow; public ExecutionProgressViewer() { // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); toolTip.SetToolTip(autoCloseCheckBox, string.Format("エラーがなく正常に終了した場合、{0}秒後に自動的にこのダイアログを閉じます", autoCloseTimer.Interval/1000)); } private void onDownloadEvent(object sender, DownloadEventArgs a) { if (InvokeRequired) { Invoke(new EventHandler(onDownloadEvent), sender, a); return; } switch (a.Type) { case DownloadEventType.INITED: case DownloadEventType.CONNECTED: progressSubLabel.Text = a.TaskMessage; progressBarSub.Visible = true; progressSubLabel.Visible = true; break; case DownloadEventType.DOWNLOADING: progressSubLabel.Text = a.TaskMessage; break; case DownloadEventType.COMPLETED: progressBarSub.Visible = false; progressSubLabel.Visible = false; break; case DownloadEventType.ERROR: progressBarSub.Visible = false; progressSubLabel.Visible = false; logBox.SelectionColor = System.Drawing.Color.Red; logBox.AppendText(" [エラー] " + a.TaskMessage + System.Environment.NewLine); logBox.SelectionColor = logBox.ForeColor; break; } // ダウンロードの進捗を表示 if (a.TaskProgressPercent >= 0) { progressBarSub.Value = (int) a.TaskProgressPercent; progressBarSub.Style = ProgressBarStyle.Continuous; } else { progressBarSub.Style = ProgressBarStyle.Marquee; } } #region NaGetTaskSet関連 private void onTaskSetRaised(object sender, NaGetTaskSetEventArgs e) { NaGetTaskSet taskSet = (NaGetTaskSet) sender; NativeMethods.ProgressBarState progressState = NativeMethods.ProgressBarState.Normal; cancelButton.Enabled = taskSet.Running && taskSet.Cancelable; switch (e.Type) { case NaGetTaskSetEventType.COMPLETED: logBox.AppendText("完了." + System.Environment.NewLine); if (taskSet.Done) { okButton.Enabled = true; cancelButton.Enabled = false; // タスクが完了したらしばらく待って閉じるために、自動クローズタイマーを起動する autoCloseTimer.Start(); } break; case NaGetTaskSetEventType.STARTED_TASKSET: progressLabel.Text = taskSet.TaskSetNames[taskSet.CurrentTaskSetIndex]; logBox.AppendText(" " + e.TaskMessage + System.Environment.NewLine); break; case NaGetTaskSetEventType.COMPLETED_TASKSET: if (progressBarSub.Visible) progressBarSub.Hide(); if (progressSubLabel.Visible) progressSubLabel.Hide(); progressState = NativeMethods.ProgressBarState.Normal; logBox.AppendText(string.Format(" ... 完了. [{0}%]", (int) e.TaskProgressPercent)); logBox.AppendText(System.Environment.NewLine); break; case NaGetTaskSetEventType.INFO: logBox.AppendText(" " + e.TaskMessage + System.Environment.NewLine); break; case NaGetTaskSetEventType.ERROR: logBox.SelectionColor = System.Drawing.Color.Red; logBox.AppendText(" [エラー] " + e.TaskMessage + System.Environment.NewLine); logBox.SelectionColor = logBox.ForeColor; progressState = NativeMethods.ProgressBarState.Error; autoCloseCheckBox.Enabled = false; okButton.Enabled = true; cancelButton.Enabled = false; break; case NaGetTaskSetEventType.CANCELED: logBox.SelectionColor = System.Drawing.Color.Red; logBox.AppendText(e.TaskMessage + System.Environment.NewLine); logBox.SelectionColor = logBox.ForeColor; progressState = NativeMethods.ProgressBarState.Error; autoCloseCheckBox.Enabled = false; okButton.Enabled = true; cancelButton.Enabled = false; break; case NaGetTaskSetEventType.WARNING: logBox.SelectionColor = System.Drawing.Color.Red; logBox.AppendText(" [エラー] " + e.TaskMessage + System.Environment.NewLine); logBox.SelectionColor = logBox.ForeColor; progressState = NativeMethods.ProgressBarState.Error; autoCloseCheckBox.Enabled = false; break; } // タスクセット全体の進捗をプログレスバーに表示する if (e.TaskProgressPercent >= 0) { progressBar.Value = (int) e.TaskProgressPercent; progressBar.Style = ProgressBarStyle.Continuous; } else { progressBar.Style = ProgressBarStyle.Marquee; } NativeMethods.ProgressBar_SetState(progressBar, progressState); NativeMethods.ProgressBar_SetState(progressBarSub, progressState); // タスクセット全体の進捗をタスクバーに表示する(Windows 7以降のみ) if (e.TaskProgressPercent >= 0 && e.TaskProgressPercent < 100) { NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, (ulong) e.TaskProgressPercent, 100); } else { NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, 0, 0); } if (taskSet.Done) { if ((ActionOnDone & ActionOnDoneFlags.FlashWindow) != 0) { NativeMethods.Form_FlashWindow(this, NativeMethods.FlashFlag.All | NativeMethods.FlashFlag.TimerNoFG, uint.MaxValue, 0); } if (okButton.Enabled && (ActionOnDone & ActionOnDoneFlags.AutoCloseOnSuccess) != 0) { this.DialogResult = DialogResult.OK; Close(); Dispose(); } } } private NaGetTaskQueryResult onTaskQueryRaised(object sender, NaGetTaskQueryArgs e) { MessageBoxButtons buttons = MessageBoxButtons.OKCancel; if (e.SelectionFlag == (NaGetTaskQueryResult.CONTINUE | NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) { buttons = MessageBoxButtons.AbortRetryIgnore; } else if (e.SelectionFlag == (NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) { buttons = MessageBoxButtons.RetryCancel; } else if (e.SelectionFlag == NaGetTaskQueryResult.CONTINUE) { buttons = MessageBoxButtons.OK; } DialogResult result = MessageBox.Show(e.Message, this.Text, buttons); switch (result) { case DialogResult.OK: case DialogResult.Ignore: return NaGetTaskQueryResult.CONTINUE; case DialogResult.Cancel: case DialogResult.Abort: return NaGetTaskQueryResult.CANCEL; case DialogResult.Retry: return NaGetTaskQueryResult.RETRY; default: return NaGetTaskQueryResult.CANCELED_AUTOMATICALLY; } } public void SetTaskSet(NaGetTaskSet taskSet) { this.taskSet = taskSet; taskSet.TaskSetRaised += delegate(object sender, NaGetTaskSetEventArgs e) { if (InvokeRequired) { Invoke(new EventHandler(onTaskSetRaised), taskSet, e); } else { onTaskSetRaised(taskSet, e); } }; System.Reflection.PropertyInfo fDownloader = taskSet.GetType().GetProperty("Downloader"); if (fDownloader != null && (fDownloader.PropertyType == typeof(Downloader))) { ((Downloader) fDownloader.GetValue(taskSet, null)).DownloadEventRaised += onDownloadEvent; } taskSet.TaskQueryRaised += onTaskQueryRaised; } public void StartTaskSet() { tasksetRunningThread = new Thread(taskSet.Run); // スレッドをSTAにしないとCOMアクセスできず、ウイルススキャンができない。 tasksetRunningThread.SetApartmentState(ApartmentState.STA); tasksetRunningThread.Start(); } #endregion void LogBoxTextChanged(object sender, EventArgs e) { logBox.Select(logBox.TextLength, 0); logBox.ScrollToCaret(); } void OkButtonClick(object sender, EventArgs e) { if (taskSet == null || taskSet.Done) { this.Close(); this.Dispose(); } } void CancelButtonClick(object sender, EventArgs e) { if (InvokeRequired) { Invoke(new EventHandler(CancelButtonClickConcrete), sender, e); } else { CancelButtonClickConcrete(sender,e); } } void CancelButtonClickConcrete(object sender, EventArgs e) { autoCloseCheckBox.Enabled = false; if (taskSet != null && taskSet.Running && taskSet.Cancelable) { cancelButton.Enabled = false; NativeMethods.ProgressBar_SetState(progressBar, NativeMethods.ProgressBarState.Paused); NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style,NativeMethods.ProgressBarState.Paused, (ulong) progressBar.Value, (ulong) progressBar.Maximum); taskSet.Cancel(); } } void ExecutionProgressViewerShown(object sender, EventArgs e) { this.BringToFront(); } void ExecutionProgressViewerFormClosed(object sender, FormClosedEventArgs e) { autoCloseTimer.Enabled = false; } void AutoCloseTimerTick(object sender, EventArgs e) { autoCloseTimer.Stop(); if (InvokeRequired) { Invoke(new EventHandler(AutoCloseTimerTickConcrete), sender, e); } else { AutoCloseTimerTickConcrete(sender,e); } } void AutoCloseTimerTickConcrete(object sender, EventArgs e) { // autoCloseCheckBoxが有効(正常終了)かつチェックのときに限り、OKボタンを自動的にクリック if (autoCloseCheckBox.Enabled && autoCloseCheckBox.Checked && okButton.Enabled) { OkButtonClick(sender, e); } else if (! autoCloseCheckBox.Enabled) { // タイマーの時間がすぎて、そのとき自動で閉じないようにしていしてあるならば、手動で閉じるように autoCloseCheckBox.Enabled = false; } } } }