[RESOLVED] Creating shortcuts without using Script Host Object
I am creating shortcuts on the Desktop using the Script Host Object. It all works fine, but I would like to free my applications from the wshom.ocx reference. Searching the net did not yield other interesting results. I peaked at the .lnk file format, but it's rather involved, and if I did write a proper .lnk, I bet there would be other surprises down the line.
Is there any other API way of creating a shortcut? One of my requirements is being able to specify an icon in addition of a target path. Thanks.
1 Attachment(s)
Re: Creating shortcuts without using Script Host Object
Well you could "go to the source" and do this via Shell Automation. It's another wrapper on Shell's flat API calls much as you've been using but at least it is all housed in the same library (Shell32.dll).
Code:
Option Explicit
Private Sub CreateLink()
Const ssfDESKTOP As Long = 0
Dim F As Integer
With CreateObject("Shell.Application").NameSpace(ssfDESKTOP)
'Create new (empty) link, here we'll do it on the Desktop:
F = FreeFile(0)
Open .Self.Path & "\Sample.lnk" For Binary Access Write As #F
Close #F
'Populate link data, update:
With .Items.Item("Sample.lnk").GetLink
.Path = App.Path & "\" & App.EXEName & ".exe"
.WorkingDirectory = App.Path
.Arguments = "Hello World!"
.Description = App.FileDescription
.ShowCommand = 1
.SetIconLocation .Path, 0
.Save
End With
End With
End Sub
Private Sub Main()
If Len(Command$()) > 0 Then
MsgBox Command$()
Else
On Error Resume Next
GetAttr App.EXEName & ".exe"
If Err Then
MsgBox "Compile this program first."
Exit Sub
End If
On Error GoTo 0
'Create a "shortcut" to myself on the Desktop:
CreateLink
End If
End Sub
Re: Creating shortcuts without using Script Host Object
Another option is to use the method that the package and deployment wizard uses. The source code is included with VB6. It uses I think the vb6stkit.dll
Code:
Public Declare Function OSfCreateShellLink Lib "vb6stkit.dll" Alias "fCreateShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String, ByVal lpstrLinkPath As String, ByVal lpstrLinkArguments As String, ByVal fPrivate As Long, ByVal sParent As String) As Long
Re: Creating shortcuts without using Script Host Object
For completeness (and to introduce a Helper-Object, which can also set e.g. the
"Run as Administrator"-flag, in case that's needed)...
Here's what it looks like when vbRichClient5.cShellLink is used:
Code:
Private Sub Main()
Dim WorkDir As String
WorkDir = New_c.FSO.GetUserAppDataPath & "\MyApp\"
If Not New_c.FSO.FolderExists(WorkDir) Then New_c.FSO.CreateDirectory WorkDir
With New_c.ShellLink
.SetWorkingDirectory WorkDir
.SetPath "Notepad.exe"
' .SetArguments "SomeTextFile.txt" 'set arguments if needed here
.SetDescription "This starts Notepad.exe"
.SetHotKey (vbCtrlMask Or vbAltMask) * 256 + vbKeyN 'use Ctrl+Alt+N as a HotKey
.SetShowCmd SL_SHOWNORMAL
'not setting the IconLocation will use the default-icon of the executable or document...
'alternatively force the *.lnk to use either an Icon from a Dll-Resource, or from an *.ico-File
' .SetIconLocation "shell32.dll", 80
' .SetIconLocation "C:\MyIcons\SomeIcon.ico", 0
'comment the next line in, if you want to switch-on the "Run as Administrator"-Flag
' .SetFlags SLDF_RUNAS_USER
'the last line below finally writes out the *.lnk-File to the Desktop
.Save New_c.FSO.GetSpecialFolder(CSIDL_DESKTOPDIRECTORY) & "\MyLink.lnk", True
End With
End Sub
Olaf
Re: Creating shortcuts without using Script Host Object
VBRichClient5 is a bit of overkill; you can gain access to IShellLink by itself...
http://www.vbaccelerator.com/home/VB...onstration.asp is a heavyweight demonstration,
but the core routine can be simplified into just one function once the typelib is added as a reference...
Code:
Public Sub SaveNewLink(sLink As String, _
sPath As String, _
Optional sIconFile As String = vbNullString, _
Optional ByVal lIcon As Long = 0, _
Optional ByVal iHK As Integer = 0, _
Optional sArgs As String = vbNullString, _
Optional sDesc As String = vbNullString, _
Optional ByVal pidl As Long = 0, _
Optional sWorkDir As String = vbNullString, _
Optional sRelPath As String = vbNullString, _
Optional swc As EShowWindowFlags = SW_NORMAL)
Dim csl As CShellLink
Dim ipf As IPersistFileVB
Set csl = New CShellLink
Set ipf = csl
With csl
.SetPath (sPath)
.SetArguments sArgs
.SetDescription sDesc
.SetIconLocation sIconFile, lIcon
.Hotkey = iHK
.ShowCmd = swc
.SetRelativePath sRelPath, 0
.SetWorkingDirectory sWorkDir
If pidl Then .SetIDList pidl
.Resolve 0, SLR_UPDATE
End With
ipf.Save sLink, 0
Set ipf = Nothing
Set csl = Nothing
A lot of projects already have olelib.tlb as a reference, which does contain the IShellLink interface... I can't recall the problem that made me switch to VBAccelerator's lib...
Edit: In olelib there's no coclass for it so you can't use the New statement. It can be patched with
Code:
[ uuid(00021401-0000-0000-C000-000000000046),
helpstring("VB IShellLinkA Class")
]
coclass ShellLinkA {
[default] interface IShellLinkA;
};
if you were so inclined. I only mention this because olelib is common, but many things aren't done right, so then you start getting multiple versions of interfaces and have to start always remembering you want ShellLinkVB.IShellLink and not olelib.IShellLink, etc. So it's better to update olelib.
Re: Creating shortcuts without using Script Host Object
Thank you everyone, I did not expect solutions that varied in scope.
I will try everyone of them, actually I have already, some with mixed results. In each one of them there is something to learn but ultimately, my basic criteria are :
- as simple as possible, with as little dependencies as possible, especially for the project i need the feature for.
- must be able to work with modern Icon formats, not the outdated icons insertable in a VB6 compiled exe.
Dilettante :
Your little project worked fine, simple with only calls to shell32.dll. I am running into a little glitch trying to customize it. A medium long report would be needed here. I'll keep that for later, after I have done a bit more work.
Datamiser :
that one was easy, thanks ... just a little bit short though on external icon support.
Olaf :
elegant, very short piece of code, looks real good. For a while I thought it was the File Scripting Object (scrrun.dll).. is it ? No such method as GetUserAppDataPath in scripting object. I am obviouly working with the wrong object...
vbRichClient5 ?? i could not find that, code did not work.
fafalone :
Thanks, Interesting code... reasonably compact... i had no problem getting the tlb from vbAccelerator, but the parameters described here lack clarity of documentation. I wanted to give a peak at the bigger project, but it would not load and let me peak at the code without going back there a third time and get some ocx not included in the project. I once had a plan to rework the Icon Program on vbAccelerator. The guy there writes code that is hard to manage. I had to let go this one for the time being at least.
Re: Creating shortcuts without using Script Host Object
Navion, just search for vbRichClient with google. It seems that posting the link is forbidden, don't try to understand :rolleyes:
Re: Creating shortcuts without using Script Host Object
Quote:
Originally Posted by
Navion
Olaf :
elegant, very short piece of code, looks real good. For a while I thought it was the File Scripting Object (scrrun.dll).. is it ? No such method as GetUserAppDataPath in scripting object. I am obviouly working with the wrong object...
vbRichClient5 ?? i could not find that, code did not work.
vbRichClient5 is a free available, modern Framework for VB5/6 which contains a lot of
useful Helper-Classes - many of them without alternative in the VBClassic-universe.
The above New_c.FSO instance of the RichClient is not using the Scripting.FSO under the hood,
it's a Wrapper-Class around a lot of FileSystem-APIs - and Unicode-capable throughout
(the whole RichClient-functionality is unicode-aware).
E.g. cFSO offers beside "the usual File-Functions and -Dialogs" also FileSystem-Watchers, the
fastest DirListing-class available for VB6, and maybe interesting for you, also a (huge-file-capable)
Stream-Class, a fast CSV-parser for CSV-files > 4GB, Unicode-Reading/Decoding etc.
It contains also the fastest XML-parser for VB6, the fastest JSON-parser for VB6, the
fastest Collection and Dictionary-Classes for VB6, the fastest (ADO-like usable) COM-wrapper
for SQLite, and the most complete and comprehensive graphics- and GUI-framework for VB6
(easier and with larger functionality than GDI+, as e.g. offering SVG-support and PDF-support).
It will add about 1.6MB (when LZMA-compressed, 2.2MB when zipped) deployment-size to an Application,
but on the other hand allows "regfree usage and shipping" in a SubFolder alongside your App, so these
"costs" are very bearable I'd think.
Other than e.g. on the vbAccelerator-site (which offers a lot of separated, but related binaries), the
Class-Stack in the RichClient is "precompiled and bundled in one place" - and major version-numbers
try to maintain binary-compatibility on the COM-interfaces.
I wrote it as a modern ClassRuntime-Enhancement for VBClassic - available for anybody...
just check in a single project-reference, and then "off you go" with kinda like a "VB 6.5". ;)
Olaf
Re: Creating shortcuts without using Script Host Object
Quote:
Originally Posted by
Navion
Thanks, Interesting code... reasonably compact... i had no problem getting the tlb from vbAccelerator, but the parameters described here lack clarity of documentation. I wanted to give a peak at the bigger project, but it would not load and let me peak at the code without going back there a third time and get some ocx not included in the project. I once had a plan to rework the Icon Program on vbAccelerator. The guy there writes code that is hard to manage. I had to let go this one for the time being at least.
You don't have to worry about any of the code. All you have to do is add the vba TLB as a reference (you don't also need olelib; that's a whole other topic i was talking about), then the single function I posted will create the shortcut. No other code needed.
sLink - the full output link, e.g. c:\path\file.txt.lnk
sPath - the full path of the input file, e.g. c:\file.txt
sIconFile As String - It uses the default icon on its own, but you can manually change it by specifying the file with the new icon here
lIcon - And the index/ID of the icon here
iHK - define a hotkey... not sure myself never used it
sArgs - the 'arguments' box of shortcut properties; blank unless you need command line arguments for an exe
sDesc - Specify your own description
pidl - Instead of a filename, you can use a fully qualified pidl (ignore this if you don't know what that is)
sWorkDir - Working directory; almost never needed
sRelPath - Use a relative path; rarely used
EShowWindowFlags - normal, windowed, maximized, etc.
All the Optional arguments can be ignored if you're not using them; you can make it as simple as SaveNewLink("C:\file.txt.lnk", "C:\folder\file.txt")
Re: Creating shortcuts without using Script Host Object
Quote:
Originally Posted by
Schmidt
vbRichClient5 is a free available, modern Framework for VB5/6 which contains a lot of
useful Helper-Classes - many of them without alternative in the VBClassic-universe.
Ok, thanks, got it now.. Interesting project whose goal I do embrace. I downloaded it. Will give it a closer look soon.
Re: Creating shortcuts without using Script Host Object
Quote:
Originally Posted by
fafalone
You don't have to worry about any of the code. All you have to do is add the vba TLB as a reference (you don't also need olelib; that's a whole other topic i was talking about), then the single function I posted will create the shortcut. No other code needed.
sLink - the full output link, e.g. c:\path\file.txt.lnk
sPath - the full path of the input file, e.g. c:\file.txt
Yeahh.. that's what I thought, simple enough, but it did not work, hence my comment about documentation. I was really exhausted at the time I tried it. I had put an exit sub in the routine to check the passing of arguments before calling a routine that writes to my precious desktop. Forgot to remove it. My bad. I spotted this first thing this morning. Works A-OK.
(Edit) Details about the project :
It is a super tiny program that contains half a dozen most needed file, clipboard and desktop management utilities. Compiled just once, it performs self installation, creation of shortcuts on the desktop and/or taskbar. The program is designed as a drop in folder, with no external system dependencies whatsoever. All Windows versions contain the basic VB6 runtime files, but as soon as you add an external control or dll or OCX, you have to provide a package to install and register those dependencies. I wanted to alleviate that. Once compiled, the main exe is just copied with different names as 6 different utilities and each behaves according to its EXE name.
With your routine, I could reduce the setup code to these two lines (it could have been one)
Code:
apptoken$ = App.EXEName
SaveNewLink makeFilename(desktopFolder, apptoken$ & ".lnk"), makeFilename(App.Path, apptoken$ & ".exe"), makeFilename(App.Path, apptoken$ & ".ico")
Actually, this is not exactly what I am using, there is a little bit more code checking file existence, whether or not shortcuts have been installed in the task bar, etc.. but essentially, those two lines perform all the setup work. Come to think of it will probably move the file checking code inside the SaveNewLink routine (and call it CheckLinks).
Re: [RESOLVED] Creating shortcuts without using Script Host Object
Thanks everyone. Solution tested and deployed from XP to 10, no dependencies ;