创建具有依赖项的应用程序快捷方式

Create shortcut of application with dependencies

我正在尝试让我的应用程序在桌面上创建一个快捷方式。原因是因为我的应用程序有一些依赖项,例如外部 dll 和其他,我更喜欢将它放在一个文件夹中,并且只是在我的桌面上有一个快捷方式,而不是将所有文件都放在我的桌面上或一个包含所有内容的文件夹中。

这是我第一次尝试这个。我相信这很简单,如果我的问题有点笨拙,我真的很抱歉。 我的简单代码如下所示:

string checkDesktopDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
if (!File.Exists(checkDesktopDir + "\My app.url"))
    {
        ShortCutWithDependencies("My app");
    }   
private void ShortCutWithDependencies(string sAppName)
    {
        string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

        using (StreamWriter writer = new StreamWriter(deskDir + "\" + sAppName + ".url"))
        {
            string app = Assembly.GetExecutingAssembly().Location;
            MessageBox.Show(app);
            writer.WriteLine("[InternetShortcut]");
            writer.WriteLine("URL=" + app);
            writer.WriteLine("IconIndex=0");
            string icon = app.Replace('\', '/');
            writer.WriteLine("IconFile=" + icon);
            writer.Flush();
        }
    }

但是我的应用程序永远无法运行。一旦到达需要依赖项才能继续的部分,它就会崩溃。更具体地说,当我使用通过 DLLImport 导入的方法时,例如 bass.dll 方法,它只会崩溃。当然,我在输出中看不到任何内容,因为快捷方式是已编译的 .exe。

所以我的问题是这样的;如何创建我的应用程序的完整快捷方式?

编辑:更新 dllimport 示例

        [DllImport("bass.dll")]
        public static extern bool BASS_Start();
        [DllImport("bass.dll")]
        public static extern bool BASS_Init(int device, uint freq, uint flag,
             IntPtr hParent, uint guid);

        if (mp3ToPlay != string.Empty)
                            {
                                BASS_Start();
                                BASS_Init(-1, 44100, 0, IntPtr.Zero, 0);
                                BassHandle = BASS_StreamCreateFile(false, mp3ToPlay, 0, 0, 0x20000);
                                BASS_ChannelPlay(BassHandle, false);
                                PlayBackLength = BASS_ChannelGetLength(BassHandle, 0);
                                PlayBack = true;
                            }

现在我相信这就是问题所在。不过我不确定。外部 dll(bass.dll、Newtonsoft.Json.dll 和 Spotify.dll)已将 Copy to output directory 设置为 Copy always 并被复制。 .exe 将 运行 正常,手动创建并发送到桌面的快捷方式也将 运行 正常。

编辑:使用 Federico 的示例更新 2 现在这将起作用:

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

但是这里有一个小故障。 我的这部分代码

public string mp3Path = Directory.GetCurrentDirectory() + "\mp3Directory";

if (!System.IO.File.Exists(mp3Path))
            {
                Directory.CreateDirectory(mp3Path);
            }

将其更改为 AppDomain.CurrentDomain.BaseDirectory 即可轻松修复。

尝试使用本机 COM Windows API 创建快捷方式,如以下答案中所述:

At first, Project > Add Reference > COM > Windows Script Host Object Model.

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();
}

[编辑 1] Directory.GetCurrentDirectory() 问题后更新:

来自documentationThe current directory is distinct from the original directory, which is the one from which the process was started.

您预期的目录与 Directory.GetCurrentDirectory() 返回的目录不同,因为当您使用快捷方式(您的桌面)时,您实际上是从不同的目录启动您的进程。 Directory.GetCurrentDirectory() returns 当前 working 目录,如果您通过打开 .exe 文件启动程序集,它与您的程序集相同,但如果您是快捷方式目录从 .lnk 文件启动它。

在您的场景中,我会使用 Assembly.GetExecutingAssembly().Location(查看此答案以获取更多信息:)

如果我没理解错的话,听起来您最好还是为您的应用程序制作一个安装程序。您可以通过 Visual Studio 执行此操作,它几乎可以为您自动完成该过程。此外,您可以尝试使您的程序成为具有依赖项的 ClickOnce 应用程序。我个人会选择后者。

我知道这不是一个特别彻底的答案,但我觉得这个问题有点不清楚。