6

有谁知道如何纠正这种行为?

目前,当我们的安装程序安装我们的应用程序时,它会获得一个IShellLink,然后使用我们的快捷方式图标(在开始菜单和桌面中)所需的数据加载它,然后使用IPersistFile::Save写出快捷方式。

问题是通过IShellLink::SetIconLocation为图标指定的路径被转换为使用%ProgramFiles%...这...对于 x64,是错误的。

我注意到许多其他 32 位软件在 x64 下都失败了 - 但后来我假设他们自己使用%ProgamFiles%作为 .lnk 创建代码中的文字元素。但是,似乎是IShellLink迫使此错误存在,并且我没有解决方法(或者可能是 shell 中的链接属性编辑器负责该问题并且底层链接正常)。

一些谷歌搜索没有任何结果......有没有其他人遇到过这个或知道如何强制 x64 窗口不搞砸的文章/示例?

澄清示例:

hr = m_shell_link->SetIconLocation("C:\\Program Files (x86)\\Acme\\Prog.exe", 0);

将产生一个具有正确图标的快捷方式,但是当您在快捷方式属性页面中按“更改图标”时,将报告“Windows 找不到文件 %ProgramFiles%\Acme\Prog.exe”。)

4

3 回答 3

3

将名称转换为短文件名,它只会转换驱动器号,但保持正确的路径。

        PWCHAR pIcon = L"C:\\Program Files (x86)\\Myfoo\\Bar.exe";
        DWORD dwLen = GetShortPathName(pIcon, NULL, 0);
        PWCHAR pShort = NULL; 
        if (dwLen) {
            pShort = new WCHAR[dwLen];
            dwLen = GetShortPathName(pIcon, pShort, dwLen);
            if (!dwLen) {
                delete [] pShort;
                pShort = NULL;
            }
        }

        if (NULL == pShort) {
            psl->SetIconLocation(pIcon,iTmp);
        } else {
            psl->SetIconLocation(pShort,iTmp);
        }
        delete [] pShort;
于 2011-06-02T04:30:38.937 回答
3

正如用户“pointoforder”在 GitHub 上的此问题报告中指出的那样,另一个修复方法是取消设置SLDF_HAS_EXP_ICON_SZ标志并从对象中删除EXP_SZ_ICON_SIG数据块。此评论具有相应的 Delphi 代码片段。IShellLinkDataList

于 2012-11-13T09:25:31.937 回答
3

当我在寻找在 C# 中创建快捷方式的解决方案时,我在 StackOverflow 上找到了这篇文章。

现在我遇到了这个线程中描述的问题。我不确定在哪里发布我的解决方案,但我想这是正确的地方。

我添加了 IShellLinkDataList 并更改了 Save() 方法,如下所示:

#region IShellLinkDataList Interface
[ComImportAttribute()]
[GuidAttribute("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellLinkDataList
{
    void AddDataBlock(IntPtr pDataBlock);
    void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
    void RemoveDataBlock(uint dwSig);
    void GetFlags(out uint pdwFlags);
    void SetFlags(uint dwFlags);
}
#endregion

private const uint SLDF_HAS_EXP_ICON_SZ = 0x00004000;
private const uint EXP_SZ_ICON_SIG = 0xA0000007;

public void Save(string linkFile)
{   
    // Save the object to disk
    uint flags;
    if (linkA == null)
    {
        ((IShellLinkDataList)linkW).GetFlags(out flags);
        flags = flags & ~SLDF_HAS_EXP_ICON_SZ;
        ((IShellLinkDataList)linkW).SetFlags(flags);
        ((IShellLinkDataList)linkW).RemoveDataBlock(EXP_SZ_ICON_SIG);
        ((IPersistFile)linkW).Save(linkFile, true);
        shortcutFile = linkFile;
    }
    else
    {
        ((IShellLinkDataList)linkA).GetFlags(out flags);
        flags = flags & ~SLDF_HAS_EXP_ICON_SZ;
        ((IShellLinkDataList)linkA).SetFlags(flags);
        ((IShellLinkDataList)linkA).RemoveDataBlock(EXP_SZ_ICON_SIG);
        ((IPersistFile)linkA).Save(linkFile, true);
        shortcutFile = linkFile;
    }
}
于 2016-09-02T00:55:58.980 回答