Index: trunk/sources/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs
===================================================================
--- trunk/sources/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs	(revision 1227)
+++ trunk/sources/HeuristicLab.PluginInfrastructure/BaseClasses/PluginBase.cs	(revision 1229)
@@ -30,5 +30,5 @@
   /// Default implementation of the IPlugin interface.
   /// </summary>
-  public class PluginBase : IPlugin {
+  public abstract class PluginBase : IPlugin {
     private string name;
     private Version version;
@@ -47,5 +47,5 @@
 
       // exactly one attribute of the type ClassInfoAttribute must be given
-      if(pluginAttributes.Length != 1) {
+      if (pluginAttributes.Length != 1) {
         throw new InvalidPluginException();
       }
@@ -55,5 +55,5 @@
 
       // if the plugin name is not explicitly set in the attribute then the default plugin name is the FullName of the type
-      if(pluginAttribute != null && pluginAttribute.Name != null) {
+      if (pluginAttribute != null && pluginAttribute.Name != null) {
         this.name = pluginAttribute.Name;
       } else {
@@ -62,5 +62,5 @@
 
       // if the version is not explicitly set in the attribute then the version of the assembly is used as default
-      if(pluginAttribute != null && pluginAttribute.Version != null) {
+      if (pluginAttribute != null && pluginAttribute.Version != null) {
         this.version = new Version(pluginAttribute.Version);
       } else {
@@ -69,5 +69,5 @@
 
       // if the description is not explicitly set in the attribute then the name of name of the plugin is used as default
-      if(pluginAttribute != null && pluginAttribute.Description != null) {
+      if (pluginAttribute != null && pluginAttribute.Description != null) {
         this.description = pluginAttribute.Description;
       } else {
@@ -81,5 +81,5 @@
       this.files = new string[fileAttributes.Length];
       int i = 0;
-      foreach(PluginFileAttribute fileAttr in fileAttributes) {
+      foreach (PluginFileAttribute fileAttr in fileAttributes) {
         files[i++] = fileAttr.Filename;
       }
@@ -121,19 +121,14 @@
     }
 
-    /// <inheritdoc/>
-    public virtual void OnInstall() {
-    }
-
-    /// <inheritdoc/>
-    public virtual void OnDelete() {
-    }
-
-    /// <inheritdoc/>
-    public virtual void OnPreUpdate() {
-    }
-
-    /// <inheritdoc/>
-    public virtual void OnPostUpdate() {
-    }
+    /// <inhertidoc>
+    public virtual void OnLoad() { }
+    /// <inhertidoc>
+    public virtual void OnInstall() { }
+    /// <inhertidoc>
+    public virtual void OnDelete() { }
+    /// <inhertidoc>
+    public virtual void OnPreUpdate() { }
+    /// <inhertidoc>
+    public virtual void OnPostUpdate() { }
 
     #endregion
Index: trunk/sources/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs
===================================================================
--- trunk/sources/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs	(revision 1227)
+++ trunk/sources/HeuristicLab.PluginInfrastructure/Interfaces/IPlugin.cs	(revision 1229)
@@ -30,5 +30,5 @@
   /// assemblies of the plugin. Plugin developers can use the properties of this interface to store
   /// plugin data (name, version, files, update location ...).
-  /// The methods OnInstall(), OnDelete(), OnPreUpdate(), OnPostUpdate() are called by the framework
+  /// The methods OnLoad(), OnInstall(), OnDelete(), OnPreUpdate(), OnPostUpdate() are called by the framework
   /// when the corresponding actions are executed. This mechanism allows that the plugin reacts to such
   /// events. For instance to store plugin specific settings.
@@ -42,4 +42,10 @@
     string[] Files { get; }
 
+
+    /// <summary>
+    /// Called by the framework whenever the plugin is loaded.
+    /// Plugins are loaded once at startup and then each time a new application is started from the starter.
+    /// </summary>
+    void OnLoad();
     /// <summary>
     /// called by the framework after the plugin was successfully installed
Index: trunk/sources/HeuristicLab.PluginInfrastructure/Loader.cs
===================================================================
--- trunk/sources/HeuristicLab.PluginInfrastructure/Loader.cs	(revision 1227)
+++ trunk/sources/HeuristicLab.PluginInfrastructure/Loader.cs	(revision 1229)
@@ -51,6 +51,6 @@
       get {
         List<PluginInfo> list = new List<PluginInfo>();
-        foreach(PluginInfo info in allPlugins.Keys) {
-          if(!disabledPlugins.Exists(delegate(PluginInfo disabledInfo) { return info.Name == disabledInfo.Name; })) {
+        foreach (PluginInfo info in allPlugins.Keys) {
+          if (!disabledPlugins.Exists(delegate(PluginInfo disabledInfo) { return info.Name == disabledInfo.Name; })) {
             list.Add(info);
           }
@@ -80,5 +80,5 @@
 
     private IPlugin FindPlugin(PluginInfo plugin) {
-      if(allPlugins.ContainsKey(plugin)) {
+      if (allPlugins.ContainsKey(plugin)) {
         return allPlugins[plugin];
       } else return null;
@@ -101,8 +101,9 @@
         try {
           return Assembly.ReflectionOnlyLoad(args.Name);
-        } catch(FileLoadException ex) {
+        }
+        catch (FileLoadException ex) {
           return null;
         }
-        };
+      };
       allPlugins.Clear();
       disabledPlugins.Clear();
@@ -121,5 +122,5 @@
       applications = new List<ApplicationInfo>();
 
-      foreach(IApplication application in apps) {
+      foreach (IApplication application in apps) {
         ApplicationInfo info = new ApplicationInfo();
         info.Name = application.Name;
@@ -137,8 +138,9 @@
       List<Assembly> assemblies = new List<Assembly>();
       // load all installed plugins into the reflection only context
-      foreach(String filename in Directory.GetFiles(pluginDir, "*.dll")) {
+      foreach (String filename in Directory.GetFiles(pluginDir, "*.dll")) {
         try {
           assemblies.Add(ReflectionOnlyLoadDll(filename));
-        } catch(BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll
+        }
+        catch (BadImageFormatException) { } // just ignore the case that the .dll file is not actually a CLR dll
       }
       return assemblies;
@@ -150,5 +152,5 @@
 
     private void CheckAssemblyDependencies(List<Assembly> assemblies) {
-      foreach(Assembly assembly in assemblies) {
+      foreach (Assembly assembly in assemblies) {
         // GetExportedTypes throws FileNotFoundException when a referenced assembly
         // of the current assembly is missing.
@@ -156,7 +158,7 @@
           Type[] exported = assembly.GetExportedTypes();
 
-          foreach(Type t in exported) {
+          foreach (Type t in exported) {
             // if there is a type that implements IPlugin
-            if(Array.Exists<Type>(t.GetInterfaces(), delegate(Type iface) {
+            if (Array.Exists<Type>(t.GetInterfaces(), delegate(Type iface) {
               // use AssemblyQualifiedName to compare the types because we can't directly 
               // compare ReflectionOnly types and Execution types
@@ -167,5 +169,6 @@
             }
           }
-        } catch(FileNotFoundException ex) {
+        }
+        catch (FileNotFoundException ex) {
           PluginInfo info = new PluginInfo();
           AssemblyName name = assembly.GetName();
@@ -176,5 +179,6 @@
           info.Message = "File not found: " + ex.FileName;
           disabledPlugins.Add(info);
-        } catch(FileLoadException ex) {
+        }
+        catch (FileLoadException ex) {
           PluginInfo info = new PluginInfo();
           AssemblyName name = assembly.GetName();
@@ -203,5 +207,5 @@
       string pluginName = "";
       // iterate through all custom attributes and search for named arguments that we are interested in 
-      foreach(CustomAttributeData attributeData in attributes) {
+      foreach (CustomAttributeData attributeData in attributes) {
         List<CustomAttributeNamedArgument> namedArguments = new List<CustomAttributeNamedArgument>(attributeData.NamedArguments);
         // if the current attribute contains a named argument with the name "Name" then extract the plugin name
@@ -209,5 +213,5 @@
           return arg.MemberInfo.Name == "Name";
         });
-        if(pluginNameArgument.MemberInfo != null) {
+        if (pluginNameArgument.MemberInfo != null) {
           pluginName = (string)pluginNameArgument.TypedValue.Value;
         }
@@ -217,5 +221,5 @@
           return arg.MemberInfo.Name == "Dependency";
         });
-        if(dependencyNameArgument.MemberInfo != null) {
+        if (dependencyNameArgument.MemberInfo != null) {
           pluginDependencies.Add((string)dependencyNameArgument.TypedValue.Value);
         }
@@ -228,7 +232,7 @@
           return arg.MemberInfo.Name == "Filetype";
         });
-        if(filenameArg.MemberInfo != null && filetypeArg.MemberInfo != null) {
+        if (filenameArg.MemberInfo != null && filetypeArg.MemberInfo != null) {
           pluginFiles.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value);
-          if((PluginFileType)filetypeArg.TypedValue.Value == PluginFileType.Assembly) {
+          if ((PluginFileType)filetypeArg.TypedValue.Value == PluginFileType.Assembly) {
             pluginAssemblies.Add(pluginDir + "/" + (string)filenameArg.TypedValue.Value);
           }
@@ -237,5 +241,5 @@
 
       // minimal sanity check of the attribute values
-      if(pluginName != "" && pluginAssemblies.Count > 0) {
+      if (pluginName != "" && pluginAssemblies.Count > 0) {
         // create a temporary PluginInfo that contains the attribute values
         PluginInfo info = new PluginInfo();
@@ -253,14 +257,14 @@
 
     private void CheckPluginDependencies() {
-      foreach(PluginInfo pluginInfo in preloadedPluginInfos) {
+      foreach (PluginInfo pluginInfo in preloadedPluginInfos) {
         // don't need to check plugins that are already disabled
-        if(disabledPlugins.Contains(pluginInfo)) {
+        if (disabledPlugins.Contains(pluginInfo)) {
           continue;
         }
         visitedDependencies.Clear();
-        if(!CheckPluginDependencies(pluginInfo.Name)) {
+        if (!CheckPluginDependencies(pluginInfo.Name)) {
           PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginInfo.Name; });
-          if(matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
-          foreach(string dependency in pluginDependencies[matchingInfo]) {
+          if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
+          foreach (string dependency in pluginDependencies[matchingInfo]) {
             PluginInfo dependencyInfo = new PluginInfo();
             dependencyInfo.Name = dependency;
@@ -276,5 +280,5 @@
     private List<string> visitedDependencies = new List<string>();
     private bool CheckPluginDependencies(string pluginName) {
-      if(!preloadedPluginInfos.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||
+      if (!preloadedPluginInfos.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||
         disabledPlugins.Exists(delegate(PluginInfo info) { return pluginName == info.Name; }) ||
         visitedDependencies.Contains(pluginName)) {
@@ -286,8 +290,8 @@
 
         PluginInfo matchingInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == pluginName; });
-        if(matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
-        foreach(string dependency in pluginDependencies[matchingInfo]) {
+        if (matchingInfo == null) throw new InvalidProgramException(); // shouldn't happen
+        foreach (string dependency in pluginDependencies[matchingInfo]) {
           visitedDependencies.Add(pluginName);
-          if(CheckPluginDependencies(dependency) == false) {
+          if (CheckPluginDependencies(dependency) == false) {
             // if only one dependency is not available that means that the current plugin also is unloadable
             return false;
@@ -304,7 +308,7 @@
     private void LoadPlugins() {
       // load all loadable plugins (all dependencies available) into the execution context
-      foreach(PluginInfo pluginInfo in preloadedPluginInfos) {
-        if(!disabledPlugins.Contains(pluginInfo)) {
-          foreach(string assembly in pluginInfo.Assemblies) {
+      foreach (PluginInfo pluginInfo in preloadedPluginInfos) {
+        if (!disabledPlugins.Contains(pluginInfo)) {
+          foreach (string assembly in pluginInfo.Assemblies) {
             Assembly.LoadFrom(assembly);
           }
@@ -314,13 +318,14 @@
       DiscoveryService service = new DiscoveryService();
       // now search and instantiate an IPlugin type in each loaded assembly
-      foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
+      foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
         // don't search for plugins in the PluginInfrastructure
-        if(assembly == this.GetType().Assembly)
+        if (assembly == this.GetType().Assembly)
           continue;
         Type[] availablePluginTypes = service.GetTypes(typeof(IPlugin), assembly);
-        foreach(Type pluginType in availablePluginTypes) {
-          if(!pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) {
+        foreach (Type pluginType in availablePluginTypes) {
+          if (!pluginType.IsAbstract && !pluginType.IsInterface && !pluginType.HasElementType) {
             IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
             PluginAction(this, new PluginManagerActionEventArgs(plugin.Name, PluginManagerAction.InitializingPlugin));
+            plugin.OnLoad();
             pluginsByName.Add(plugin.Name, plugin);
           }
@@ -328,5 +333,5 @@
       }
 
-      foreach(IPlugin plugin in pluginsByName.Values) {
+      foreach (IPlugin plugin in pluginsByName.Values) {
         PluginInfo pluginInfo = GetPluginInfo(plugin);
         allPlugins.Add(pluginInfo, plugin);
@@ -335,5 +340,5 @@
     }
     private PluginInfo GetPluginInfo(IPlugin plugin) {
-      if(pluginInfos.ContainsKey(plugin)) {
+      if (pluginInfos.ContainsKey(plugin)) {
         return pluginInfos[plugin];
       }
@@ -344,5 +349,5 @@
 
       object[] customAttributes = plugin.GetType().Assembly.GetCustomAttributes(typeof(AssemblyBuildDateAttribute), false);
-      if(customAttributes.Length > 0) {
+      if (customAttributes.Length > 0) {
         pluginInfo.BuildDate = ((AssemblyBuildDateAttribute)customAttributes[0]).BuildDate;
       }
@@ -357,10 +362,10 @@
 
       PluginInfo preloadedInfo = preloadedPluginInfos.Find(delegate(PluginInfo info) { return info.Name == plugin.Name; });
-      foreach(string assembly in preloadedInfo.Assemblies) {
+      foreach (string assembly in preloadedInfo.Assemblies) {
         // always use \ as directory separator (this is necessary for discovery of types in 
         // plugins see DiscoveryService.GetTypes() 
         pluginInfo.Assemblies.Add(assembly.Replace('/', '\\'));
       }
-      foreach(string dependency in pluginDependencies[preloadedInfo]) {
+      foreach (string dependency in pluginDependencies[preloadedInfo]) {
         // accumulate the dependencies of each assembly into the dependencies of the whole plugin
         PluginInfo dependencyInfo = GetPluginInfo(pluginsByName[dependency]);
@@ -372,6 +377,6 @@
 
     private void CheckPluginFiles() {
-      foreach(PluginInfo plugin in preloadedPluginInfos) {
-        if(!CheckPluginFiles(plugin)) {
+      foreach (PluginInfo plugin in preloadedPluginInfos) {
+        if (!CheckPluginFiles(plugin)) {
           plugin.Message = "Disabled: missing plugin file.";
           disabledPlugins.Add(plugin);
@@ -381,7 +386,7 @@
 
     private bool CheckPluginFiles(PluginInfo pluginInfo) {
-      foreach(string filename in pluginInfo.Files) {
-        if(!File.Exists(filename)) {
-          if(MissingPluginFile != null) {
+      foreach (string filename in pluginInfo.Files) {
+        if (!File.Exists(filename)) {
+          if (MissingPluginFile != null) {
             MissingPluginFile(pluginInfo.Name, filename);
           }
@@ -402,20 +407,20 @@
     internal void OnDelete(PluginInfo pluginInfo) {
       IPlugin plugin = FindPlugin(pluginInfo);
-      if(plugin!=null) plugin.OnDelete();
+      if (plugin != null) plugin.OnDelete();
     }
 
     internal void OnInstall(PluginInfo pluginInfo) {
       IPlugin plugin = FindPlugin(pluginInfo);
-      if(plugin != null) plugin.OnInstall();
+      if (plugin != null) plugin.OnInstall();
     }
 
     internal void OnPreUpdate(PluginInfo pluginInfo) {
       IPlugin plugin = FindPlugin(pluginInfo);
-      if(plugin != null) plugin.OnPreUpdate();
+      if (plugin != null) plugin.OnPreUpdate();
     }
 
     internal void OnPostUpdate(PluginInfo pluginInfo) {
       IPlugin plugin = FindPlugin(pluginInfo);
-      if(plugin != null) plugin.OnPostUpdate();
+      if (plugin != null) plugin.OnPostUpdate();
     }
   }
Index: trunk/sources/HeuristicLab.PluginInfrastructure/Runner.cs
===================================================================
--- trunk/sources/HeuristicLab.PluginInfrastructure/Runner.cs	(revision 1227)
+++ trunk/sources/HeuristicLab.PluginInfrastructure/Runner.cs	(revision 1229)
@@ -39,4 +39,5 @@
       }
       //CodeAccessPermission.RevertAssert();
+      FireOnLoad();
       PluginManager.Manager.LoadedPlugins = plugins;
     }
@@ -45,4 +46,9 @@
       IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.PluginAssembly, appInfo.PluginType).Unwrap();
       runnablePlugin.Run();
+    }
+
+    private void FireOnLoad() {
+      DiscoveryService service = new DiscoveryService();
+      Array.ForEach(service.GetInstances<IPlugin>(), p => p.OnLoad());
     }
 
