Create Windows shortcuts shortcut .lnk .url

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
Zippy
Posts: 1295
Joined: Feb 10, 2006 18:05

Create Windows shortcuts shortcut .lnk .url

Post by Zippy »

The ubiquitous Windows ShortCut.. This code should work on Win95 with WSH installed, Win98 forward except WinNT (Win98 forward came/comes with WSH, except NT did not for reasons unknown to me).

This first code set is a complete example; brief typeset examples follow, brief Notes after each:

Code: Select all

'disphelper create shortcut .lnk .url, Windows 98+ (Win95 with WSH)
'
#include once "windows.bi"
' I'm trying, here, to prevent UNICODE conflicts..
#ifndef UNICODE
    #define UNICODE
    #define LnkUNICODE
#endif
#include once "disphelper/disphelper.bi"
#ifdef LnkUNICODE
    #undef UNICODE
    #undef LnkUNICODE
#endif
'
type tagLnkData
    as string  TargetPath       'file or program or url to .lnk
    as string  Arguments        'program arguments if any
    as string  WorkingDirectory '
    as string  LinkName         'something.lnk OR someplace.url
    as string  LinkLocation     'absolute path or see sf= in function
    as string  LinkDescription  'comment
    as string  IconLocation     'where to look for icon
    as integer IconIdx          'index of icon in file, or use 0 if only one/none/default
    as integer WindowStyle      '1,3 or 7
    as string  Hotkey           'i.e., "CTRL+SHIFT+F"
end type
dim as tagLnkData Lnkdata
'
declare function createLnk(LnkData as tagLnkData ptr) as integer
'
dim as integer res
'
'set .lnk parameters
LnkData.TargetPath      ="%windir%\notepad.exe"
LnkData.Arguments       =""
LnkData.WorkingDirectory="%homedrive%%homepath%"
LnkData.LinkName        ="Notepadtest.lnk"
LnkData.LinkLocation    ="Desktop"
LnkData.LinkDescription ="Test Link"
LnkData.IconLocation    ="%windir%\notepad.exe"'use app's icon
LnkData.IconIdx         =0
LnkData.WindowStyle     =1
LnkData.Hotkey          =""
'
res=createLnk(@LnkData)
if res<>1 then
    print "Error ";res;" creating lnk, see function for error codes"
else
    print LnkData.LinkName;" created"
end if
'
print "Done, Sleeping.."
sleep
'
function createLnk(LnkData as tagLnkData ptr) as integer
'
    dim as integer Lnkcode=1
    dim as string ds,sf,ts
    dim as zstring ptr tsp
    dim as HRESULT hres
    '
    sf =" AllUsersDesktop AllUsersStartMenu AllUsersPrograms "
    sf+=" AllUsersStartup Desktop Favorites Fonts MyDocuments "
    sf+=" NetHood PrintHood Programs Recent SendTo StartMenu "
    sf+=" Startup Templates "
    '
    DISPATCH_OBJ(WshShell)
    DISPATCH_OBJ(oShellLink)
    '
    dhInitialize(TRUE)
    '
'Note:
'dhToggleExceptions(TRUE)'use for debugging, comment-out otherwise
    '
    'get our WSH object
    hres=dhCreateObject("WScript.Shell",NULL,@WshShell)
    if hres<>0 then LnkCode=                -1 : goto CreateLnkBugOut
    '
    'get/set location of shortcut
    ' "AllUsersDesktop" requires admin rights to save in Vista, "Desktop" works..
    ts=LnkData->LinkLocation
    if ts="" then Lnkcode =                 -2 : goto CreateLnkBugOut
    '
    'see if we have a Special Folder location
    if instr(sf," " & ts & " ")<>0 then
        'special folder names are CaSe-SenSitive
        hres=dhGetValue("%s",@tsp,WshShell,".SpecialFolders(%s)",LnkData->LinkLocation)
        '
        'failed to get Special Folder location
        if hres<>0 then LnkCode =           -3 : goto CreateLnkBugOut
        if *tsp="" then LnkCode =           -4 : goto CreateLnkBugOut
        '
        ts=*tsp
        if LnkData->LinkLocation=LnkData->WorkingDirectory then
            LnkData->WorkingDirectory=ts
        end if
        '
    'special folder names are CaSe-SenSitive .. Fail if no MaTcH
    elseif instr(ucase(sf)," " & ucase(ts) & " ")<>0 then
                        LnkCode =           -5 : goto CreateLnkBugOut
    'our LinkLocation is not a Special Folder, check that dir exists
    else
        ds=dir(ts,&h10)
        if ds="" then LnkCode =             -6 : goto CreateLnkBugOut
    end if
    if right(ts,len(ts))<>"\" then ts+="\"
    '
    'gotta have a name for our .lnk
    if LnkData->LinkName="" then LnkCode =  -7 : goto CreateLnkBugOut
    '
    'now create and name the shortcut
    hres=dhGetValue("%o",@oShellLink,WshShell,".CreateShortcut(%s)",ts & LnkData->LinkName)
    if hres<>0 then LnkCode =               -8 : goto CreateLnkBugOut
    '
    'where is the file/program/url to link
    dhPutValue(oShellLink,".TargetPath = %s",LnkData->TargetPath)
    '
    'more params, not applicable to .url shortcuts
    if right(ucase(LnkData->LinkName),4)<>".URL" then
        dhPutValue(oShellLink,".WindowStyle = %d",LnkData->WindowStyle)
        dhPutValue(oShellLink,".IconLocation = %s",LnkData->IconLocation &", " & str(LnkData->IconIdx))
        dhPutValue(oShellLink,".Description = %s",LnkData->LinkDescription)
        dhPutValue(oShellLink,".WorkingDirectory = %s",LnkData->WorkingDirectory)
        dhPutValue(oShellLink,".Arguments = %s",LnkData->Arguments)
        if LnkData->HotKey<>"" then
            dhPutValue(oShellLink,".HotKey = %s",LnkData->HotKey)
        end if
    end if
    '
    'finalize shortcut, analogous to closing a file
    ' if save fails the most likely cause is insufficent user rights
    hres=dhCallMethod(oShellLink,"Save")
    if hres<>0 then LnkCode =               -9
    '
CreateLnkBugOut:
    '
    'cleanup..
    SAFE_RELEASE(WshShell)
    SAFE_RELEASE(oShellLink)
    dhUninitialize(TRUE)
    '
    return LnkCode
'
end function
Shortcuts can .lnk to executables, urls, or any file type that has an associated program (like .txt files, which are associated with Notepad.exe).

.TargetPath is the path or url to/of what you want linked. The function does no error checking of this as there are too many possibilies (URLs are diff to check).

.Arguments is used to pass.. arguments to the .TargetPath, like "text.txt" could be an argument to Notepad linked in code above.

.WorkingDirectory is - where the program should use as its base directory.

.LinkName is the "filename", the name of the shortcut. It must follow filenaming conventions and must end in ".lnk" or ".url". A .lnk can be a URL, but a .url cannot be a .lnk :-)

.LinkLocation is where.. the shortcut will be created. You can use Special Folder names (see sf= in the function) or an absolute path. Not all Special Folders are available (exist) in all versions of Windows, some Special Folder locations require admin rights ("All"s, usually).

.IconLocation and the remaining params should be more or less obvious from the first example above, and the following examples.

=====

This is a URL .lnk (not a .url shortcut):

Code: Select all

LnkData.TargetPath      ="http://freebasic.net/forum"
LnkData.Arguments       =""
LnkData.WorkingDirectory="Desktop"
LnkData.LinkName        ="FB Forum.lnk"
LnkData.LinkLocation    ="Desktop"
LnkData.LinkDescription ="FB Forum"
LnkData.IconLocation    ="%systemroot%\System32\shell32.dll"
LnkData.IconIdx         =14
LnkData.WindowStyle     =1
LnkData.Hotkey          ="CTRL+SHIFT+F"
Uses the 15th icon in shell32.dll. Sets a global hotkey.


This is a true .url shortcut:

Code: Select all

LnkData.TargetPath      ="http://freebasic.net/forum"
LnkData.Arguments       ="" 'NA for .url
LnkData.WorkingDirectory="" 'NA for .url
LnkData.LinkName        ="FB Forum.url"
LnkData.LinkLocation    ="Desktop"
LnkData.LinkDescription ="" 'NA for .url
LnkData.IconLocation    ="" 'NA for .url
LnkData.IconIdx         =0  'NA for .url
LnkData.WindowStyle     =1  'NA for .url
LnkData.Hotkey          ="" 'There's a place for it, but can't add/modify
Note you can't set extra params for a .url shortcut. The icon will be set/taken from the favicon from the website if it's been downloaded.


This .lnks a file, a .txt file that will open with/by the associated program (likely Notepad):

Code: Select all

LnkData.TargetPath      ="c:\temp\test.txt"
LnkData.Arguments       =""
LnkData.WorkingDirectory="Desktop"
LnkData.LinkName        ="test.txt.lnk"
LnkData.LinkLocation    ="c:\temp" ' do NOT append backslash
LnkData.LinkDescription ="Test Text"
LnkData.IconLocation    ="" 'Windows will use default text icon if not spec-ed
LnkData.IconIdx         =0  'not applicable
LnkData.WindowStyle     =1
LnkData.Hotkey          =""
Windows will add the icon, or you can spec one.


This .lnks a directory:

Code: Select all

LnkData.TargetPath      ="c:\temp"
LnkData.Arguments       =""
LnkData.WorkingDirectory="Desktop"
LnkData.LinkName        ="CTEMP.lnk"
LnkData.LinkLocation    ="Desktop"
LnkData.LinkDescription ="Temp Folder"
LnkData.IconLocation    ="%systemroot%\System32\shell32.dll"
LnkData.IconIdx         =4
LnkData.WindowStyle     =1
LnkData.Hotkey          =""
Uses a folder icon from shell32.dll


This starts a cmd shell, lists c:\*.*, and pauses:

Code: Select all

LnkData.TargetPath      ="%systemroot%\system32\cmd.exe"
LnkData.Arguments       =!"/c \"dir *.* /w & pause\""
LnkData.WorkingDirectory="%homedrive%%homepath%"
LnkData.LinkName        ="TestCMD.lnk"
LnkData.LinkLocation    ="Desktop"
LnkData.LinkDescription ="CMD"
LnkData.IconLocation    ="%systemroot%\system32\cmd.exe"
LnkData.IconIdx         =0
LnkData.WindowStyle     =1
LnkData.Hotkey          =""
Note the quoting. Shell quoting is necessary and strange. Perhaps arbitrary.
Post Reply