HurleyShanabarger Posted May 26, 2020 Posted May 26, 2020 Seems that I have kind of an issue lately with 32bit/64bit versions of some projects that I am working on. Currently I want to retrieve the icon from a shortcut; if this is not available I would like to get the icon from file the link points to. #NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #Tidy_Parameters=/reel /sf /ri #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #Region Includes #include <Array.au3> #EndRegion Includes #Region Variables/Opt #EndRegion Variables/Opt #Region Main _Main() Func _Main() Local $aShortcut, $sLinkfile = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Everything.lnk" $aShortcut = FileGetShortcut($sLinkfile) _ArrayDisplay($aShortcut) EndFunc ;==>_Main #EndRegion Main If the shortcut points to "C:\Program Files\..." and the script runs in 32bit I will retrieve "C:\Program Files (x86)\...". Is there any way for a 32bit script to just read the shortcut target path without having it altered depening if the script is running in 32bit or not?
Subz Posted May 26, 2020 Posted May 26, 2020 (edited) It returns both for me: #include <File.au3> Global $g_aShortcut, $g_aShortcuts = _FileListToArrayRec(@StartMenuCommonDir, "*.lnk", 1, 1, 0, 2) If @error Then Exit For $i = 1 To $g_aShortcuts[0] $g_aShortcut = FileGetShortcut($g_aShortcuts[$i]) ConsoleWrite($g_aShortcut[0] & @CRLF) Next Edited May 26, 2020 by Subz
HurleyShanabarger Posted May 26, 2020 Author Posted May 26, 2020 2 minutes ago, Subz said: It returns both for me: #include <File.au3> Global $g_aShortcut, $g_aShortcuts = _FileListToArrayRec(@StartMenuCommonDir, "*.lnk", 1, 1, 0, 2) If @error Then Exit For $i = 1 To $g_aShortcuts[0] $g_aShortcut = FileGetShortcut($g_aShortcuts[$i]) ConsoleWrite($g_aShortcut[0] & @CRLF) Next If I run yours in 32bit I retrieve "C:\Program Files (x86)\Utilities\Everything\Everything.exe" If I run yours in 64bit I retrieve "C:\Program Files\Utilities\Everything\Everything.exe" The correct target path is "C:\Program Files\Utilities\Everything\Everything.exe"
Subz Posted May 26, 2020 Posted May 26, 2020 Is the path hard coded in the shortcut or is it using an environment variable? i.e. "%ProgramFiles%\Utilities\Everything\Everything.exe"
HurleyShanabarger Posted May 27, 2020 Author Posted May 27, 2020 The path seems to be hardcoded (Everything is just an example for all the other shortcuts), but maybe Windows does something in the background.
Subz Posted May 27, 2020 Posted May 27, 2020 Have been able to replicate the issue, but not really sure why it occurs, it appears to be an issue in Windows (seen other related posts on different forums), it's strange though, if I use FileCreateShortcut for 64-bit application (with 32 or 64 bit script) and then use FileGetShortcut, it returns "C:\Program Files\..." if I modify the shorcut for example change the "Start in:" it then returns "C:\Program Files (x86)\..". One way around it would be to use WMI, below is a quick example for both FileGetShortcut and WMI Win32_ShortcutFile class: #include <File.au3> Global $g_oComError = ObjEvent("AutoIt.Error", "_ComError") Global $g_aShortcut, $g_aShortcuts = _FileListToArrayRec(@StartMenuCommonDir, "*.lnk", 1, 1, 0, 2) If @error Then Exit For $i = 1 To $g_aShortcuts[0] $g_aShortcut = FileGetShortcut($g_aShortcuts[$i]) ConsoleWrite($g_aShortcut[0] & @CRLF & _ShortcutTarget($g_aShortcuts[$i]) & @CRLF & "---------------------------------------------" & @CRLF) Next Func _ShortcutTarget($_sShortcut) Local $oWMI = ObjGet("winmgmts:\\.\root\cimv2") Local $oScInstance = $oWMI.ExecQuery('Select * From Win32_ShortcutFile Where Name = "' & StringReplace($_sShortcut, "\", "\\") & '"') For $oScProperty In $oScInstance Return $oScProperty.Target Next EndFunc Func _ComError($_oComError) ConsoleWrite(@ScriptName & " (" & $_oComError.scriptline & ") " & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($_oComError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $_oComError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $_oComError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $_oComError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $_oComError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $_oComError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $_oComError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $_oComError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($_oComError.retcode) & @CRLF & @CRLF) EndFunc
HurleyShanabarger Posted May 27, 2020 Author Posted May 27, 2020 Thank you, that is a really nice solution. It lacks a little bit in speed compared to FileGetShortcut. I started to look into the lnk-file itself; there is a structure desription (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943) - maybe I will write a wrapper for it.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now