Introduction
ShortCut is a .NET class that allows you to create shortcuts to files as
well as resolve existing shortcuts. The class was coded in Managed C++ and
makes ample use of IJW. I have compiled the class as a Class Library under the
namespace ShortCutLib. Thus you can now use it from your C# and VB .NET
programs. Simply add a reference to the DLL. This is yet another example of how
Managed C++ eases the transition between managed and unmanaged code so easily.
It just works!
Sample Usage [C#]
using System;
using ShortCutLib;
namespace ShortCutTest
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
ShortCut sc = new ShortCut();
sc.FilePath = "C:\\windows\\notepad.exe";
sc.LnkPath = "c:\\abc.lnk";
sc.LnkDesc = "This runs notepad";
sc.WorkDir = "C:\\";
sc.CreateLink();
//Resolving a shortcut
sc.LnkPath = "C:\\xyz.lnk";
sc.ResolveLink();
Console.WriteLine("File is {0}",sc.FilePath);
Console.WriteLine("Description is {0}",sc.LnkDesc);
Console.WriteLine("Woirking Dir is {0}",sc.WorkDir);
}
}
}
Source Listing (only the main header and cpp file)
For those of you who only have beta 2, you can use the following two source
listings:
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;
namespace ShortCutLib
{
public __gc class ShortCut
{
private:
String* m_filepath;
String* m_workdir;
String* m_lnkdesc;
String* m_lnkpath;
HRESULT _CreateLink(LPCWSTR FilePath, LPCWSTR LnkPath,
LPCWSTR LnkDesc,LPCWSTR WorkDir);
HRESULT _ResolveLink(LPCWSTR LnkFile, LPWSTR FilePath,
LPWSTR LnkDesc,LPWSTR WorkDir);
public:
__property String* get_FilePath()
{
return m_filepath;
}
__property void set_FilePath(String *str)
{
m_filepath = str;
}
__property String* get_WorkDir()
{
return m_workdir;
}
__property void set_WorkDir(String *str)
{
m_workdir = str;
}
__property String* get_LnkDesc()
{
return m_lnkdesc;
}
__property void set_LnkDesc(String *str)
{
m_lnkdesc = str;
}
__property String* get_LnkPath()
{
return m_lnkpath;
}
__property void set_LnkPath(String *str)
{
m_lnkpath = str;
}
bool CreateLink()
{
IntPtr strfilepath = Marshal::StringToCoTaskMemUni(FilePath);
IntPtr strlnkpath = Marshal::StringToCoTaskMemUni(LnkPath);
IntPtr strlnkdesc = Marshal::StringToCoTaskMemUni(LnkDesc);
IntPtr strworkdir = Marshal::StringToCoTaskMemUni(WorkDir);
HRESULT hres = _CreateLink((LPCWSTR)strfilepath.ToPointer(),
(LPCWSTR)strlnkpath.ToPointer(),
(LPCWSTR)strlnkdesc.ToPointer(),
(LPCWSTR)strworkdir.ToPointer());
Marshal::FreeCoTaskMem(strfilepath);
Marshal::FreeCoTaskMem(strlnkpath);
Marshal::FreeCoTaskMem(strlnkdesc);
Marshal::FreeCoTaskMem(strworkdir);
return (hres==S_OK);
}
bool ResolveLink()
{
wchar_t strfilepath[MAX_PATH];
wchar_t strworkdir[MAX_PATH];
wchar_t strlnkdesc[INFOTIPSIZE];
IntPtr strlnkpath = Marshal::StringToCoTaskMemUni(LnkPath);
HRESULT hres = _ResolveLink((LPCWSTR)strlnkpath.ToPointer(),
strfilepath, strlnkdesc, strworkdir);
FilePath = strfilepath;
LnkDesc = strlnkdesc;
WorkDir = strworkdir;
Marshal::FreeCoTaskMem(strlnkpath);
return (hres==S_OK);
}
};
}
#include "stdafx.h"
#using <mscorlib.dll>
#include <Shlobj.h>
#include <crtdbg.h>
#include <atldef.h>
#include <atlconv.h>
#include "ShortCut.h"
HRESULT ShortCutLib::ShortCut::_CreateLink(LPCWSTR FilePath,
LPCWSTR LnkPath, LPCWSTR LnkDesc,LPCWSTR WorkDir)
{
USES_CONVERSION;
CoInitialize(NULL);
IShellLink* psl;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
psl->SetPath(W2A(FilePath));
psl->SetWorkingDirectory(W2A(WorkDir));
psl->SetDescription(W2A(LnkDesc));
hres = psl->QueryInterface(IID_IPersistFile,(LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
hres = ppf->Save(LnkPath, TRUE);
ppf->Release();
}
psl->Release();
}
CoUninitialize();
return hres;
}
HRESULT ShortCutLib::ShortCut::_ResolveLink(LPCWSTR LnkFile, LPWSTR FilePath,
LPWSTR LnkDesc,LPWSTR WorkDir)
{
CoInitialize(NULL);
HRESULT hres;
IShellLink* psl;
WIN32_FIND_DATA wfd;
char strfilepath[MAX_PATH];
char strlnkdesc[INFOTIPSIZE];
char strworkdir[MAX_PATH];
USES_CONVERSION;
hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
if (SUCCEEDED(hres))
{
hres = ppf->Load(LnkFile, STGM_READ);
if (SUCCEEDED(hres))
{
hres = psl->Resolve(GetDesktopWindow(), 0);
if (SUCCEEDED(hres))
{
hres = psl->GetPath(strfilepath,MAX_PATH, &wfd,
SLGP_UNCPRIORITY );
if (SUCCEEDED(hres))
{
wcscpy(FilePath, A2W(strfilepath));
hres = psl->GetDescription(strlnkdesc,INFOTIPSIZE);
}
if (SUCCEEDED(hres))
{
wcscpy(LnkDesc,A2W(strlnkdesc));
hres = psl->GetWorkingDirectory(strworkdir,MAX_PATH);
}
if (SUCCEEDED(hres))
{
wcscpy(WorkDir,A2W(strworkdir));
}
}
}
ppf->Release();
}
psl->Release();
}
CoUninitialize();
return hres;
}
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site -
www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff -
blog.voidnish.com.
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy
Summer Love and Some more Cricket as well as a programming book –
Extending MFC applications with the .NET Framework.
Nish's latest book
C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.