Monday, December 06, 2010

C# IShellLink COM Interop Example #1

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.

The Project
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.

Read more: Pigs Can Fly