Monday, November 11, 2013
Print Screen directly with the default printer
Do you often use the Print Screen key to make a screenshot of your screen, and then insert the screenshot in a document or graphics painting or viewing program to print the screenshot with your default printer? Why not directly printing after pressing the Print Screen key? With the software PrintScreen this is possible. After starting the software, the PrintScreen icon appears in the tray. The PrintScreen tray icon offers only the possibility to exit the software. After starting the software pressing the Print Screen key will take a screenshot and print it with the default printer with the user name and date and time as title.
Saturday, November 2, 2013
WPF Open Dialog 1.1.1 Released
Today the final version of WPF Open Dialog 1.1.1 was released. This version contains a fix that prevent the application to crash in some circumstances.
Sunday, June 16, 2013
Award Winning TechNet Guru Article: Creating a Simple Plugin Mechanism
I'm proud to announce that the article Creating a Simple Plugin Mechanism has been awarded with the bronze medal at the TechNet Guru Awards - May 2013 in the section Visual C#.
Friday, May 31, 2013
Creating a Simple Plugin Mechanism
One of the recurring problems in software development is a plugin
mechanism to extending the application without changing existing code.
In two articles on the Developer Code Samples Gallery is described how to create a simple plugin mechanism. The sample code is written in C# and VB.NET.
The first article introduces into Creating a simple plugin mechanism (part 1) by reflections.
The second article introduces into Creating a simple plugin mechanism (part 2) by the Managed Extensibility Framework (MEF).
On the TechNet Wiki both articles are outlined in Creating a simple plugin mechanism.
To solve this problem, a simple plugin mechanism is implemented that search and loads plugins from a predefined location. The created plugins are projects in form of built assemblies (DLLs).
Searching for plugins
First of all we have to know where to search for plugins. Usually we will specify a folder in that all plugins are put in. In this folder we search for all assemblies.
Loading the plugins
Next we have to load the assemblies. Therefore we are using Reflections (System.Reflection
).
Searching for plugin implementations
Now we have loaded all assemblies from our predefined location, we can search for all types that implement our Interface IPlugin.
Instantiate plugin implementations
Last we create instances from our found types using Reflections.
We are using a Dictionary with the name of the plugin as key to
memorize, which button content belongs to which plugin. So we can
execute the correct plugin method on certain button click.
and using System.ComponentModel.Composition. Now we can mark the class
with the Export attribute. So the MEF will later find and process this
class. Furthermore the type is explicit stated. Hence we want to use the
interface
rather than the concrete class in the main project.
Last we need to search for the exported and imported parts and
compose them. Therefore we specify a folder in that all plugins are put
in.
So far we have searched and initialized our plugins, so we can use
the implemented properties and methods of our plugins. To access our
plugins we use the implemented MEFPluginLoader.
With that we could also use the same plugin loader to resolve several types of plugins in the same project. So we could have an ICalculationPlugin, IExporterPlugin, ISomethingElsePlugin. All these plugin interfaces can have their own properties and methods. They can be accessed from different places in different cases.
In two articles on the Developer Code Samples Gallery is described how to create a simple plugin mechanism. The sample code is written in C# and VB.NET.
The first article introduces into Creating a simple plugin mechanism (part 1) by reflections.
The second article introduces into Creating a simple plugin mechanism (part 2) by the Managed Extensibility Framework (MEF).
On the TechNet Wiki both articles are outlined in Creating a simple plugin mechanism.
To solve this problem, a simple plugin mechanism is implemented that search and loads plugins from a predefined location. The created plugins are projects in form of built assemblies (DLLs).
Creating the plugin interface
First we need to define an Interface that all plugins must implement. This Interface is often included in an own project, so other developers only need the assembly of this project to write their own plugins. The members of the Interface depend on what your application is intended to do. In this sample we have one property that is returning a name and one method that is doing something.namespace
PluginContracts {
public
interface
IPlugin {
string
Name { get; }
void
Do(); }
}Implementing the plugin interface
To provide a plugin, you have to create a new project and add a reference to PluginContracts. Then you have to implement IPlugin.using
PluginContracts; namespace
FirstPlugin {
public
class
FirstPlugin : IPlugin {
#region IPlugin Members
public
string
Name {
get {
return
"First Plugin";
}
}
public
void
Do() {
System.Windows.MessageBox.Show("Do Something in First Plugin");
}
#endregion
}
}Implementing the plugin framework
Next we need to implement the framework in our main application that knows how to find and how to handle the plugins.Searching for plugins
First of all we have to know where to search for plugins. Usually we will specify a folder in that all plugins are put in. In this folder we search for all assemblies.
string[] dllFileNames =
null;
if(Directory.Exists(path))
{
dllFileNames = Directory.GetFiles(path,
"*.dll");
}Next we have to load the assemblies. Therefore we are using Reflections (System.Reflection
ICollection<Assembly> assemblies =
new
List<Assembly>(dllFileNames.Length); foreach(string
dllFile in
dllFileNames) {
AssemblyName an = GetAssemblyName(dllFile);
Assembly assembly = Assembly.Load(an);
assemblies.Add(assembly);
}Now we have loaded all assemblies from our predefined location, we can search for all types that implement our Interface IPlugin.
Type pluginType =
typeof(IPlugin);
ICollection<Type> pluginTypes =
new
List<Type>(); foreach(Assembly assembly
in
assemblies) {
if(assembly !=
null)
{
Type[] types = assembly.GetTypes();
foreach(Type type
in
types) {
if(type.IsInterface || type.IsAbstract)
{
continue;
}
else {
if(type.GetInterface(pluginType.FullName) !=
null)
{
pluginTypes.Add(type);
}
}
}
}
}Last we create instances from our found types using Reflections.
ICollection<IPlugin> plugins =
new
List<IPlugin>(pluginTypes.Count); foreach(Type type
in
pluginTypes) {
IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
plugins.Add(plugin);
}Integrate the plugin mechanism in the main application
In the main application we can use the implemented properties and methods of our plugins. We create a button for each loaded plugin and connect the content and the click event of the button to the property and the method of the plugin to demonstrate that._Plugins =
new
Dictionary<string, IPlugin>();
ICollection<IPlugin> plugins = PluginLoader.LoadPlugins("Plugins");
foreach(var item
in
plugins) {
_Plugins.Add(item.Name, item);
Button b =
new
Button(); b.Content = item.Name;
b.Click += b_Click;
PluginGrid.Children.Add(b);
}private
void
b_Click(object
sender, RoutedEventArgs e) {
Button b = sender
as
Button; if(b !=
null)
{
string
key = b.Content.ToString(); if(_Plugins.ContainsKey(key))
{
IPlugin plugin = _Plugins[key];
plugin.Do();
}
}
}Creating a simple plugin mechanism with MEF
Creating a plugin mechanism with MEF differs not in all parts from creating a plugin mechanism from scratch. So only the differences are described in the next sections. Furthermore with the MEF, the plugin framework exists already and must not be implemented.Implementing the plugin interface
In the source of the plugins that we want to provide, we have to make our first changes. We have to add the reference to System.ComponentModel.Compositionusing
System.ComponentModel.Composition; using
PluginContracts; namespace
FirstPlugin {
[Export(typeof(IPlugin))]
public
class
FirstPlugin : IPlugin {
#region IPlugin Members
public
string
Name {
get {
return
"First Plugin";
}
}
public
void
Do() {
System.Windows.MessageBox.Show("Do Something in First Plugin");
}
#endregion
}
}Using MEF in the main application
Next we need to implement the mechanism in our main application that knows how to find and how to handle the plugins. For that we are using methods provided by MEF.
So that we can use the Export marked parts, we
have to mark properties with the Import attribute. In our case we want
to use several exported parts, so we are using the ImportMany attribute.
[ImportMany]
public
IEnumerable<IPlugin> Plugins {
get;
set;
}public
MEFPluginLoader(string
path) {
DirectoryCatalog directoryCatalog =
new
DirectoryCatalog(path); // An aggregate catalog that combines multiple catalogs
var catalog =
new
AggregateCatalog(directoryCatalog); // Create the CompositionContainer with all parts in the catalog (links Exports and Imports)
_Container =
new
CompositionContainer(catalog); // Fill the imports of this object
_Container.ComposeParts(this);
}MEFPluginLoader loader =
new
MEFPluginLoader("Plugins");
IEnumerable<IPlugin> plugins = loader.Plugins;Improvement
So that we do not need to implement for each new solution its own plugin loader, we use Generics. This allows us to remove the dependence from a certain plugin interface (here IPlugin).With that we could also use the same plugin loader to resolve several types of plugins in the same project. So we could have an ICalculationPlugin, IExporterPlugin, ISomethingElsePlugin. All these plugin interfaces can have their own properties and methods. They can be accessed from different places in different cases.
Type pluginType =
typeof(T);
ICollection<Type> pluginTypes =
new
List<Type>(); foreach(Assembly assembly
in
assemblies) {
if(assembly !=
null)
{
Type[] types = assembly.GetTypes();
foreach(Type type
in
types) {
if(type.IsInterface || type.IsAbstract)
{
continue;
}
else {
if(type.GetInterface(pluginType.FullName) !=
null)
{
pluginTypes.Add(type);
}
}
}
}
}ICollection<T> plugins =
new
List<T>(pluginTypes.Count); foreach(Type type
in
pluginTypes) {
T plugin = (T)Activator.CreateInstance(type);
plugins.Add(plugin);
}
Labels:
.NET,
C#,
Generics,
Managed Extensibility Framework,
MEF,
Plugin,
Reflection,
VB.NET,
Visual Basic,
WPF
Saturday, January 19, 2013
WPF Open Dialog 1.1.0 Released
Today the final version of WPF Open Dialog 1.1.0 was released. WPF Open Dialog is a simple library. It is using WPF and XAML and is written in C#.
WPF Open Dialog is a simple and free open file/folder dialog for WPF using MVVM
pattern. It contains an open file dialog, a folder browser dialog, and a save file dialog. Further features are file filter by extension, customizable date format, customizable texts of UI elements, and setting of owner and start-up location. The library is
available for .NET 3.5, .NET 4.0 and .NET
4.5. For more information, see http://opendialog.codeplex.com/.
Thursday, December 20, 2012
WPF Message Box 2.0.0 Released
Today the final version of WPF Message Box 2.0.0 was released. WPF Message
Box is a simple library. It is using WPF and XAML and is written in C#. WPF Message Box is a simple and free message box for WPF using MVVM pattern. Image, buttons, message, and caption can be set. The library is available for .NET 3.5, .NET 4.0 and .NET
4.5. For more information, see http://messagebox.codeplex.com/.
Thursday, November 1, 2012
WPF About Box 1.4.3.1 Released
Today the final version of WPF About Box 1.4.3.1 was released. WPF About Box is a simple library. It is using WPF and XAML and is written in C#. WPF About Box is a simple and free about box for WPF using MVVM pattern.
Several properties can be set. Some properties are read from assembly,
automatically. The library is available for .NET 3.5, .NET 4.0 and .NET 4.5. For more information, see http://aboutbox.codeplex.com/.
Saturday, March 10, 2012
Revision Control
I'm surprised again and again, when people do not
use revision control systems in software development. Also I cannot
understand not making frequently use of it. There are so many advantages
when using it. Withal it does not matter which system is used, as long
as one is used. I personally like to use subversion, but there are some
others that can be used as well. Best known revision control systems are
- Concurrent Versions System (CVS)
- Git
- Mercurial
- Subversion (SVN)
There are many advantages using revision control systems. Usually called are
- Backup functionality
- Marked software revisions
- History of changes
- Concurrent software development
Some count backup
functionality to the greatest advantage. But for me this is not the main
feature of revision control. The main feature is the history of changes. All changes can be traced. Therefor you have to check in your code with significant comment.
This is a point that is also not always done, but this should be a
matter of course. Only with a significant comment you can identify the
changes that are made. The checked in code with comment should reflect
the added functionality. So it is easy to find the location at that the
changes or added functionalities take place. It is also easy to revert
changes that made the code worse. There are also other great features of
revision control, but the main feature for me is history of changes.
Labels:
git,
Revision Control,
Subversion,
SVN,
TortoiseSVN,
VCS,
Version Control Systems
Subscribe to:
Posts (Atom)


