Article View: borland.public.cppbuilder.nativeapi
Article #12415Re: Failed to resolve explorer lnk from the taskbar
From: Angus
Date: Mon, 08 Dec 2003 02:47
Date: Mon, 08 Dec 2003 02:47
258 lines
10896 bytes
10896 bytes
Hi Remy, great great code, and it all makes a lot more sense - especially
the use of stuct and the COM wrappers.
Didn't know also about not changing the exception message. Feel i'm back to
novice level.
With regard to the func itself, it still will not resolve the Internet
Explorer lnk file when opened from the taskbar (ie from the file location
C:\Documents and Settings\Administrator\Application Data\Microsoft\Internet
Explorer\Quick Launch)
I have other lnk files in this same directory, which work without a problem.
Once again my thanks, Angus.
"Remy Lebeau (TeamB)" <gambit47.no.spam@no.spam.yahoo.com> wrote in message
news:3fd2f996@newsgroups.borland.com...
>
> "Angus" <aguspickton@yahoo.com> wrote in message
> news:3fd298ae@newsgroups.borland.com...
> > But when applied to certain taskbar icons, such as
> > explorer, PathName comes out as NULL.
>
> You're going to have to be a little more specific. "explorer" could mean
> anything. Are you referring to "Windows Explorer"? "Internet Explorer"?
> "Some Other Explorer"?
>
> The issue is probably due the fact that not all desktop items are
shortcuts
> to begin with. How exactly are you determining the initial filename for
the
> desktop items and then calling the ResolveDeskTopIcon function to begin
> with? You didn't show any of that code at all.
>
> > bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR
> > pszShortcutFile,AnsiString& FileName,AnsiString& PathName,
> > AnsiString& Arguments,AnsiString& Description, WORD& Hotkey,
> > AnsiString& IconPath,AnsiString& GetWorkingDirectory,int& IconIndex,
> > int& GetShowCommand){
>
> That is a lot of parameters for a function to have. You should seriously
> consider storing the link information into a separate structure instead.
> That way, you can pass in just a single parameter for the structure
itself,
> rather than separate parameters for the individual values. Not only does
> that make the code cleaner and easier to manage, but it also is much more
> flexible should you want to add more return values later on. For example:
>
> struct TLinkInfo
> {
> AnsiString FileName;
> AnsiString PathName;
> AnsiString Arguments;
> AnsiString Description;
> AnsiString IconPath;
> AnsiString WorkingDir;
> int IconIndex;
> int ShowCommand;
> WORD Hotkey;
> };
>
> bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR pszShortcutFile,
> TListInfo &Info)
> {
> // fill in the Info parameter as needed..
> }
>
> > if(SUCCEEDED(CoInitialize(NULL))){
>
> I would suggest that you look at the TInitOle class in utilcls.h. It will
> allow you to initialize *and release* COM in a safe manner, in case an
> exception occurs your current code would have a lot of leaks.
>
> > IShellLink* psl;// Shell Link Interface
> > IPersistFile *ppf; // Interface to Shortcut
>
> For the same reason above, I would suggest you look at the TComInterface
> wrapper class in utilcls.h as well.
>
> > AnsiString FilePath(pszShortcutFile);
> > wchar_t wFilePath[MAX_PATH];
> > FilePath.WideChar(wFilePath, MAX_PATH);
>
> Rather than doing that, you could just use a WideString instead. It will
> handle the char*->wchar_t* conversion for you.
>
> > char filename[MAX_PATH];
>
> You should initialize such a buffer to MAX_PATH+1, to make sure that there
> is always room for a null-terminator even if the path happens to be
exactly
> MAX_PATH in length. Its rare, but it is possible. You should also zero
out
> the buffer contents prior to using it.
>
> > if(pidl){
> > delete pidl;
> > pidl = NULL;
> > }
>
> That is completely wrong. The ITEMIDLIST was allocated by the Shell's
> memory allocator. You can't simply 'delete' the memory, the 'delete'
> operator does not use the same memory manager as the Shell, thus the
> ITEMIDLIST memory will *not* be freed correctly. You must use
> IMalloc::Free() or CoTaskMemFree() instead in order to free the memory
> correctly.
>
> > else throw Exception("Unable to resolve lnk
filename");
>
> By throwing your own exceptions, you are leaking *all* of your interface
> instances. With the way you have your code set up, Release() will not be
> called if an exception is thrown. Either use TComInterface as I mentioned
> above, or else you must change the way you are using your exception
> handling, in order to make sure that Release() is always called no matter
> what.
>
> > ppf->Release(); // Release pointer to IPersistFile interface.
> > psl->Release(); // Release pointer to IShellLink interface.
>
> You are calling Release() on the IPersistFile instance even if the call to
> QueryInterface() fails, thus you would be calling Release() on an invalid
> pointer. You need to move that call to Release() inside the if() block
for
> the QueryInterface() result, not outside of the block.
>
> > e.Message += "Error: -(ResolveIt) mxm";
>
> I do not recommend that you *ever* alter any of the properties of an
> Exception when you catch one. Always copy the Exception's values to local
> variables and use those instead.
>
> > Application->ShowException(&e);
>
> Likewise, I would not suggest using ShowException(). It displays a
default
> message box that contains no meaninful information at all about the error.
> You should display your own message box so that you can include more
> meaningful info about why the error occured, etc.
>
> With all of that said, try this code instead:
>
> #include <utilcls.h>
> #include <shellapi.h>
>
> struct TLinkInfo
> {
> AnsiString FileName;
> AnsiString PathName;
> AnsiString Arguments;
> AnsiString Description;
> AnsiString IconPath;
> AnsiString WorkingDir;
> int IconIndex;
> int ShowCommand;
> WORD Hotkey;
> };
>
> bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR pszShortcutFile,
> TLinkInfo &Info)
> {
> // initialize defaults
> Info.FileName = "";
> Info.PathName = "";
> Info.Arguments = "";
> Info.Description = "";
> Info.IconPath = "";
> Info.WorkingDir = "";
> Info.IconIndex = -1;
> Info.ShowCommand = 0;
> Info.Hotkey = 0;
>
> try
> {
> // Before creating our CoCreatInstance, we first must
initialise
> the com library!
> TInitOle ole;
> if( !ole )
> throw Exception("Unable to initialize COM");
>
> // Get a pointer to the IShellLink interface.
> TComInterface<IShellLink> psl;
> if( FAILED(CoCreateInstance(CLSID_ShellLink, NULL,
> CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl)) )
> throw Exception("Unable to create IShellLink");
>
> // Get a pointer to the IPersistFile interface.
> TComInterface<IPersistFile> ppf;
> if( FAILED(psl->QueryInterface(IID_IPersistFile,
> (LPVOID*)&ppf)) )
> throw Exception("Unable to request IPersistFile");
>
> // use the IPersistFile::Load function to load the shortcut
> if( FAILED(ppf->Load(WideString(pszShortcutFile),
STGM_READ)) )
> throw Exception("Unable to load IShellLink");
>
> // use the IShellLink::Resolve function to resolve the link
> if( FAILED(psl->Resolve(NULL, SLR_INVOKE_MSI | SLR_NOUPDATE |
> SLR_NO_UI)) )
> throw Exception("Unable to resolve IShellLink");
>
> // get the path of the link's target
> LPITEMIDLIST pidl = NULL;
> if( SUCCEEDED(psl->GetIDList(&pidl)) )
> {
> char buf[MAX_PATH+1] = {0};
> if( SHGetPathFromIDList(pidl, buf) )
> {
> Info.PathName = buf;
> Info.FileName = ExtractFileName(Info.PathName);
> }
> CoTaskMemFree(pidl);
> }
>
> if( Info.FileName.IsEmpty() )
> throw Exception("Unable to resolve lnk filename");
>
> char desc[MAX_PATH+1] = {0};
> if( FAILED(psl->GetDescription(desc, MAX_PATH)) )
> throw Exception("Unable to resolve lnk description");
> Info.Description = desc;
>
> char args[MAX_PATH+1] = {0};
> if( FAILED(psl->GetArguments(args, MAX_PATH)) )
> throw Exception("Unable to resolve lnk Arguments");
> Info.Arguments = args;
>
> if( FAILED(psl->GetHotkey(&Info.Hotkey)) )
> throw Exception("Error:Unable to resolve lnk Hotkey");
>
> char icon[MAX_PATH+1] = {0};
> if( FAILED(psl->GetIconLocation(icon, MAX_PATH,
> &Info.IconIndex)) )
> throw Exception("Unable to resolve lnk IconLocation");
> Info.IconPath = icon;
>
> char workingdir[MAX_PATH+1] = {0};
> if( FAILED(psl->GetArguments(workingdir, MAX_PATH)) )
> throw Exception("Unable to resolve lnk IconLocation");
> Info.WorkingDir = workingdir;
>
> if( FAILED(psl->GetShowCmd(&Info.ShowCommand)) )
> throw Exception("Unable to resolve lnk IconLocation");
> }
> catch(const Exception &e)
> {
> MessageBox(hwnd, e.Message.c_str(), "Messenger", MB_OK |
> MB_ICONERROR | MB_TOPMOST);
> return false;
> }
> return true;
> }
>
>
> Gambit
>
>
Technical Details
Message-ID:
<3fd3e621@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailReferences:
<3fd298ae@newsgroups.borland.com> <3fd2f996@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 10cc67,ebe7a1f15ea83f48 X-Google-Attributes: gid10cc67,public X-Google-ArrivalTime: 2003-12-07 19:09:20 PST Reply-To: "Angus" <anguspickton@yahoo.com> From: "Angus" <aguspickton@yahoo.com> Newsgroups: borland.public.cppbuilder.nativeapi References: <3fd298ae@newsgroups.borland.com> <3fd2f996@newsgroups.borland.com> Subject: Re: Failed to resolve explorer lnk from the taskbar Date: Mon, 8 Dec 2003 15:47:04 +1300 Lines: 260 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 NNTP-Posting-Host: 203.173.216.167 Message-ID: <3fd3e621@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1070851617 203.173.216.167 (7 Dec 2003 18:46:57 -0700) Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail