= IShellLink Example = ''Part of'' TutorialAdvanced == Description == Shows using COM to create a shortcut (requires Windows). Creates a Windows shortcut to an executable, adding several properties. == Example == {{{ #!d /* If you want an .ico file you can use mine: http://jcc_7.tripod.com/d/tutor/fldr_a.ico */ import std.c.windows.windows; import std.string; import std.c.windows.com; /* Windows API constants */ const int SW_SHOW =5; const int CP_ACP = 0; // default to ANSI code page extern(C) const GUID CLSID_ShellLink = {0x00021401, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IShellLinkA = {0x000214EE, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IPersistFile = {0x0000010B, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; alias IID_IShellLinkA IID_IShellLink; /* Windows API types */ alias ushort *LPWSTR; struct SHITEMID { USHORT cb; BYTE abID[1]; } alias SHITEMID* LPSHITEMID; struct ITEMIDLIST { SHITEMID mkid; } alias ITEMIDLIST* LPCITEMIDLIST; alias ITEMIDLIST* LPITEMIDLIST; struct WIN32_FIND_DATA { DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; char cFileName[MAX_PATH]; char cAlternateFileName[14]; WORD dummy; } alias WIN32_FIND_DATA* LPWIN32_FIND_DATA, PWIN32_FIND_DATA; struct WIN32_FIND_DATAA { DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; CHAR cFileName[MAX_PATH]; CHAR cAlternateFileName[14]; WORD dummy; } alias WIN32_FIND_DATAA* LPWIN32_FIND_DATAA, PWIN32_FIND_DATAA; struct WIN32_FIND_DATAW { DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; WCHAR cFileName[MAX_PATH]; WCHAR cAlternateFileName[14]; WORD dummy; } alias WIN32_FIND_DATAW* LPWIN32_FIND_DATAW, PWIN32_FIND_DATAW; /* Windows API functions */ extern(Windows) int MultiByteToWideChar(UINT, DWORD, LPCSTR, int, LPWSTR, int); alias MessageBoxA MessageBox; /* objidl.h excerpt */ extern(C) /+const+/ extern IID /+IID_IPersistFile+/ IID_IPERSISTFILE; extern(Windows) interface IPersistFile: IUnknown { /+ HRESULT (_stdcall *QueryInterface)(IPersistFile*,REFIID,void **); ULONG (_stdcall *AddRef)(IPersistFile*); ULONG (_stdcall *Release)(IPersistFile*);+/ HRESULT GetClassID(CLSID*); HRESULT IsDirty(); HRESULT Load(LPCOLESTR, DWORD); HRESULT Save(LPCOLESTR, BOOL); HRESULT SaveCompleted(LPCOLESTR); HRESULT GetCurFile(LPOLESTR*); } /* end of objidl.h excerpt */ /* shobjidl.h excerpt */ extern(Windows) interface IPersistIDList: IUnknown { /+ HRESULT QueryInterface(REFIID, void **); ULONG AddRef(); ULONG Release();+/ HRESULT GetClassID(CLSID*); HRESULT SetIDList(LPCITEMIDLIST); HRESULT GetIDList(LPITEMIDLIST*); } extern(Windows) interface IShellLink: IUnknown { /+ HRESULT QueryInterface(REFIID, void **); ULONG AddRef(); ULONG Release();+/ HRESULT GetPath(LPSTR, int, WIN32_FIND_DATAA*, DWORD); HRESULT GetIDList(LPITEMIDLIST*); HRESULT SetIDList(LPCITEMIDLIST); HRESULT GetDescription(LPSTR, int); HRESULT SetDescription(LPCSTR); HRESULT GetWorkingDirectory(LPSTR, int); HRESULT SetWorkingDirectory(LPCSTR); HRESULT GetArguments(LPSTR, int); HRESULT SetArguments(LPCSTR); HRESULT GetHotkey(WORD*); HRESULT SetHotkey(WORD); HRESULT GetShowCmd(int*); HRESULT SetShowCmd(int); HRESULT GetIconLocation(LPSTR, int, int*); HRESULT SetIconLocation(LPCSTR, int); HRESULT SetRelativePath(LPCSTR, DWORD); HRESULT Resolve(HWND, DWORD); HRESULT SetPath(LPCSTR); } /* end of shobjidl.h excerpt */ void main() { /* You'll probably need to change some paths to reflect your system. */ char[] SCPath = "c:\\windows\\"; char[] szFile; char[] szTarget; char[] szDesc; char[] szIcon; szFile = SCPath ~ "explorer.exe"; szTarget = SCPath ~ "d_shortcut.lnk"; szIcon = "c:\\dmd\\src\\jcc_7\\examples\\various\\fldr_a.ico"; szDesc = "Shortcut to test.lnk using D!"; if (CreateLink(szFile, szTarget, szDesc, szIcon) == S_OK) MessageBox(null, "Your shortcut has been created!", "Look at that, D does do COM!", 0); else MessageBox(null, "An error occured while trying to create your shortcut", "Aw man...", 0); } /* Helpful functions */ char[] Left(char[] s, int leng) { /* Left$(s$, leng) */ if (leng <= s.length) return s[0..leng]; return s[]; } char[] AppPath(char[] path) { /* -------------------------------------------------------------------------- DESCRIPTION: Gets a path from full path name INPUT: String to full path name OUTPUT: String to path name USAGE: buffer$ = AppPath$("c:\your directory\your file.exe") RETURNS: c:\your directory\ -------------------------------------------------------------------------- */ return Left(path, find(path, cast(char[]) "\\")); } HRESULT CreateLink(char[] lpszPathObj, char[] lpszPathLink, char[] lpszDesc, char[] lpszIcon) { /* -------------------------------------------------------------------------- DESCRIPTION: Creates a Windows shortcut INPUT: string to EXE, string to shortcut, string to description, string to icon OUTPUT: HRESULT to success or failure USAGE: result = CreateLink("c:\in.exe", "c:\out.lnk, "description") RETURNS: S_OK if the interface is supported, E_NOINTERFACE if not. -------------------------------------------------------------------------- */ HRESULT hres; IShellLink psl; CoInitialize(null); /* Initialize the COM object */ /* Get a pointer to the IShellLink interface. */ hres = CoCreateInstance(&CLSID_ShellLink, null, CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl); if (SUCCEEDED(hres)) { IPersistFile ppf; /* Sets shortcut location */ psl.SetPath(cast(char*) (lpszPathObj ~ \0)); /* Sets shortcut description */ psl.SetDescription(cast(char*) (lpszDesc ~ \0)); /* Gives shortcut an icon */ psl.SetIconLocation(cast(char*) (lpszIcon ~ \0), 0); /* Make it full screen */ psl.SetShowCmd(SW_SHOW); /* MAXIMIZED */ /* Set default path */ psl.SetWorkingDirectory(cast(char*) (AppPath(lpszPathObj) ~ \0)); /+ /* Set arguments */ psl.SetArguments("-arg1 -arg2 -arg3"); /*UNCOMMENT THIS IF YOU WANT TO SET ARGUMENTS*/ /* **** Other properties are available! **** Do not uncomment unless you define the other parameters. Read the Microsoft PSDK for more info. */ psl.SetHotkey(wHotkey); psl.SetIDList(pidl); psl.SetRelativePath(pszPathRel, null); +/ /* Query IShellLink for the IPersistFile interface for saving the shortcut in persistent storage. */ hres = psl.QueryInterface(&IID_IPersistFile, cast(void **) &ppf); if (SUCCEEDED(hres)) { WORD wsz[MAX_PATH]; /* Ensure that the string is ANSI. */ MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH); /* Save the link by calling IPersistFile::Save. */ hres = ppf.Save(cast(wchar*) wsz, cast(int) true); ppf.Release(); } psl.Release(); } CoUninitialize(); /* Uninitialize the COM object */ return hres; } }}} == Compiling and Linking Tips == Compile like this... {{{ dmd createLink.d ole32.lib uuid.lib }}} Link with: * ole32.lib (for _CoUninitialize@0, _CoInitialize@4, _CoCreateInstance@20) * uuid.lib (for _CLSID_ShellLink) == Source == * Ported to D (DMD version 0.59) from BCX/LCC-Win32 by J C Calvarese ([http://jcc_7.tripod.com/d/tutor/createLink.html createLink.html]) * Based on "BCX COM EXAMPLE" (by dl_programmer) * BCX source in makelink.zip at http://groups.yahoo.com/group/BCX/files/Source_Code/