How to get targetPath, workingDir information from microsoft office shotcuts(eg. Word 2013.lnk)

886 Views Asked by At

Tried using IShellLink COM interface to get the information of .LNK files. It works fine for many application shorcuts But for Microsoft Office application shortcuts It doesn't provide correct information For instance:

while reading ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Word 2013.lnk

IShellLink::GetPath returns "C:\Windows\Installer{90150000-0011-0000-0000-0000000FF1CE}\wordicon.exe"

not C:\Program Files (x86)\Microsoft Office\Office15\WINWORD.exe

Is there any way to get the target information from such .lnk files. which windows uses to launch the application when double clicking the shorcut.

@Denis

Here is the C++ code i tried

IShellLinkDataList* comShellLinkDataList;
if (SUCCEEDED(psl->QueryInterface(IID_IShellLinkDataList,(void**)&comShellLinkDataList)))
{
    DWORD flags = 0;
    if (SUCCEEDED(comShellLinkDataList->GetFlags(&flags)))
    {
        if (flags & SLDF_HAS_DARWINID)
        {
            PIDLIST_ABSOLUTE pidList;
            if (SUCCEEDED(psl->GetIDList(&pidList)))
            {
                IShellFolder* shellFolder;
                PCITEMID_CHILD childItem;
                if (SUCCEEDED(SHBindToParent(pidList, IID_IShellFolder, (void**)&shellFolder, &childItem)))
                {
                    STRRET strRet;
                    if (SUCCEEDED(shellFolder->GetDisplayNameOf(childItem, SHGDN_NORMAL | SHGDN_FORPARSING, &strRet)))
                    {
                        TCHAR path[MAX_PATH] = {0};
                        if (SUCCEEDED(StrRetToBuf(&strRet, childItem, path, MAX_PATH)))
                        {
                            return path;
                        }
                    }                                    
                }                                
            }

        }
    }  
}
1

There are 1 best solutions below

3
On
function GetExeNameFromShellLink(AShellLink: IShellLink): UnicodeString;
var List: IShellLinkDataList;
    Flags: DWORD;
    IDList: PItemIDList;
    ShellFolder: IShellFolder;
    ChildItem: PItemIDList;
    Attr: DWORD;
    StrRet: TStrRet;
begin
  if Succeeded(AShellLink.QueryInterface(IShellLinkDataList, List)) then
    try
      if Succeeded(List.GetFlags(Flags)) and (Flags and SLDF_HAS_DARWINID <> 0) then
        AShellLink.Resolve(0, SLR_INVOKE_MSI);
    finally
      List := nil;
    end;
  OleCheck(AShellLink.GetIDList(IDList));
  try
    OleCheck(SHBindToParent(IDList, IShellFolder, Pointer(ShellFolder), ChildItem));
    try
      OleCheck(ShellFolder.GetDisplayNameOf(ChildItem, SHGDN_NORMAL or SHGDN_FORPARSING, StrRet));
      case StrRet.uType of
        STRRET_WSTR:
          begin
            Result := StrRet.pOleStr;
            CoTaskMemFree(StrRet.pOleStr);
          end;
        STRRET_OFFSET:
          begin
            Inc(PByte(ChildItem), StrRet.uOffset);
            Result := UnicodeString(PAnsiChar(ChildItem));
          end;
        STRRET_CSTR:
          Result := UnicodeString(AnsiString(StrRet.cStr));
      else
        Result := '';
      end;
    finally
      ShellFolder := nil;
    end;
  finally
    CoTaskMemFree(IDList);
  end;
end;