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.GetDescription(description, description.Capacity)); return description.ToString(); } set { NativeCalls.VerifySucceeded(shellLinkW.SetDescription(value)); } } public string WorkingDirectory { get { // No limitation to length of buffer string in the case of Unicode though. StringBuilder workingDirectory = new StringBuilder(NativeValues.INFOTIPSIZE); NativeCalls.VerifySucceeded(shellLinkW.GetWorkingDirectory(workingDirectory, workingDirectory.Capacity)); return workingDirectory.ToString(); } set { NativeCalls.VerifySucceeded(shellLinkW.SetWorkingDirectory(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 } }