6

I'm using IWshRuntimeLibrary to create shortcut with c#. the shortcut file name is in Hindi "नमस्ते".

I'm using following code my snip to create shortcut, where shortcutName = "नमस्ते.lnk"

 WshShellClass wshShell = new WshShellClass();
 IWshRuntimeLibrary.IWshShortcut shortcut;

shortcut = (IWshRuntimeLibrary.IWshShortcut)wshShell.CreateShortcut(destPath + "\\" + shortcutName);

 shortcut.TargetPath = sourcePath;
 shortcut.Save();

on shortcut.Save() I'm getting following exception.

The filename, directory name, or volume label syntax is incorrect. (Exception from HRESULT: 0x8007007B)
kmatyaszek
  • 19,016
  • 9
  • 60
  • 65
Naresh
  • 785
  • 1
  • 11
  • 23

1 Answers1

8

You can tell what goes wrong with the debugger. Inspect "shortcut" in the debugger and note that your Hindi name has been replaced by question marks. Which produces an invalid filename and triggers the exception.

You are using an ancient scripting support library that's just not capable of handling the string. You'll need to use something more up-to-date. Project + Add Reference, Browse tab and select c:\windows\system32\shell32.dll. That adds the Shell32 namespace to your project with a few interfaces to do shell related work. Just enough to get this going, the ShellLinkObject interface lets you modify properties of a .lnk file. One trick is needed, it doesn't have the ability to create a new .lnk file from scratch. You solve that by creating an empty .lnk file. This worked well:

    string destPath = @"c:\temp";
    string shortcutName = @"नमस्ते.lnk";

    // Create empty .lnk file
    string path = System.IO.Path.Combine(destPath, shortcutName);
    System.IO.File.WriteAllBytes(path, new byte[0]);
    // Create a ShellLinkObject that references the .lnk file
    Shell32.Shell shl = new Shell32.Shell();
    Shell32.Folder dir = shl.NameSpace(destPath);
    Shell32.FolderItem itm = dir.Items().Item(shortcutName);
    Shell32.ShellLinkObject lnk = (Shell32.ShellLinkObject)itm.GetLink;
    // Set the .lnk file properties
    lnk.Path = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\notepad.exe";
    lnk.Description = "nobugz was here";
    lnk.Arguments = "sample.txt";
    lnk.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    lnk.Save(path);
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    This thing worked, one change rather referencing Shell32.dll from file system, go to COM tab of the "Add ref..." dialog and select the component named "Microsoft Shell Controls And Automation" – Naresh Nov 26 '12 at 13:36
  • Makes no difference, the Browse tab just makes it easier to find the file. – Hans Passant Nov 26 '12 at 13:46
  • But I think adding COM component makes it device independent. Not all users may have c:\ as their primary disk. – Naresh Nov 28 '12 at 06:00
  • 1
    No, shell32.dll is part of the operating system and available on every machine. Just like the IWshRuntimeLibrary provider. Nor do you ever refer to c:\ in your code. – Hans Passant Nov 28 '12 at 08:19
  • @HansPassant What if `destPath` was not created? Kaboom! Line: `System.IO.File.WriteAllBytes(path, new byte[0]);` fails with `System.IO.DirectoryNotFoundException`. So before that line I suggest: `if (!System.IO.Directory.Exists(destPath)) System.IO.Directory.CreateDirectory(destPath);` – Simple Aug 17 '22 at 20:31
  • @Naresh Also note that `Shell32` requires `STAThread` so make sure you run it from an `STAThread` otherwise an exception is thrown. If you're using `WinForms` and run the `Shell32` code from a non `STAThread` so the `Invoke` method solves the problem, since it will run from the UI Thread which should be `STAThread`. – Simple Aug 18 '22 at 21:56
  • @Naresh Beware! This solution may not work on some versions of Windows such as Win7, the `Interop.Shell32.1.0.dll` generated by `VS` will not be compatible with and will throw the following: `System.InvalidCastException: Unable to cast COM object of type 'Shell32.ShellCass' to interface type 'Shell32.IShellDispatch6'.` A workaround for that is replace it by an `Interop.Shell32.dll` of version 1.2.107.0. You need to reference that version too, looks like the version 1.0 is too old and does not work properly on diff OS. – Simple Aug 19 '22 at 17:02
  • @HansPassant Can you update your answer with the concerns I mentioned above? Or provide a more reliable solution? – Simple Aug 19 '22 at 17:10