有谁知道如何纠正这种行为?
目前,当我们的安装程序安装我们的应用程序时,它会获得 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 。“)
答案 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;
}
}