代码之家  ›  专栏  ›  技术社区  ›  Mordachai

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

  •  4
  • Mordachai  · 技术社区  · 14 年前

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

    目前,当安装程序安装我们的应用程序时,它会获得 伊希林 ,然后使用快捷方式图标所需的数据加载它(在“开始”菜单和桌面中),然后使用 IPersistFile::保存 写下快捷方式。

    问题是为图标指定的路径,通过 IShellLink::设置图标位置 ,转化为使用 %程序文件百分比… 哪个…对于x64,是错误的。

    我注意到许多其他的32位软件在X64下都会出现这种故障,但后来我假设它们正在使用 %PrimaFix% 它们自己的.lnk创建代码中的一个文本元素。然而,似乎是 伊希林 正迫使这个bug存在,而我没有解决方法(或者可能是shell中的链接属性编辑器负责这个问题,并且底层链接正常)。

    一些谷歌搜索没有发现任何东西…是否有其他人遇到过这种情况或知道如何强制x64窗口不弄脏它的文章/示例?

    澄清示例:

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

    将生成具有正确图标的快捷方式,但当您在快捷方式属性页中按“更改图标”时,将报告 “Windows找不到文件%programfiles%\acme\prog.exe。” )

    3 回复  |  直到 8 年前
        1
  •  3
  •   Benj    10 年前

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

            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;
    
        2
  •  2
  •   sschuberth    12 年前

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

        3
  •  1
  •   Community Mr_and_Mrs_D    7 年前

    当我在寻找在C中创建快捷方式的解决方案时,我发现 this post 在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;
        }
    }