Crea un collegamento sul desktop

Voglio creare un collegamento che punta a un file EXE, sul desktop, utilizzando .NET Framework 3.5 e facendo affidamento su un’API Windows ufficiale. Come lo posso fare?

Con opzioni aggiuntive come hotkey, descrizione ecc.

Inizialmente, Progetto > Aggiungi riferimento > COM > Modello object host script di Windows.

using IWshRuntimeLibrary; private void CreateShortcut() { object shDesktop = (object)"Desktop"; WshShell shell = new WshShell(); string shortcutAddress = (string)shell.SpecialFolders.Item(ref shDesktop) + @"\Notepad.lnk"; IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutAddress); shortcut.Description = "New shortcut for a Notepad"; shortcut.Hotkey = "Ctrl+Shift+N"; shortcut.TargetPath = Environment.GetFolderPath(Environment.SpecialFolders.System) + @"\notepad.exe"; shortcut.Save(); } 

scorciatoia url

 private void urlShortcutToDesktop(string linkName, string linkUrl) { string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); using (StreamWriter writer = new StreamWriter(deskDir + "\\" + linkName + ".url")) { writer.WriteLine("[InternetShortcut]"); writer.WriteLine("URL=" + linkUrl); writer.Flush(); } } 

Collegamento dell’applicazione

 private void appShortcutToDesktop(string linkName) { string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); using (StreamWriter writer = new StreamWriter(deskDir + "\\" + linkName + ".url")) { string app = System.Reflection.Assembly.GetExecutingAssembly().Location; writer.WriteLine("[InternetShortcut]"); writer.WriteLine("URL=file:///" + app); writer.WriteLine("IconIndex=0"); string icon = app.Replace('\\', '/'); writer.WriteLine("IconFile=" + icon); writer.Flush(); } } 

anche controllare questi

esempio 1 esempio2

se si desidera utilizzare alcune funzioni specifiche dell’API, sarà necessario utilizzare l’ IShellLink interface e l’ IPersistFile interface (tramite l’interoperabilità COM).

Ecco un articolo che spiega dettagliatamente cosa è necessario fare, oltre al codice di esempio:

Ecco una parte di codice che non ha alcuna dipendenza da un object COM esterno (WSH) e supporta i programmi a 32 e 64 bit:

 using System; using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Text; namespace TestShortcut { class Program { static void Main(string[] args) { IShellLink link = (IShellLink)new ShellLink(); // setup shortcut information link.SetDescription("My Description"); link.SetPath(@"c:\MyPath\MyProgram.exe"); // save it IPersistFile file = (IPersistFile)link; string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); file.Save(Path.Combine(desktopPath, "MyLink.lnk"), false); } } [ComImport] [Guid("00021401-0000-0000-C000-000000000046")] internal class ShellLink { } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214F9-0000-0000-C000-000000000046")] internal interface IShellLink { void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags); void GetIDList(out IntPtr ppidl); void SetIDList(IntPtr pidl); void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); void GetHotkey(out short pwHotkey); void SetHotkey(short wHotkey); void GetShowCmd(out int piShowCmd); void SetShowCmd(int iShowCmd); void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); void Resolve(IntPtr hwnd, int fFlags); void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); } } 

È ansible utilizzare questa class ShellLink.cs per creare il collegamento.

Per ottenere la directory del desktop, utilizzare:

 var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 

oppure utilizzare Environment.SpecialFolder.CommonDesktopDirectory per crearlo per tutti gli utenti.

Senza ulteriore riferimento:

 using System; using System.Runtime.InteropServices; public class Shortcut { private static Type m_type = Type.GetTypeFromProgID("WScript.Shell"); private static object m_shell = Activator.CreateInstance(m_type); [ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")] private interface IWshShortcut { [DispId(0)] string FullName { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0)] get; } [DispId(0x3e8)] string Arguments { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] set; } [DispId(0x3e9)] string Description { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] set; } [DispId(0x3ea)] string Hotkey { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] set; } [DispId(0x3eb)] string IconLocation { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] set; } [DispId(0x3ec)] string RelativePath { [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ec)] set; } [DispId(0x3ed)] string TargetPath { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] set; } [DispId(0x3ee)] int WindowStyle { [DispId(0x3ee)] get; [param: In] [DispId(0x3ee)] set; } [DispId(0x3ef)] string WorkingDirectory { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] set; } [TypeLibFunc((short)0x40), DispId(0x7d0)] void Load([In, MarshalAs(UnmanagedType.BStr)] string PathLink); [DispId(0x7d1)] void Save(); } public static void Create(string fileName, string targetPath, string arguments, string workingDirectory, string description, string hotkey, string iconPath) { IWshShortcut shortcut = (IWshShortcut)m_type.InvokeMember("CreateShortcut", System.Reflection.BindingFlags.InvokeMethod, null, m_shell, new object[] { fileName }); shortcut.Description = description; shortcut.Hotkey = hotkey; shortcut.TargetPath = targetPath; shortcut.WorkingDirectory = workingDirectory; shortcut.Arguments = arguments; if (!string.IsNullOrEmpty(iconPath)) shortcut.IconLocation = iconPath; shortcut.Save(); } } 

Per creare un collegamento sul desktop:

  string lnkFileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Notepad.lnk"); Shortcut.Create(lnkFileName, System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "notepad.exe"), null, null, "Open Notepad", "Ctrl+Shift+N", null); 

Uso semplicemente per la mia app:

 using IWshRuntimeLibrary; // > Ref > COM > Windows Script Host Object ... private static void CreateShortcut() { string link = Environment.GetFolderPath( Environment.SpecialFolder.Desktop ) + Path.DirectorySeparatorChar + Application.ProductName + ".lnk"; var shell = new WshShell(); var shortcut = shell.CreateShortcut( link ) as IWshShortcut; shortcut.TargetPath = Application.ExecutablePath; shortcut.WorkingDirectory = Application.StartupPath; //shortcut... shortcut.Save(); } 

Usa ShellLink.cs in vbAccelerator per creare facilmente il tuo collegamento!

 private static void AddShortCut() { using (ShellLink shortcut = new ShellLink()) { shortcut.Target = Application.ExecutablePath; shortcut.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath); shortcut.Description = "My Shorcut"; shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmNormal; shortcut.Save(SHORTCUT_FILEPATH); } } 

Ecco il mio codice:

 public static class ShortcutHelper { #region Constants ///  /// Default shortcut extension ///  public const string DEFAULT_SHORTCUT_EXTENSION = ".lnk"; private const string WSCRIPT_SHELL_NAME = "WScript.Shell"; #endregion ///  /// Create shortcut in current path. ///  /// shortcut name(include .lnk extension.) /// target path /// working path /// arguments /// hot key(ex: Ctrl+Shift+Alt+A) /// window style /// shortcut description /// icon index(start of 0) /// shortcut file path. ///  public static string CreateShortcut( string linkFileName, string targetPath, string workingDirectory = "", string arguments = "", string hotkey = "", ShortcutWindowStyles shortcutWindowStyle = ShortcutWindowStyles.WshNormalFocus, string description = "", int iconNumber = 0) { if (linkFileName.Contains(DEFAULT_SHORTCUT_EXTENSION) == false) { linkFileName = string.Format("{0}{1}", linkFileName, DEFAULT_SHORTCUT_EXTENSION); } if (File.Exists(targetPath) == false) { throw new FileNotFoundException(targetPath); } if (workingDirectory == string.Empty) { workingDirectory = Path.GetDirectoryName(targetPath); } string iconLocation = string.Format("{0},{1}", targetPath, iconNumber); if (Environment.Version.Major >= 4) { Type shellType = Type.GetTypeFromProgID(WSCRIPT_SHELL_NAME); dynamic shell = Activator.CreateInstance(shellType); dynamic shortcut = shell.CreateShortcut(linkFileName); shortcut.TargetPath = targetPath; shortcut.WorkingDirectory = workingDirectory; shortcut.Arguments = arguments; shortcut.Hotkey = hotkey; shortcut.WindowStyle = shortcutWindowStyle; shortcut.Description = description; shortcut.IconLocation = iconLocation; shortcut.Save(); } else { Type shellType = Type.GetTypeFromProgID(WSCRIPT_SHELL_NAME); object shell = Activator.CreateInstance(shellType); object shortcut = shellType.InvokeMethod("CreateShortcut", shell, linkFileName); Type shortcutType = shortcut.GetType(); shortcutType.InvokeSetMember("TargetPath", shortcut, targetPath); shortcutType.InvokeSetMember("WorkingDirectory", shortcut, workingDirectory); shortcutType.InvokeSetMember("Arguments", shortcut, arguments); shortcutType.InvokeSetMember("Hotkey", shortcut, hotkey); shortcutType.InvokeSetMember("WindowStyle", shortcut, shortcutWindowStyle); shortcutType.InvokeSetMember("Description", shortcut, description); shortcutType.InvokeSetMember("IconLocation", shortcut, iconLocation); shortcutType.InvokeMethod("Save", shortcut); } return Path.Combine(System.Windows.Forms.Application.StartupPath, linkFileName); } private static object InvokeSetMember(this Type type, string methodName, object targetInstance, params object[] arguments) { return type.InvokeMember( methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, targetInstance, arguments); } private static object InvokeMethod(this Type type, string methodName, object targetInstance, params object[] arguments) { return type.InvokeMember( methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, targetInstance, arguments); } ///  /// windows styles ///  public enum ShortcutWindowStyles { ///  /// Hide ///  WshHide = 0, ///  /// NormalFocus ///  WshNormalFocus = 1, ///  /// MinimizedFocus ///  WshMinimizedFocus = 2, ///  /// MaximizedFocus ///  WshMaximizedFocus = 3, ///  /// NormalNoFocus ///  WshNormalNoFocus = 4, ///  /// MinimizedNoFocus ///  WshMinimizedNoFocus = 6, } } 

EDIT: non consiglio più questa soluzione. Se non esiste ancora un metodo migliore rispetto all’utilizzo del motore di scripting di Windows, almeno utilizza la soluzione di @ Mehmet che chiama direttamente il motore anziché creare uno script di testo in chiaro.

Abbiamo usato VBScript per generare un collegamento. Non ha bisogno di p / Invoke, COM Interop e DLL aggiuntive. Funziona così:

  • Genera un VBScript in fase di runtime con i parametri specificati del metodo C # di CreateShortcut
  • Salva questo VBScript in un file temporaneo
  • Aspetta che lo script finisca
  • Elimina il file temporaneo

Ecco qui:

 static string _scriptTempFilename; ///  /// Creates a shortcut at the specified path with the given target and /// arguments. ///  /// The path where the shortcut will be created. This should /// be a file with the LNK extension. /// The target of the shortcut, eg the program or file /// or folder which will be opened. /// The additional command line arguments passed to the /// target. public static void CreateShortcut(string path, string target, string arguments) { // Check if link path ends with LNK or URL string extension = Path.GetExtension(path).ToUpper(); if (extension != ".LNK" && extension != ".URL") { throw new ArgumentException("The path of the shortcut must have the extension .lnk or .url."); } // Get temporary file name with correct extension _scriptTempFilename = Path.GetTempFileName(); File.Move(_scriptTempFilename, _scriptTempFilename += ".vbs"); // Generate script and write it in the temporary file File.WriteAllText(_scriptTempFilename, String.Format(@"Dim WSHShell Set WSHShell = WScript.CreateObject({0}WScript.Shell{0}) Dim Shortcut Set Shortcut = WSHShell.CreateShortcut({0}{1}{0}) Shortcut.TargetPath = {0}{2}{0} Shortcut.WorkingDirectory = {0}{3}{0} Shortcut.Arguments = {0}{4}{0} Shortcut.Save", "\"", path, target, Path.GetDirectoryName(target), arguments), Encoding.Unicode); // Run the script and delete it after it has finished Process process = new Process(); process.StartInfo.FileName = _scriptTempFilename; process.Start(); process.WaitForExit(); File.Delete(_scriptTempFilename); } 

Uso il riferimento “Modello object host Windows Script” per creare collegamenti.

Aggiunta di

e per creare un collegamento in una posizione specifica:

  void CreateShortcut(string linkPath, string filename) { // Create shortcut dir if not exists if (!Directory.Exists(linkPath)) Directory.CreateDirectory(linkPath); // shortcut file name string linkName = Path.ChangeExtension(Path.GetFileName(filename), ".lnk"); // COM object instance/props IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); IWshRuntimeLibrary.IWshShortcut sc = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(linkName); sc.Description = "some desc"; //shortcut.IconLocation = @"C:\..."; sc.TargetPath = linkPath; // save shortcut to target sc.Save(); } 

Ecco un metodo di estensione (testato), con commenti per aiutarti.

 using IWshRuntimeLibrary; using System; namespace Extensions { public static class XShortCut { ///  /// Creates a shortcut in the startup folder from a exe as found in the current directory. ///  /// The exe name eg test.exe as found in the current directory /// The shortcut's "Start In" folder /// The shortcut's description /// The folder path where created public static string CreateShortCutInStartUpFolder(string exeName, string startIn, string description) { var startupFolderPath = Environment.SpecialFolder.Startup.GetFolderPath(); var linkPath = startupFolderPath + @"\" + exeName + "-Shortcut.lnk"; var targetPath = Environment.CurrentDirectory + @"\" + exeName; XFile.Delete(linkPath); Create(linkPath, targetPath, startIn, description); return startupFolderPath; } ///  /// Create a shortcut ///  /// the full path to the shortcut to be created /// the full path to the exe to 'really execute' /// Start in this folder /// Description for the link public static void Create(string fullPathToLink, string fullPathToTargetExe, string startIn, string description) { var shell = new WshShell(); var link = (IWshShortcut)shell.CreateShortcut(fullPathToLink); link.IconLocation = fullPathToTargetExe; link.TargetPath = fullPathToTargetExe; link.Description = description; link.WorkingDirectory = startIn; link.Save(); } } } 

E un esempio di utilizzo:

 XShortCut.CreateShortCutInStartUpFolder(THEEXENAME, Environment.CurrentDirectory, "Starts some executable in the current directory of application"); 

1st parm imposta il nome exe (che si trova nella directory corrente) 2nd parm è la cartella “Start In” e 3rd parm è la descrizione del collegamento.

Esempio di utilizzo di questo codice

La convenzione di denominazione del collegamento non lascia ambiguità su ciò che farà. Per testare il collegamento basta fare doppio clic su di esso.

Nota finale: l’applicazione stessa (objective) deve avere un’immagine ICON associata ad essa. Il collegamento è facilmente in grado di individuare l’icona all’interno dell’exe. Se l’applicazione di destinazione ha più di un’icona, è ansible aprire le proprietà del collegamento e modificare l’icona in qualsiasi altra trovata nell’exe.