[C#] ショートカットファイル(.lnk)の内容を取得する

2018-05-13 (日)

Windows Script Host(COM)を使用して.lnkファイルの内容を取得します。
COMを参照設定する方法としない方法(リフレクション)で行います。

環境

  • Windows 10 Pro 64bit 1709
  • Visual Studio Community 2017 15.5.7
  • .NET Framework 4.6.1
  • C# 7.0

結果

ショートカットの設定内容です。

取得結果です。

実装

参照設定する版

COMWindows Script Host Object Modelを参照設定に追加します。

using System;
using System.Runtime.InteropServices;
using IWshRuntimeLibrary;

public static class ShortcutWshShell
{
    public static string Get(string fullPath)
    {
        WshShell shell = null;
        IWshShortcut lnk = null;
        try
        {
            shell = new WshShell();
            lnk = (IWshShortcut)shell.CreateShortcut(fullPath);

            if (string.IsNullOrEmpty(lnk.TargetPath))
                return "lnkファイルが存在しない場合はここに来る";

            var result = new
            {
                lnk.Arguments,
                lnk.Description,
                lnk.FullName,
                lnk.Hotkey,
                lnk.IconLocation,
                lnk.TargetPath,
                lnk.WindowStyle,
                lnk.WorkingDirectory
            };

            return result.ToString();
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
        finally
        {
            if (lnk != null) Marshal.ReleaseComObject(lnk);
            if (shell != null) Marshal.ReleaseComObject(shell);
        }
    }
}

参照設定しない版

リフレクションを使用します。

using System;
using System.Runtime.InteropServices;

public static class ShortcutDynamic
{
    public static string Get(string fullPath)
    {
        dynamic shell = null;   // IWshRuntimeLibrary.WshShell
        dynamic lnk = null;     // IWshRuntimeLibrary.IWshShortcut
        try
        {
            var type = Type.GetTypeFromProgID("WScript.Shell");
            shell = Activator.CreateInstance(type);
            lnk = shell.CreateShortcut(fullPath);

            if (string.IsNullOrEmpty(lnk.TargetPath))
                return "lnkファイルが存在しない場合はここに来る";

            var result = new
            {
                lnk.Arguments,
                lnk.Description,
                lnk.FullName,
                lnk.Hotkey,
                lnk.IconLocation,
                lnk.TargetPath,
                lnk.WindowStyle,
                lnk.WorkingDirectory
            };

            return result.ToString();
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
        finally
        {
            if (lnk != null) Marshal.ReleaseComObject(lnk);
            if (shell != null) Marshal.ReleaseComObject(shell);
        }
    }
}

用途に合わせて、ValueTupleなりclassなりで返しても良いと思います。

public class Shortcut
{
    public string Arguments { get; set; }
    public string Description { get; set; }
    public string FullName { get; set; }
    public string Hotkey { get; set; }
    public string IconLocation { get; set; }
    public string TargetPath { get; set; }
    public int WindowStyle { get; set; }
    public string WorkingDirectory { get; set; }
}

その他の取得方法について

IWshRuntimeLibrary.WshShellの他にShell32.Shellを使用する方法もあります。

Windows Script Host Object Model 参照設定 (今回使用)

IWshRuntimeLibrary.WshShell
Windows Script Host のオブジェクト モデル

IWshRuntimeLibrary.IWshShortcut
WshShortcut Object

Microsoft Shell Controls and Automation 参照設定

Shell32.Shell
Scriptable Shell Objects (Windows)

Shell32.ShellLinkObject
ShellLinkObject object (Windows)

Shell32.Shell を使用しない理由

読み取り専用ファイル設定や管理者権限などに影響して例外になる場合があるため避けました。

感謝

2018-05-13 (日)