Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.Orienteering/HeuristicLab.PluginInfrastructure/3.3/Starter/StarterForm.cs @ 11130

Last change on this file since 11130 was 11113, checked in by ascheibe, 10 years ago

#2153 fixed assembly file version lookup to also work in sandboxes.
FileVersionInfo.GetVersionInfo(..) needs LinkDemand which we don't allow in a Hive sandbox and therefore throws an exceptions. This leads to tasks that get rescheduled or just stay paused on the slave and never get sent back to the server.

File size: 13.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Linq;
26using System.Threading;
27using System.Threading.Tasks;
28using System.Windows.Forms;
29using HeuristicLab.PluginInfrastructure.Advanced;
30using HeuristicLab.PluginInfrastructure.Manager;
31
32namespace HeuristicLab.PluginInfrastructure.Starter {
33  /// <summary>
34  /// The starter form is responsible for initializing the plugin infrastructure
35  /// and shows a list of installed applications.
36  /// </summary>
37  public partial class StarterForm : Form {
38    private const string pluginManagerItemName = "Plugin Manager";
39    private const string updatePluginsItemName = "Updates Available";
40    private const string optimizerItemName = "Optimizer";
41
42    private readonly ICommandLineArgument[] arguments;
43
44    private ListViewItem pluginManagerListViewItem;
45    private bool abortRequested;
46    private PluginManager pluginManager;
47    private SplashScreen splashScreen;
48    private bool updatesAvailable = false;
49
50    /// <summary>
51    /// Initializes an instance of the starter form.
52    /// The starter form shows a splashscreen and initializes the plugin infrastructure.
53    /// </summary>
54    public StarterForm()
55      : base() {
56      InitializeComponent();
57      largeImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.HeuristicLab.ToBitmap());
58      largeImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.UpdateAvailable.ToBitmap());
59      smallImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.HeuristicLab.ToBitmap());
60      smallImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.UpdateAvailable.ToBitmap());
61      Text = "HeuristicLab " + AssemblyHelpers.GetFileVersion(GetType().Assembly);
62
63      string pluginPath = Path.GetFullPath(Application.StartupPath);
64      pluginManager = new PluginManager(pluginPath);
65      splashScreen = new SplashScreen(pluginManager, 1000);
66      splashScreen.VisibleChanged += new EventHandler(splashScreen_VisibleChanged);
67      splashScreen.Show(this, "Loading HeuristicLab...");
68
69      pluginManager.DiscoverAndCheckPlugins();
70      UpdateApplicationsList();
71
72      CheckUpdatesAvailableAsync();
73    }
74
75    /// <summary>
76    /// Creates a new StarterForm and passes the arguments in <paramref name="args"/>.
77    /// </summary>
78    /// <param name="args">The arguments that should be processed</param>
79    public StarterForm(string[] args)
80      : this() {
81      arguments = CommandLineArgumentHandling.GetArguments(args);
82    }
83
84    protected override void SetVisibleCore(bool value) {
85      value &= !(arguments.OfType<HideStarterArgument>().Any() || arguments.OfType<OpenArgument>().Any());
86      if (!value) HandleArguments();
87      base.SetVisibleCore(value);
88    }
89
90    #region Events
91    private void StarterForm_Load(object sender, EventArgs e) {
92      HandleArguments();
93    }
94
95    private void StarterForm_FormClosing(object sender, FormClosingEventArgs e) {
96      splashScreen.Close();
97      abortRequested = true;
98    }
99
100    private void applicationsListView_SelectedIndexChanged(object sender, EventArgs e) {
101      startButton.Enabled = applicationsListView.SelectedItems.Count > 0;
102    }
103
104    private void applicationsListView_ItemActivate(object sender, EventArgs e) {
105      if (applicationsListView.SelectedItems.Count > 0) {
106        ListViewItem selected = applicationsListView.SelectedItems[0];
107        if (selected.Text == pluginManagerItemName) {
108          if (pluginManager.Plugins.Any(x => x.PluginState == PluginState.Loaded)) {
109            MessageBox.Show("Installation Manager cannot be started while another HeuristicLab application is active." + Environment.NewLine +
110              "Please stop all active HeuristicLab applications and try again.", "Plugin Manager",
111              MessageBoxButtons.OK, MessageBoxIcon.Information);
112          } else {
113            try {
114              Cursor = Cursors.AppStarting;
115              using (InstallationManagerForm form = new InstallationManagerForm(pluginManager)) {
116                form.ShowDialog(this);
117              }
118              UpdateApplicationsList();
119            }
120            finally {
121              Cursor = Cursors.Arrow;
122            }
123          }
124        } else if (selected.Text == updatePluginsItemName) {
125          if (pluginManager.Plugins.Any(x => x.PluginState == PluginState.Loaded)) {
126            MessageBox.Show("Updating is not possible while another HeuristicLab application is active." + Environment.NewLine +
127              "Please stop all active HeuristicLab applications and try again.", "Update plugins",
128              MessageBoxButtons.OK, MessageBoxIcon.Information);
129          } else {
130            try {
131              Cursor = Cursors.AppStarting;
132              using (PluginUpdaterForm form = new PluginUpdaterForm(pluginManager)) {
133                form.ShowDialog(this);
134              }
135              updatesAvailable = false;
136              CheckUpdatesAvailableAsync();
137              UpdateApplicationsList();
138            }
139            finally {
140              Cursor = Cursors.Arrow;
141            }
142          }
143        } else {
144          ApplicationDescription app = (ApplicationDescription)applicationsListView.SelectedItems[0].Tag;
145          StartApplication(app, arguments);
146        }
147      }
148    }
149
150    private void largeIconsButton_Click(object sender, EventArgs e) {
151      applicationsListView.View = View.LargeIcon;
152    }
153
154    private void detailsButton_Click(object sender, EventArgs e) {
155      applicationsListView.View = View.Details;
156      foreach (ColumnHeader column in applicationsListView.Columns) {
157        if (applicationsListView.Items.Count > 0)
158          column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
159        else column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
160      }
161    }
162
163    private void aboutButton_Click(object sender, EventArgs e) {
164      List<IPluginDescription> plugins = new List<IPluginDescription>(pluginManager.Plugins.OfType<IPluginDescription>());
165      using (var dialog = new AboutDialog(plugins)) {
166        dialog.ShowDialog();
167      }
168    }
169
170    private void splashScreen_VisibleChanged(object sender, EventArgs e) {
171      // close hidden starter form
172      if (!splashScreen.Visible && arguments != null &&
173           (arguments.OfType<HideStarterArgument>().Any() || arguments.OfType<OpenArgument>().Any()))
174        Close();
175    }
176    #endregion
177
178    #region Helpers
179    private void UpdateApplicationsList() {
180      if (InvokeRequired) Invoke((Action)UpdateApplicationsList);
181      else {
182        applicationsListView.Items.Clear();
183        AddPluginManagerItem();
184        AddUpdatePluginsItem();
185
186        foreach (ApplicationDescription info in pluginManager.Applications) {
187          ListViewItem item = new ListViewItem(info.Name, 0);
188          item.Tag = info;
189          item.Group = applicationsListView.Groups["Applications"];
190          item.SubItems.Add(new ListViewItem.ListViewSubItem(item, info.Version.ToString()));
191          item.SubItems.Add(new ListViewItem.ListViewSubItem(item, info.Description));
192          item.ToolTipText = info.Description;
193          applicationsListView.Items.Add(item);
194        }
195        foreach (ColumnHeader column in applicationsListView.Columns) {
196          if (applicationsListView.Items.Count > 0)
197            column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
198          else column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
199        }
200      }
201    }
202
203    private void AddPluginManagerItem() {
204      pluginManagerListViewItem = new ListViewItem(pluginManagerItemName, 0);
205      pluginManagerListViewItem.Group = applicationsListView.Groups["Plugin Management"];
206      pluginManagerListViewItem.SubItems.Add(new ListViewItem.ListViewSubItem(pluginManagerListViewItem, AssemblyHelpers.GetFileVersion(GetType().Assembly)));
207      pluginManagerListViewItem.SubItems.Add(new ListViewItem.ListViewSubItem(pluginManagerListViewItem, "Install, upgrade or delete plugins"));
208      pluginManagerListViewItem.ToolTipText = "Install, upgrade or delete plugins";
209
210      applicationsListView.Items.Add(pluginManagerListViewItem);
211    }
212
213    private void AddUpdatePluginsItem() {
214      if (updatesAvailable) {
215        var updateListViewItem = new ListViewItem(updatePluginsItemName, 1);
216        updateListViewItem.Group = applicationsListView.Groups["Plugin Management"];
217        updateListViewItem.SubItems.Add(new ListViewItem.ListViewSubItem(updateListViewItem, ""));
218        updateListViewItem.SubItems.Add(new ListViewItem.ListViewSubItem(updateListViewItem, "Download and install updates"));
219        updateListViewItem.ToolTipText = "Download and install updates";
220
221        applicationsListView.Items.Add(updateListViewItem);
222      }
223    }
224
225    private void CheckUpdatesAvailableAsync() {
226      string pluginPath = Path.GetFullPath(Application.StartupPath);
227      var task = Task.Factory.StartNew<bool>(() => {
228        var installationManager = new InstallationManager(pluginPath);
229        IEnumerable<IPluginDescription> installedPlugins = pluginManager.Plugins.OfType<IPluginDescription>();
230        var remotePlugins = installationManager.GetRemotePluginList();
231        // if there is a local plugin with same name and same major and minor version then it's an update
232        var pluginsToUpdate = from remotePlugin in remotePlugins
233                              let matchingLocalPlugins = from installedPlugin in installedPlugins
234                                                         where installedPlugin.Name == remotePlugin.Name
235                                                         where installedPlugin.Version.Major == remotePlugin.Version.Major
236                                                         where installedPlugin.Version.Minor == remotePlugin.Version.Minor
237                                                         where Util.IsNewerThan(remotePlugin, installedPlugin)
238                                                         select installedPlugin
239                              where matchingLocalPlugins.Count() > 0
240                              select remotePlugin;
241        return pluginsToUpdate.Count() > 0;
242      });
243      task.ContinueWith(t => {
244        try {
245          t.Wait();
246          updatesAvailable = t.Result;
247          UpdateApplicationsList();
248        }
249        catch (AggregateException ae) {
250          ae.Handle(ex => {
251            if (ex is InstallationManagerException) {
252              // this is expected when no internet connection is available => do nothing
253              return true;
254            } else {
255              return false;
256            }
257          });
258        }
259      });
260    }
261
262    private void HandleArguments() {
263      try {
264        if (arguments.OfType<OpenArgument>().Any() && !arguments.OfType<StartArgument>().Any()) {
265          InitiateApplicationStart(optimizerItemName);
266        }
267        foreach (var argument in arguments) {
268          if (argument is StartArgument) {
269            var arg = (StartArgument)argument;
270            InitiateApplicationStart(arg.Value);
271          }
272        }
273      }
274      catch (AggregateException ex) {
275        ErrorHandling.ShowErrorDialog(this, "One or more errors occurred while initializing the application.", ex);
276      }
277    }
278
279    private void InitiateApplicationStart(string appName) {
280      var appDesc = (from desc in pluginManager.Applications
281                     where desc.Name.Equals(appName)
282                     select desc).SingleOrDefault();
283      if (appDesc != null) {
284        StartApplication(appDesc, arguments);
285      } else {
286        MessageBox.Show("Cannot start application " + appName + ".",
287                        "HeuristicLab",
288                        MessageBoxButtons.OK,
289                        MessageBoxIcon.Warning);
290      }
291    }
292
293    private void StartApplication(ApplicationDescription app, ICommandLineArgument[] args) {
294      splashScreen.Show("Loading " + app.Name);
295      Thread t = new Thread(delegate() {
296        bool stopped = false;
297        do {
298          try {
299            if (!abortRequested) {
300              pluginManager.Run(app, args);
301            }
302            stopped = true;
303          }
304          catch (Exception ex) {
305            stopped = false;
306            ThreadPool.QueueUserWorkItem(delegate(object exception) { ErrorHandling.ShowErrorDialog(this, (Exception)exception); }, ex);
307            Thread.Sleep(5000); // sleep 5 seconds before autorestart
308          }
309        } while (!abortRequested && !stopped && app.AutoRestart);
310      });
311      t.SetApartmentState(ApartmentState.STA); // needed for the AdvancedOptimizationFrontent
312      t.Start();
313    }
314    #endregion
315  }
316}
Note: See TracBrowser for help on using the repository browser.