Solved

Getting Target Path from a Shortcut (.lnk file)

Posted on 2000-02-22
13
1,181 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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
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 Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

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…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

743 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