Solved

Getting Target Path from a Shortcut (.lnk file)

Posted on 2000-02-22
13
1,205 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
  • 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
 
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

895 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now