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:
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
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
Http Error 500.30 - Ancm In-Process Start Failure
What Is [Serializable] and When Should I Use It
Call Signalr Core Hub Method from Controller
Headless Browser for C# (.Net)
Using Filesystemwatcher to Monitor a Directory
Reading Datetime Value from Excel Sheet
JSON.Net: Serialize/Deserialize Property as a Value, Not as an Object
Alphanumeric Sorting Using Linq
How to Run an Exe Program from a Windows Service Using C#
A Generic List of Anonymous Class
Regular Expression to Remove HTML Tags
Check for Column Name in a SQLdatareader Object
Check If Number Is Prime Number
How to Dynamically Create ASP.NET Controls Within Dynamically Created ASP.NET Controls