6

この動作を修正する方法を知っている人はいますか?

現在、インストーラーがアプリケーションをインストールすると、IShellLinkが取得され、ショートカット アイコン (スタート メニューとデスクトップ) に必要なデータが読み込まれ、IPersistFile::Saveを使用してショートカットが書き出されます。

問題は、 IShellLink::SetIconLocationを介してアイコンに指定されたパスが%ProgramFiles%を使用するように変換されることです... x64 の場合、間違っています。

他の多くの 32 ビット ソフトウェアでは、x64 でこれが失敗することに気付きましたが、%ProgamFiles%自体を .lnk 作成コードのリテラル要素として使用していると想定しました。ただし、IShellLinkがこのバグを強制的に存在させているようで、回避策がありません (または、シェルのリンク プロパティ エディターが問題の原因であり、基になるリンクは問題ない可能性があります)。

いくつかのGoogle検索では何も見つかりませんでした...他の誰かがこれに遭遇したか、記事を知っていますか/x64ウィンドウがこれを台無しにしないようにする方法の例を知っていますか?

明確な例:

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

正しいアイコンを持つショートカットが作成されますが、ショートカットのプロパティ ページで [アイコンの変更] を押すと、「Windows はファイル %ProgramFiles%\Acme\Prog.exe を見つけることができません」と報告されます。)

4

3 に答える 3

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 に答える
3

ユーザー「pointoforder」が GitHubのこの問題レポートで指摘しているように、別の修正として、SLDF_HAS_EXP_ICON_SZフラグの設定を解除EXP_SZ_ICON_SIGし、オブジェクトからデータ ブロックを削除しIShellLinkDataListます。このコメントには、対応する Delphi コード スニペットがあります。

于 2012-11-13T09:25:31.937 に答える
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 に答える