Jump to content

get the "shortcut keys" of a shortcut (.lnk file)


Recommended Posts

hello all,

my script deploys some files to target machine, and using FileCreateShortcut it creates a shortcut (.lnk file) with a shortcut keys combination.

as part of a validation process, i'm trying to retrieve the shortcut keys combination of the created shortcut.

the internal FileGetShortcut does not return it.

the deployment is silent and done remotely, so it's not possible to open the "Properties" and capture the text in the "Shortcut Key" control.

i found _FileGetShortcutEx by Ascend4nt:

'?do=embed' frameborder='0' data-embedContent>>

but (so i understand it) it does not return more details than the internal FileGetShortcut, only details of shortcuts that are not covered by it.

ideas?

thanks,

orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Shhh :shhh: , its a secret:

$sShortcutFile = "C:\MyShortcut.lnk"
$nShortcutKey = Number(StringToBinary(StringMid(FileRead($sShortcutFile, 68), 65, 4)))
ConsoleWrite("Shortcut key = " & $nShortcutKey & @CRLF)

 

Well not really a secret.  Just make sure its an actual shortcut file, otherwise that code is undefined.  The reason I know the offset is because of a LNK Info display program I wrote..

Link to comment
Share on other sites

top cool! i tried to parse the content of the .lnk file myself, but couldn't make anything of it...

but now, what does the result mean? for example, my shortcut is Ctrl+Alt+Shift+U, which your script parses as the number 1877. i can use that well enough for validation, but just for interest, how do you translate that to a string like !+^U ?

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Here's a description of what the value contains (you need to examine the low byte for the key):

IShellLink::GetHotkey

Since MSDN likes to leave out values for things and links to other help, here u go:

#define HOTKEYF_SHIFT           0x01
#define HOTKEYF_CONTROL         0x02
#define HOTKEYF_ALT             0x04
#define HOTKEYF_EXT             0x08

Virtual-Key Codes

Keyboard Input Functions (including those dealing with Virtual Key codes)

Ah, and here's one of the sites I got info on the LNK format (now at archive.org):

Shortcut File Format (LNK) - Stdlib.com

Link to comment
Share on other sites

Here's an example of how to get basic modifiers and convert Virtual-Key codes into ASCII characters.  Note that special keys (arrow keys) and function keys won't be able to be converted to strings so easily.  For that you'd need to write a custom converstion function.  But this does the job for simple combinations:

$sShortcutFile = "C:\MyShortcut.lnk"
$nShortcutKey = Number(StringToBinary(StringMid(FileRead($sShortcutFile, 68), 65, 4)))
ConsoleWrite("Shortcut key = 0x" & Hex($nShortcutKey,4) & ", Upper byte = 0x" & Hex(BitShift($nShortcutKey, 8), 2) & @CRLF)

; Upper byte required for this
$sAutoItModifiers = _KeyModifiersToString(BitShift($nShortcutKey, 8))
; False for this call to get the full descriptive key combination
$sModifiers = _KeyModifiersToString(BitShift($nShortcutKey, 8), False)
; Mask off the virtual-key code (lower byte)
$cChar = _KeyVirtualKeyToChar(BitAND($nShortcutKey, 0xFF))

ConsoleWrite("Modifiers: " & $sModifiers & ", Char: '" & $cChar & "', AutoIt Send() Sequence = """ & $sAutoItModifiers & $cChar & '"' & @CRLF)

; ==============================================================================================
; Func _KeyModifiersToString($nModifiers, $bSendType = True)
;
; Convert modifiers to a string of characters, either AutoIt Send() style,
; or full descriptive key combo style ("SHIFT+CTRL"..)
;
; $nModifiers = Modifier value
;  This is a combo of any of these values:
;   HOTKEYF_SHIFT     0x01
;   HOTKEYF_CONTROL   0x02
;   HOTKEYF_ALT       0x04
;   HOTKEYF_EXT       0x08  ; This is used primarily for extended VK keys
;
; $bSendType = If non-zero or True (default, returns Send()-style key combo
;   Otherwise a full descriptive key combo string is returned ("SHIFT+CTRL"..)
;
; Returns:
;  Success: A string representing either the AutoIt modifiers, or a full descriptive key-combo
;           (depending on $bSendType)
;  Failure: none. An empty string means no modifiers were found
;
; Author: Ascend4nt
; ==============================================================================================

Func _KeyModifiersToString($nModifiers, $bSendType = True)
    Local $sModifiers = ""
    Local $sAutoItModifiers = ""
    ; SHIFT?
    If BitAND($nModifiers, 1) Then
        $sModifiers &= "SHIFT+"
        $sAutoItModifiers &= '+'
    EndIf
    ; CONTROL?
    If BitAND($nModifiers, 2) Then
        $sModifiers &= "CTRL+"
        $sAutoItModifiers &= '^'
    EndIf
    ; ALT?
    If BitAND($nModifiers, 4) Then
        $sModifiers &= "ALT"
        $sAutoItModifiers &= '!'
    EndIf
    If $bSendType Then Return $sAutoItModifiers
    ; Else
    If StringRight($sModifiers, 1) = '+' Then $sModifiers = StringTrimRight($sModifiers, 1)
    Return $sModifiers
EndFunc


; ==============================================================================================
; Func _KeyVirtualKeyToChar($nVKCode)
;
; Converts a Virtual-Key code to an ASCII character, if possible.
;  The exceptions are special keys like Arrow keys, function keys, etc, which return as ""
;
; $nVKCode = virtual key code
;
; Returns:
;  Success: Either "" for non-matching character, or the character itself. @error = 0
;  Failure: "" with @error set
;
; Author: Ascend4nt
; ==============================================================================================

Func _KeyVirtualKeyToChar($nVKCode)
    Local $aRet, $cChar = ""
    $aRet = DllCall("user32.dll", "uint", "MapVirtualKeyW", "uint", $nVKCode, "uint", 2)
    If @error Then Return SetError(2, @error, "")
    If $aRet[0] <> 0 Then
        $cChar = Chr(BitAND($aRet[0], 0xFF))
    EndIf
    Return $cChar
EndFunc

*edit: addede @error return for DLLCall failure

Edited by Ascend4nt
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...