Sunday, July 12, 2020

Creating Windows Shortcuts (links) with .NET Core and .NET Standard

I was tasked with creating a shortcut in a C# application. As a technology goal, it was desired to use .NET Standard so the code could be more readily updated to .NET Core/.NET 5 at a future time.  There are numerous examples of creating and managing file shortcuts programmatically with C# and the .NET Framework. One such example is: Create shortcut programmatically in C#. All such examples use COM and the Windows Script Host Object Model to access the Windows Shell (the system that creates and manages shortcuts). COM interop works for the .NET Framework but does not work for .NET Core or .NET Standard.

The shortcut was to be same across every computer on which the software was installed such as:
  • c:\bin\nuget.exe: executable to invoke when shortcut is clicked on
  • c:\SomeFolder\nuget.lnk: location of the shortcut that invokes c:\bin\nuget.exe
The problem to be solved is not about creating a shortcut. That can be done manually on Windows (see Windows How to Create/Copy a File Shortcut using File Explorer). The problem is solved by copying the shortcut file once created to the new machine. To make life simpler, the shortcut file should be renamed so that it could be written with the *.lnk extension but could be managed as a generic binary file (extension *.bytes) so that Windows does not attempt to treat the file as a shortcut. 

Developers who need to create a custom shortcut (custom target, custom name, etc.) using .NET Standard or .NET Core should stop reading. That functionality is only available using .NET Framework and COM interop and this style of development is not presented as part of this blog.

Recall in Windows How to Create/Copy a File Shortcut using File Explorer that a shortcut could be uploaded to Google Drive. As Google Drive is not Windows there was no attempt to follow the shortcut to the target folder so just the file associated with shortcut was updated:


Changing the extension from *.lnk to *.bytes on a Widows computer requires custom Windows Shell coding, A simpler approach is to rename the file from nuget.exe.lnk to nuget.exe.bytes while it is stored on Google Drive:


The nuget.exe.bytes file can be downloaded from Google Drive to the Downloads folder and Windows will not interpret the file as a shortcut. 

To demonstrate that a .NET Standard assembly can create a shortcut, a class library named ExampleDotNetStardardLibrary was created. The way that the shortcut will be included in this assembly is by using a resource file. A resource file is added to a C# project by clicking on the project in Solution Explorer and selecting Add | New Item:


Selecting Add | New Item displays the Add New Item dialog. Once the Add New Item dialog is displayed, the term "resource" can be typed in the textbox used to filter the file types displayed. This will reveal the Resource File file type as follows:


Click add which adds a Resource File named Resource1.resx to the .NET Standard class library project. To rename the Resource File, Resoure1.resx, right click on it and select Rename:


The resource file can be renamed ShortcutManager.resx. Double clicking on the resource file, ShortcutManager.resx, displays a designer that includes a menu entitled Add Resource. Clicking on the down arrow of Add Resource allows the Add Existing File menu item to be selected:


Invoking the Add Existing File option displays the Add existing file to resource dialog. Using this dialog it is possible to navigate to the Downloads folder where nuget.exe.bytes was downloaded from Google drive:


Once nuget.exe.bytes is selected, click on the Open button to add the file to the resource file: The nuget.exe.bytes file will be stripped of its extension (*.bytes) and stored in the project's Resources folder as follows:


Double clicking on the ShortcutManager.Designer.cs displays the code generated by Visual Studio that allows the byte associated with the nuget.exe resource to be access (remember this a shortcut not the executable):


The nuget_exe property can be invoked in order to access the bytes associated with the shortcut. This property has protection level internal so it can only be accessed by code internal to the Standard Library containing the resource file.

The ShortcutManager class, like the nuget_exe property, is set to protection level internal so the calls's methods and properties cannot be invoked from outside its .NET Standard class library. The following class, Shortcut, with protection level public demonstrates how to save the shortcut to a folder thus showing .NET Standard can be used to create a shortcut:

namespace ExampleDotNetStandardLibrary
{
    using System.IO;

    public class Shortcut
    {
        public static void Save()
        {
            File.WriteAllBytes(
                "C:\\SomeFolder\\nuget.exe.lnk", 
                 ShortcutManager.nuget_exe);
        }
    }
}







No comments :

Post a Comment