Jump to content

_FileGetShortcutEx for LNK files that are Advertised Shortcuts


Recommended Posts

_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
Link to comment
Share on other sites

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

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

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