Create a Shortcut on Desktop

How to create shortcut for desktop and startmenu after installation in NSIS?

Giving the user the choice of user/machine shortcuts is in conflict with how UAC works. When a non-admin user elevates with an administrator account the installer will end up running with the "wrong" profile.

The Windows guidelines say that only application suites (with individual major applications, like MS Office) should create Start menu folders. Regular applications should create their (single) shortcut directly in $SMPrograms. You should not create shortcuts to the uninstaller nor help-files. You should also refrain from creating a desktop shortcut.

This means you can simply use the components page to provide the shortcut option(s):

!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English

Section "Program files"
SectionIn RO
SetOutPath $InstDir
File "MyApp.exe"
SectionEnd

Section "Start menu shortcut"
CreateShortcut "$SMPrograms\$(^Name).lnk" "$InstDir\MyApp.exe"
SectionEnd

Section /o "Desktop shortcut"
CreateShortcut "$Desktop\$(^Name).lnk" "$InstDir\MyApp.exe"
SectionEnd

or as a checkbox on the Finish page:

!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_SHOWREADME ""
!define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Start menu shortcut"
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateShortcuts
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English

Function CreateShortcuts
CreateShortcut "$SMPrograms\$(^Name).lnk" "$InstDir\MyApp.exe"
FunctionEnd

If you actually have a suite of applications then you can use the Start menu page to prompt for a folder name:

Var SMFolder

!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE STARTMENU Suite $SMFolder
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English

Section
!insertmacro MUI_STARTMENU_WRITE_BEGIN Suite
CreateDirectory "$SMPrograms\$SMFolder"
CreateShortcut "$SMPrograms\$SMFolder\App1.lnk" "$InstDir\MyApp1.exe"
CreateShortcut "$SMPrograms\$SMFolder\App2.lnk" "$InstDir\MyApp2.exe"
; TODO: Write $SMFolder to the registry or a .ini so your uninstaller can delete the folder
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd

In the unlikely event that you have a suite of applications and you also want to create desktop shortcuts then yes, you need to use a custom page:

Var SMDir
Var SMCheck
Var DeskCheck
Var SMList
Var SMDirEdit

!include LogicLib.nsh
!include nsDialogs.nsh
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
Page Custom MyShortcutsPageCreate MyShortcutsPageLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English

Function .onInit
StrCpy $SMDir "$(^Name)" ; Default
StrCpy $SMCheck ${BST_CHECKED}
FunctionEnd

Function MyShortcutsPageCreate
!insertmacro MUI_HEADER_TEXT "Shortcuts" "Shortcuts blah blah blah"
nsDialogs::Create 1018
Pop $0
${IfThen} $0 == error ${|} Abort ${|}

${NSD_CreateCheckbox} 0 0u 50% 12u "Create Start menu shortcuts"
Pop $R8
SendMessage $R8 ${BM_SETCHECK} $SMCheck ""

${NSD_CreateCheckbox} 0 14u 50% 12u "Create desktop shortcuts"
Pop $R9
SendMessage $R9 ${BM_SETCHECK} $DeskCheck ""

${NSD_CreateSortedListBox} 0 28u 100% -43u ""
Pop $SMList

${NSD_CreateText} 0 -13u 100% 12u "$SMDir"
Pop $SMDirEdit

${NSD_LB_AddString} $SMList "(Default)"
${NSD_LB_SetItemData} $SMList 0 1 ; Mark as special
SetShellVarContext Current
Call FillSMList
SetShellVarContext All
Call FillSMList
SetShellVarContext ? ; TODO: Restore to what you actually are installing as
${NSD_OnChange} $SMList OnSMListChanged

${NSD_OnClick} $R8 OnSMCheckChanged
Push $R8
Call OnSMCheckChanged
nsDialogs::Show
FunctionEnd

Function FillSMList
FindFirst $0 $1 "$SMPrograms\*"
loop:
StrCmp $1 "" done
${If} ${FileExists} "$SMPrograms\$1\*.*"
${AndIf} $1 != "."
${AndIf} $1 != ".."
${NSD_LB_FindStringExact} $SMList "$1" $2
${If} $2 < 0
${NSD_LB_AddString} $SMList $1
${EndIf}
${EndIf}
FindNext $0 $1
Goto loop
done:
FindClose $0
FunctionEnd

Function OnSMCheckChanged
Pop $0
${NSD_GetChecked} $0 $0
EnableWindow $SMList $0
EnableWindow $SMDirEdit $0
FunctionEnd

Function OnSMListChanged
Pop $0
${NSD_LB_GetSelection} $SMList $0
${NSD_SetText} $SMDirEdit "$0\$(^Name)"
${NSD_LB_GetSelectionIndex} $SMList $0
${NSD_LB_GetItemData} $SMList $0 $0
${If} $0 <> 0
${NSD_SetText} $SMDirEdit "$(^Name)"
${EndIf}
FunctionEnd

Function MyShortcutsPageLeave
${NSD_GetChecked} $R8 $SMCheck
${NSD_GetChecked} $R9 $DeskCheck
${NSD_GetText} $SMDirEdit $SMDir
FunctionEnd


Section
${If} $SMCheck <> 0
CreateDirectory "$SMPrograms\$SMDir"
CreateShortcut "$SMPrograms\$SMDir\App1.lnk" "$InstDir\App1.exe"
CreateShortcut "$SMPrograms\$SMDir\App2.lnk" "$InstDir\App2.exe"
${EndIf}

${If} $DeskCheck <> 0
CreateShortcut "$Desktop\App1.lnk" "$InstDir\App1.exe"
CreateShortcut "$Desktop\App2.lnk" "$InstDir\App2.exe"
${EndIf}
SectionEnd

How to create shortcut in Desktop after install my wpf app

Selecting the "Create desktop shortcut" option under Project->Properties->Publish->Options->Manifests in Visual Studio should give you a desktop shortcut:

Sample Image

How to create a desktop shortcut (link), but with own shortcut file extension (e.g. .appfolder) instead of .lnk programmatically in C#?

I solved it:
My registration of .appfolder wasn't completely correct to work exactly like .lnk shortcut file.
Follow this instruction.
After that both methods in C# mentioned above work.

Make a selection which desktop shortcut icons to create in Inno Setup

Create separate task for each of your shortcuts, instead of the one desktopicon task:

[Tasks]
Name: "appdesktopicon"; Description: "Application icon"; \
GroupDescription: "{cm:AdditionalIcons}"
Name: "ueficondesktopicon"; Description: "WinUEFI Console icon"; \
GroupDescription: "{cm:AdditionalIcons}"
Name: "uefi32desktopicon"; Description: "WinUEFI (32-bit) icon"; \
GroupDescription: "{cm:AdditionalIcons}"
Name: "uefi32condesktopicon"; Description: "WinUEFI (32-bit) Console icon"; \
GroupDescription: "{cm:AdditionalIcons}"

[Icons]
Name: "{autodesktop}\{#MyAppName}"; \
Filename: "{app}\{#MyAppExeName}"; Tasks: appdesktopicon
Name: "{autodesktop}\WinUEFI Console"; \
Filename: "{app}\WinUEFI-console.exe"; Tasks: ueficondesktopicon
Name: "{autodesktop}\WinUEFI (32-bit)"; \
Filename: "{app}\WinUEFI-x86.exe"; Tasks: uefi32desktopicon
Name: "{autodesktop}\WinUEFI (32-bit) Console"; \
Filename: "{app}\WinUEFI-x86-console.exe"; Tasks: uefi32condesktopicon

Sample Image

Creating a shortcut with PowerShell

The target executable and its arguments must be specified separately, namely in the .TargetPath and .Arguments property, respectively.

(Whatever you assign to .TargetPath is considered just an executable file path, and if it contains spaces, it is automatically and invariably enclosed in "..." for you.)

Therefore:

$shortcut = (New-Object -ComObject Wscript.Shell).CreateShortcut('desktop\Certificates.lnk')
$shortcut.TargetPath = 'C:\Windows\System32\rundll32.exe' # Executable only
$shortcut.Arguments = 'cryptui.dll,CryptUIStartCertMgr' # Args to pass to executable.
$shortcut.IconLocation = '%SystemRoot%\System32\SHELL32.DLL, 44'
$shortcut.Save()

Note that I've removed unnecessary (...) enclosures and, for conceptual clarity, have switched from expandable (double-quoted) strings ("...") to verbatim (single-quoted) strings ('...'), given that no string expansion (interpolation) is required in your code.

That said, for full robustness you could replace 'C:\Windows\System32\rundll32.exe' with "$env:SystemRoot\System32\rundll32.exe" - for instant expansion - or '%SystemRoot%\System32\rundll32.exe' for letting .CreateShortcut() perform the expansion.[1]


[1] It seems that the resulting shortcut file (.lnk) stores both the expanded and the unexpanded value. When inspecting a shortcut file's properties in File Explorer - and surprisingly also via getting the property values of a WshShortcut object created with (New-Object -ComObject Wscript.Shell).CreateShortcut() - you only ever see the expanded values.

Is there any way to create an shortcut desktop to a Node.js (npm) application?

**SOLVED**

An .bat file, renamed as "appstart.bat"

cd C:\Users\MyUser\MyApp
npm start

With shortcut in desktop.

Create Shortcut using PowerShell Script

You didn't show this, but the error message you received is probably this one:

Exception setting "IconLocation": "The property 'IconLocation' cannot be found on this object. Verify that the property exists and can be set."
At line:8 char:1
+ $source.IconLocation="C:\Users\Public\Pictures\ShortcutIcon.ico"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting

That is because an Internet shortcut has different properties than a 'normal' (.lnk) shortcut to a file of folder.

Another thing is that you have prefixed the shortcut filename with a double backslash and by doing so, you will get a wrong path: C:\Users\Public\Desktop\\Test Intranet.url

In below code, I have changed some of the variable names to be more self-descripting (at least, I like to think so..)

$shell        = New-Object -ComObject WScript.Shell
$destination = $shell.SpecialFolders.Item("AllUsersDesktop")
$shortcutPath = Join-Path -Path $destination -ChildPath 'Test Intranet.url'
# create the shortcut
$shortcut = $shell.CreateShortcut($shortcutPath)
# for a .url shortcut only set the TargetPath
$shortcut.TargetPath = 'https://sharepoint.com/'
$shortcut.Save()

# next update the shortcut with a path to the icon file and the index of that icon
# you can do that because a .url file is just a text file in INI format
Add-Content -Path $shortcutPath -Value "IconFile=C:\Users\Public\Pictures\ShortcutIcon.ico"
Add-Content -Path $shortcutPath -Value "IconIndex=0"

# clean up the COM objects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shortcut) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

When opened in notepad, your shortcut file looks like this:

[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://sharepoint.com/
IconFile=C:\Users\Public\Pictures\ShortcutIcon.ico
IconIndex=0


Related Topics



Leave a reply



Submit