Solved

Getting Target Path from a Shortcut (.lnk file)

Posted on 2000-02-22
13
1,300 Views
Last Modified: 2010-04-04
Ive found plenty of sources for creating a shortcut.  But how do i read a shortcut and get its target path?

I want to use this feature in a Directory tree, so that when a shortcut is double clicked it takes you to its target.
0
Comment
Question by:SpannerBracket
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 3
13 Comments
 
LVL 17

Accepted Solution

by:
inthe earned 50 total points
ID: 2548200
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls,shlobj,activex,comobj,commctrl,menus;

type
  TForm1 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }
  end;

var
  Form1: TForm1;
   NeedToUninitialize : boolean = false;
implementation

{$R *.DFM}

function LoadShellLink(shellLinkFile: string;
                       var description, linkedObj, params: string;
                       var pidl: PItemIDList; var findData: TWin32FindData;
                       var iconPath: string; var iconIndex: integer;
                       var workingDir, hotKey: string;
                       var showCmd: integer) : boolean;
var sl  : IShellLink;
    w1  : word;
    s1  : string;
    wfd : TWin32FindData;
    i1  : integer;
begin
  NeedToUninitialize:=NeedToUninitialize or succeeded(CoInitialize(nil));
  sl:=CreateComObject(CLSID_ShellLink) as IShellLink;
  result:=(sl as IPersistFile).Load(PWideChar(wideString(ShellLinkFile)),0)=S_OK;
  if not result then exit;
  SetLength(description,MAX_PATH+1);
  if sl.GetDescription(PChar(description),MAX_PATH)=NOERROR then description:=string(PChar(description))
  else                                                           description:='';
  SetLength(s1,MAX_PATH+1);
  if sl.GetPath(PChar(s1),MAX_PATH,wfd,0)=NOERROR then begin
    linkedObj:=string(PChar(s1));
    findData :=wfd;
  end else begin
    linkedObj:='';
    ZeroMemory(@findData,sizeOf(TWin32FindData));
  end;
  SetLength(params,MAX_PATH+1);
  if sl.GetArguments(PChar(params),MAX_PATH)=NOERROR then params:=string(PChar(params))
  else                                                    params:='';
  if sl.GetIDList(pidl)<>NOERROR then pidl:=nil;
  SetLength(s1,MAX_PATH+1);
  if sl.GetIconLocation(pchar(s1),MAX_PATH,i1)=NOERROR then begin
    iconPath :=string(pchar(s1));
    iconIndex:=i1;
  end else begin
    iconPath :='';
    iconIndex:=-1;
  end;
  SetLength(workingDir,MAX_PATH+1);
  if sl.GetWorkingDirectory(PChar(workingDir),MAX_PATH)=NOERROR then workingDir:=string(PChar(workingDir))
  else                                                               workingDir:='';
  sl.GetHotKey(w1);
  if w1 and (HOTKEYF_ALT     shl 8)<>0 then w1:=(w1 and (not (HOTKEYF_ALT     shl 8))) or scAlt;
  if w1 and (HOTKEYF_CONTROL shl 8)<>0 then w1:=(w1 and (not (HOTKEYF_CONTROL shl 8))) or scCtrl;
  if w1 and (HOTKEYF_SHIFT   shl 8)<>0 then w1:=(w1 and (not (HOTKEYF_SHIFT   shl 8))) or scShift;
  hotKey:=ShortCutToText(w1);
  if sl.GetShowCmd(showCmd)<>NOERROR then showCmd:=-1;
end;

procedure FreePidl(var pidl: PItemIDList);
var malloc : IMalloc;
begin
  if (pidl<>nil) and (SHGetMalloc(malloc)=NOERROR) then begin
    malloc.Free(pidl);
    pidl:=nil;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  pi:PItemIDList;
  s1,Desc,s2:String;
  icon,workdir,htkey:string;
  Data: TWin32FindData;
  i,ii : integer;
begin
  opendialog1.execute;
  loadshelllink(opendialog1.filename,desc,s1,s2,pi,Data,icon,i,workdir,htkey,ii);
  ShowMessage('File ShortCut : '+opendialog1.filename+#13#10+'File TruePath : '+s1+#13#10+'Working Dir : '+workdir+#13#10
              +'HotKey : '+htkey+#13#10+'Show Command : '+inttostr(ii));
 FreePidl(pi);
end;


initialization
finalization
  if NeedToUninitialize then CoUninitialize;

end.
0
 
LVL 17

Expert Comment

by:inthe
ID: 2548206
Hi
above is an example of reading .lnk files and all the info they can hold ,including hotkeys etc ..

Regards Barry
0
 
LVL 1

Author Comment

by:SpannerBracket
ID: 2550162
Ive had a play with the code.. and i couldn't get this to work. No matter what i did (and yeah, i did try the code exactly as it was above =).

It wouldn't return any data apart from the shortcut path (im not really interested in any other data though), but then this is just got from using the OpenDialog1.Filename.

If i just create a form, and stick in an OpenDialog i can get the shortcut target from that method, but that defeats the point of what im trying to do.

I presume the code worked for you.. any idea what i might be doing wrong?

Cheers
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 17

Expert Comment

by:inthe
ID: 2550237
im just on way to work but should only be for 3-4 hours then i test this when come home.
yes it did work i remember we spent ages trying to get it right.

leave a comment saying which parts you want to get.
ie only the file name/path the link points to or do you want any other info?
oh and what version of delphi you use.
0
 
LVL 1

Expert Comment

by:duke_n
ID: 2550458
I had a component that does it somewhere(src included). If ye want, I'll be  sending it to ye.
0
 
LVL 1

Author Comment

by:SpannerBracket
ID: 2551914
Yeah, it was just the path the link points to that i was needing, and im on Delphi 4 =)

Duke, that would be great (err, being new to this experts.. and stuff, do i need to give you my email addy?).
0
 
LVL 1

Expert Comment

by:duke_n
ID: 2552027
well, how else would I send it to ya?
0
 
LVL 1

Author Comment

by:SpannerBracket
ID: 2552451
Dunno... haven't explored Experts-Exchange properly yet, thought you might be able to get it from there... maybe not =)

spannerbracket@crosswinds.net
0
 
LVL 17

Expert Comment

by:inthe
ID: 2552961
hello ,
 sorry im late (for a change ;-)

i also use this in d4 and no probs can i ask what was problem?

try this instead:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls,shlobj,activex,comobj;

type
  TForm1 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
   procedure GetLinkInfo(ALnk: String;
       var AFile, APath, AWork: String);
    public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.GetLinkInfo(ALnk: String;
                             var AFile, APath, AWork: String);
const
  IID_IPersistFile: TGUID = (D1:$0000010B;
                             D2:$0000;
                             D3:$0000;
                             D4:($C0,$00,$00,$00,$00,$00,$00,$46));
  MB_ERR_INVALID_CHARS = $00000008;
var
  fShellLink   : IShellLink;
  fPersistFile : IPersistFile;
  fFindData    : TWin32FindData;
  fWideBuf     : array[0..MAX_PATH] of WideChar;
  fBuf         : array[0..MAX_PATH] of Char;
  hResx        : hResult;
  WideLen      : Integer;
begin
  hResx := CoCreateInstance(
  CLSID_ShellLink,nil,CLSCTX_INPROC_SERVER,IID_IShellLinkA,fShellLink);
  if SUCCEEDED(hResx) then
  begin
    hResx := fShellLink.QueryInterface(IID_IPersistFile,fPersistFile);
    if SUCCEEDED(hResx) then
    begin
      WideLen := MultiByteToWideChar(CP_ACP,
                                     MB_ERR_INVALID_CHARS,
                                     pChar(ALnk),
                                     Length(ALnk),
                                     @fWideBuf,
                                     MAX_PATH);
      if WideLen = 0 then
      begin
        ShowMessage('MultiByteToWideChar FAILED');
        Exit;
      end;
      fWideBuf[WideLen] := #0;
      hResx := fPersistFile.Load(@fWideBuf,
                                 STGM_READ or
                                 STGM_SHARE_DENY_NONE);
      if SUCCEEDED(hResx) then
      begin
        fShellLink.GetPath(@fBuf,
                           MAX_PATH,
                           fFindData,
                           0);
        AFile := fFindData.cFileName;
        APath := StrPas(fBuf);
        fShellLink.GetWorkingDirectory(@fBuf,Max_Path);
        AWork := StrPas(fBuf);
      end;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  s1,s2,s3:String;
begin
  //opendialog1.execute;
  //GetLinkInfo(opendialog1.filename,s1,s2,s3);
  GetLinkInfo('c:\windows\start menu\programs\windows explorer.lnk',s1,s2,s3);
  ShowMessage(s2);
end;

end.



btw duke_n.
that component sounds interesting ;-)

BorgsAsimilate@Aol.Com


0
 
LVL 1

Author Comment

by:SpannerBracket
ID: 2554117
Aha.. works fine now.

Maybe i was doing something stupid before, but no matter what shortcut i gave it it would return no info, no error either.

You can find a ShellLink component on delphi.icm.edu.pl . Do a search for shortcut selecting Delphi 4.

Im using the component now for the simplicity of it, but thanks for going to the trouble of posting source, ill keep it as a reference if i ever get into delphi that deep =)

Cheers again,
0
 
LVL 1

Author Comment

by:SpannerBracket
ID: 2554120
Ooops.. probably misleading, i've selected the wrong source as the answer, the second bit of source worked for me =)
0
 
LVL 1

Expert Comment

by:duke_n
ID: 2555260
Inthe, I coulndn't send an email to ye...:

Your e-mail is being returned to you because there was a problem with its
delivery.  The AOL address which was undeliverable is listed in the section
labeled: "----- The following addresses had permanent fatal errors -----".

{blablabla}

   ----- The following addresses had permanent fatal errors -----
<BorgsAsimilate@Aol.Com>
{blablabla}

sorry, muchacho
0
 
LVL 17

Expert Comment

by:inthe
ID: 2555607
hi thanks SpannerBracket ;-)

duke_n i miss and "s" sorry it should be either:

BorgsAssimilate@Aol.Com
or
Legend@Enterprise.Net
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
Suggested Courses
Course of the Month3 days, 23 hours left to enroll

630 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question