IShellLink :: SetIconLocation将我的图标路径转换为错误的%Program Files%

时间:2010-06-04 17:44:00

标签: c++ windows-shell

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

目前,当我们的安装程序安装我们的应用程序时,它会获得 IShellLink ,然后使用我们的快捷方式图标(在开始菜单和桌面中)所需的数据加载它,然后使用< strong> 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 。“

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:2)

正如用户“pointoforder”在此issue report on GitHub中指出的,另一个解决方法是取消设置SLDF_HAS_EXP_ICON_SZ标志并从EXP_SZ_ICON_SIG对象中删除IShellLinkDataList数据块。 This comment具有相应的Delphi代码片段。

答案 2 :(得分:1)

当我在C#中寻找创建快捷方式的解决方案时,我在StackOverflow上找到了this post

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

我添加了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;
    }
}