I recently needed to use C# to programmatically create a shortcut (.LNK file) to a console executable. This is easily done in native C/C++ using the ShellLink CoClass, the IShellLink interface and their related interfaces.
I looked around and couldn’t find a good C# COM interop example for the related native COM interfaces so I wrote one. This was a good excuse for me to learn a litle bit about C# and COM interoperability. You can find the source code here, provided under the Microsoft Permissive License.
This first cut provides a set of C# classes and related values for manipulating Windows Shell Links. The public methods, properties and enumerations (or just publics) are C# style – I didn’t let the underlying native names leak through.
For example, an important native enumeration is the native SHELL_LINK_DATA_FLAGS enumeration. I’ve seen some interop examples that expose the native names of things publicly in C#. This works, but doesn’t follow the .NET Design Guidelines for Class Library Developers (in hardback on Amazon). Exposing the native names is a bit ugly in .NET languages, and in C# in particular.
In the public aspects of my C# I provide the native functionally in a modern C# manner. For example, I provide a .NET enuneration named ShellLinkFlags which provides the values in SHELL_LINK_DATA_FLAGS. These enumerations have C# style names like RunAsUser instead of SLDF_RUNAS_USER.
Another important attribute is that all of the publics are CLS compliant. This enables all .NET languages to easily access these classes, not just C#.
There are some limitations to this code. I built this so I could create shell links to EXEs – primarily console applications. This code does not yet support the IShellLink.GetIDList() and IShellLInk.SetIDList() methiods. So, it can only be used to link to things in the file system, and not shell objects such as printers.
This code is provided in a Visual Studio 2010 project built with C# and .NET 4.0 using the client profile.
The actual shell interop code is built in a separate class library named Eidos, which is the name of my general purpose C# library. The namespace is Eidos.Shell. You can use this directly, or easily incorporate it into your own code.
I’ve also included a couple of basic unit tests – you can extend these as needed.
There is also a simple program that will dump the contents of a Shell link file to the console.
The primary public class is ShellLink. This provides a set of properties and methods that provides the functionality of IShellLink but in a C# manner.
One of the biggest differences between the C# APIs and the native COM interfaces are how Data Blocks and IShellLinkDataList are treated. These are not exposed in the my .NET classes. instead, they are wrapped using standard properties on the C# ShellLink class.
This works really well. It means you can simply get and set property values just like you would with a “normal” .NET class. The IShellLink class handles all the work of creating, writing and reading the data blocks using an internal IShellLinkDataList interface.