Jump to content

Recommended Posts

Posted (edited)

_FileGetShortcutEx()

[This code is not mine, but rather from a guy who goes by "Prog@ndy".]

(I couldn't post this in the Examples forum because I don't have access (??), so I'm putting it here)

Okay, so, I was looking all over for a reason why 'ShellExecute()' works for most but not all shortcuts (it would give me a "The parameter is incorrect" error), and found out some LNK's are just "Advertised Shortcuts" made by MSI installations. Well I guess it gets a little complex to figure out what it all means, it's just not a real shortcut to the actual program but to some other program that deals with shortcuts & installs?!.. blah, someone else would know what the heck it is.

Anyway, a 'FileGetShortcut()' call by itself would normally give you a path to the executable, but thats not the case with Advertised Shortcuts - it usually gives back a path to some odd install executable.

So, since I had to search for this code a bit, and found that it only exists in a cached form off some website, I figured I'd post it here since it has helped solve a number of problems for me :D

Again, all this code was posted on a forum by a guy that went by 'Prog@ndy', so all credit goes to him:

#include <String.au3>

;===============================================================================
;
; Function Name: _FileGetShortcutEx($link)
; Description:: Gets information from a ShortcutFile and gets the Path of MSi installed Shortcuts, too
; Parameter(s): $link : Path of the Shortcut
; Requirement(s): ?
; Return Value(s): Success: Array like FileGetShortcut
;            Error: 0
; Error Code(s): like FileGetShortCut()
;
; Author(s): Prog@ndy
;
;===============================================================================
;
Func _FileGetShortcutEx($link)
    Local $lnk = FileGetShortcut ($link )
    If @error Then Return SetError(@error,0,0)
    Local $msitest = _MSIShortcutTarget($link)
    If Not @error Then $lnk[0] = $msitest
    Return $lnk
EndFunc


;===============================================================================
;
; Function Name: _MSIShortcutTarget($link)
; Description:: Gets the Path from a Shrtcut created with MSI
; Parameter(s): $link : Path of the Shortcut
; Requirement(s): ?
; Return Value(s): Success: Executable Path
;            Error: 0
; Error Code(s): 1-3 : like DllCall
;            4 : Path does not exist OR it's not a MSI Shortcut
;            5 : Component is not installed (correctly)
;
; Author(s): Prog@ndy
;
;===============================================================================
;

Func _MSIShortcutTarget($link)
    Local Const $MsiDllName             = 'msi.dll'
    Local Const $INSTALLSTATE_ABSENT = 2; ;// uninstalled
    Local Const $INSTALLSTATE_LOCAL     = 3; ;// installed on local drive
    Local Const $INSTALLSTATE_SOURCE = 4; ;// run from source, CD or net
    Local Const $INSTALLSTATE_SOURCEABSENT = -4; ;// run from source, source is unavailable
    Local Const $INSTALLSTATE_NOTUSED = -7; ;// component disabled
    Local Const $INSTALLSTATE_INVALIDARG = -2; ;// invalid function argument
    Local Const $INSTALLSTATE_UNKNOWN = -1; ;// unrecognized product or feature
    Const $ERROR_SUCCESS = 0
    Local $500Chr0 = _StringRepeat(Chr(0),500)
    Local $shortcut,$szComponentCode,$szFeatureId,$szProductCode,$installstate
    
    $shortcut = Dllcall($MsiDllName,"int","MsiGetShortcutTarget","str",$link,"str",$500Chr0,"str",$500Chr0,"str",$500Chr0)
    If @error Then Return SetError(@error,0,0)
    If $shortcut[0] <> $ERROR_SUCCESS Then Return SetError(4,0,0)
    $szProductCode = $shortcut[2]
    $szFeatureId = $shortcut[3]
    $szComponentCode = $shortcut[4]
    $installstate = Dllcall($MsiDllName,"int","MsiGetComponentPath","str",$szProductCode,"str",$szComponentCode,"str",$500Chr0,"dword*",500)
    If @error Then Return SetError(@error,0,0)
    If $installstate[0] = $INSTALLSTATE_LOCAL Or $installstate[0] = $INSTALLSTATE_SOURCE Then
        Switch StringLeft($installstate[3],3)
            Case "00:","20:"
                $installstate[3] = "HKEY_CLASSES_ROOT" & StringMid($installstate[3],4)
            Case "01:","21:"
                $installstate[3] = "HKEY_CURRENT_USER" & StringMid($installstate[3],4)
            Case "02:","22:"
                $installstate[3] = "HKEY_LOCAL_MACHINE" & StringMid($installstate[3],4)
            Case "03:","23:"
                $installstate[3] = "HKEY_USERS" & StringMid($installstate[3],4)
        EndSwitch
        Return $installstate[3]
    EndIf
    Return SetError(5,0,0)
EndFunc

*edit: see new advanced version in Example scripts under the same name: _FileGetShortcutEx

Edited by Ascend4nt

My contributions:

  Reveal hidden contents

Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFsProcess CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen)Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery

Wrappers/Modifications of others' contributions:

_DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity)

UDF's added support/programming to:

_ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne)

(All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)

Posted

Nice first post :D Wellcome!

Here is a _ShellExecuteEx() function that allow to execute not standard shortcuts:

_ShellExecuteEx(@AppDataDir & "\Microsoft\Internet Explorer\Quick Launch\Microsoft Office Word 2003.lnk")

Func _ShellExecuteEx($sCmd, $sArgs = "", $sFolder = "", $sVerb = "", $iState = @SW_SHOWNORMAL, $hWnd = 0)
    Local $stINFO = DllStructCreate("long;long;long;ptr;ptr;ptr;ptr;long;long;long;ptr;long;long;long;long")
    Local $stVerb = DllStructCreate("char[15];char")
    Local $stPath = DllStructCreate("char[255];char")
    Local $stArgs = DllStructCreate("char[255];char")
    Local $stWDir = DllStructCreate("char[255];char")
    
    DllStructSetData($stVerb, 1, $sVerb)
    
    DllStructSetData($stPath, 1, $sCmd)
    DllStructSetData($stWDir, 1, $sFolder)
    DllStructSetData($stArgs, 1, $sArgs)

    DllStructSetData($stINFO, 1, DllStructGetSize($stINFO))
    DllStructSetData($stINFO, 2, BitOR(0xC, 0x40, 0x400))
    DllStructSetData($stINFO, 3, $hWnd)
    DllStructSetData($stINFO, 4, DllStructGetPtr($stVerb))
    DllStructSetData($stINFO, 5, DllStructGetPtr($stPath))
    DllStructSetData($stINFO, 6, DllStructGetPtr($stArgs))
    DllStructSetData($stINFO, 7, DllStructGetPtr($stWDir))
    DllStructSetData($stINFO, 8, $iState)

    Local $aRet = DllCall("shell32.dll", "int", "ShellExecuteEx", "ptr", DllStructGetPtr($stINFO))
    If Not IsArray($aRet) Or Not $aRet[0] Then Return SetError(2, 0, 0)
    
    Return 1
EndFunc

 

  Reveal hidden contents

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Posted (edited)

Wow, that's even better, hehe. I guess the two will have their uses, but now I'm not sure - would both be supported on Windows 98 without checking that ShellExecuteEx() is available? According to Microsoft's website:

Windows 95/98/Me: ShellExecuteEx is supported by the Microsoft Layer for Unicode (MSLU). To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

website: http://msdn2.microsoft.com/en-us/library/bb762154.aspx

I don't use Windows 98, but I have those people in mind when building code.. and it seems the "_MSIShortcutTarget($link)" would fail if msi.dll isn't present (which I would assume would mean MSI Installer isn't installed and there shouldn't be Advertised Shortcuts)? Or am I wrong to assume all that?

I think shell32.dll exists on all of these machines by default doesn't it? If so, would the function call fail on a machine without 'MSLU'?

Thanks for this - and thanks for your help and the code. Very cool :D

(thanks for the welcome to. Hi everyone! :D )

Edited by ascendant

My contributions:

  Reveal hidden contents

Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFsProcess CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen)Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery

Wrappers/Modifications of others' contributions:

_DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity)

UDF's added support/programming to:

_ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne)

(All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...