Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Getting Target Path from a Shortcut (.lnk file)

Posted on 2000-02-22
13
Medium Priority
?
1,343 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 200 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

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

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

661 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