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();
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 Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.
Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.
Nish's Technology Blog :
voidnish.wordpress.com