using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Runtime.InteropServices.ComTypes;
/****************************************************************************
* Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
***************************************************************************/
namespace NativeHelpers
{
// Modified from http://smdn.jp/programming/tips/createlnk/
// Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
// /Creating_and_Modifying_Shortcuts/article.asp
// Partly based on Sending toast notifications from desktop apps sample
public class ShellLink : IDisposable
{
#region Fields
private IShellLinkW shellLinkW = null;
#endregion
#region Private Properties (Interfaces)
private IPersistFile PersistFile
{
get
{
IPersistFile PersistFile = shellLinkW as IPersistFile;
if (PersistFile == null)
throw new COMException("Failed to create IPersistFile.");
else
return PersistFile;
}
}
private IPropertyStore PropertyStore
{
get
{
IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
if (PropertyStore == null)
throw new COMException("Failed to create IPropertyStore.");
else
return PropertyStore;
}
}
#endregion
#region Public Properties (Minimal)
// Path of loaded shortcut file
public string ShortcutFile
{
get
{
string shortcutFile;
PersistFile.GetCurFile(out shortcutFile);
return shortcutFile;
}
}
// Path of target file
public string TargetPath
{
get
{
// No limitation to length of buffer string in the case of Unicode though.
StringBuilder targetPath = new StringBuilder(NativeValues.MAX_PATH);
WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
NativeCalls.VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
NativeValues.SLGP_UNCPRIORITY));
return targetPath.ToString();
}
set
{
NativeCalls.VerifySucceeded(shellLinkW.SetPath(value));
}
}
public string Arguments
{
get
{
// No limitation to length of buffer string in the case of Unicode though.
StringBuilder arguments = new StringBuilder(NativeValues.INFOTIPSIZE);
NativeCalls.VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
return arguments.ToString();
}
set
{
NativeCalls.VerifySucceeded(shellLinkW.SetArguments(value));
}
}
public string Description
{
get
{
// No limitation to length of buffer string in the case of Unicode though.
StringBuilder description = new StringBuilder(NativeValues.INFOTIPSIZE);
NativeCalls.VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
return description.ToString();
}
set
{
NativeCalls.VerifySucceeded(shellLinkW.SetDescription(value));
}
}
public Tuple<string, int> IconLocation
{
get
{
// No limitation to length of buffer string in the case of Unicode though.
StringBuilder icon = new StringBuilder(NativeValues.INFOTIPSIZE);
int index;
NativeCalls.VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
return new Tuple<string, int>(icon.ToString(), index);
}
set
{
NativeCalls.VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
}
}
// AppUserModelID to be used for Windows 7 or later.
public string AppUserModelID
{
get
{
using (PropVariant pv = new PropVariant())
{
NativeCalls.VerifySucceeded(PropertyStore.GetValue(NativeValues.AppUserModelIDKey, pv));
if (pv.Value == null)
return "Null";
else
return pv.Value;
}
}
set
{
using (PropVariant pv = new PropVariant(value))
{
NativeCalls.VerifySucceeded(PropertyStore.SetValue(NativeValues.AppUserModelIDKey, pv));
NativeCalls.VerifySucceeded(PropertyStore.Commit());
}
}
}
#endregion
#region Constructor
public ShellLink()
: this(null)
{ }
// Construct with loading shortcut file.
public ShellLink(string file)
{
try
{
shellLinkW = (IShellLinkW)new CShellLink();
}
catch
{
throw new COMException("Failed to create ShellLink object.");
}
if (file != null)
Load(file);
}
#endregion
#region Destructor
~ShellLink()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (shellLinkW != null)
{
// Release all references.
Marshal.FinalReleaseComObject(shellLinkW);
shellLinkW = null;
}
}
#endregion
#region Methods
// Save shortcut file.
public void Save()
{
string file = ShortcutFile;
if (file == null)
throw new InvalidOperationException("File name is not given.");
else
Save(file);
}
public void Save(string file)
{
if (file == null)
throw new ArgumentNullException("File name is required.");
else
PersistFile.Save(file, true);
}
// Load shortcut file.
public void Load(string file)
{
if (!File.Exists(file))
throw new FileNotFoundException("File is not found.", file);
else
PersistFile.Load(file, NativeValues.STGM_READWRITE);
}
#endregion
}
}