click here for a plain text version
#include-once

; corz registry functions v0.2.3
; (c) cor + corz.org 2006->tomorrow!

#cs

    Miscelleneous Registry Comands

    @Extended values..

        0 = directory (key)
        1 = REG_SZ
        2 = REG_EXPAND_SZ
        3 = REG_BINARY
        4 = REG_DWORD
        7 = REG_MULTI_SZ


    Function List..

        MakeLongRegPaths()
        GetContextCommands()
        KeyIsEmpty()
        ReturnAllSubkeys()
        ReturnAllValueNames()
        ReturnAllPairs()
        SetExplorerContextMenu()

#ce


; switch short (i.e "HKCU") registry paths, for "long" (i.e. "HKEY_CURRENT_USER") paths
; (doesn't AutoIt do this automatically yet?)..
func MakeLongRegPaths($reg_key)
    $reg_key = StringReplace($reg_key"HKCR""HKEY_CLASSES_ROOT")
    $reg_key = StringReplace($reg_key"HKCU""HKEY_CURRENT_USER")
    $reg_key = StringReplace($reg_key"HKU""HKEY_USERS")
    $reg_key = StringReplace($reg_key"HKLM""HKEY_LOCAL_MACHINE")
    $reg_key = StringReplace($reg_key"HKCC""HKEY_CURRENT_CONFIG")
    return $reg_key
endfunc


;
; GetContextCommands()
;
; return names of the context (right-click) commands
; of a particular file type as an "AutoIt array", that is,
; an array where the first value is the number of real
; values in the array (integer).
;
;    $array = GetContextCommands("txtfile")
;
func GetContextCommands($file_type)

    $file_type = "HKEY_CLASSES_ROOT\" & $file_type & "\Shell"
    local $dirs = ""
    local $y = 1
    while $y
        local $var = RegEnumKey($file_type$y)
        if @error <> 0 then exitloop
        if @extended = 0 then ; directory
            $dirs &= $var & "|"
        endif
        $y += 1
    wend
    if $dirs <> "" then
    $dirs = StringTrimRight($dirs, 1)
    return StringSplit($dirs"|")
    endif
endfunc


; returns true is a given registry key is empty..
;
; requires ReturnAllSubkeys() & ReturnAllValueNames()
;
func KeyIsEmpty($key)
    local $reg_test_array_k = ReturnAllSubkeys($key)
    local $reg_test_array_v = ReturnAllValueNames($key)
    if $reg_test_array_k[1] = "" and  $reg_test_array_v[1] = "" then
        return 1
    endif
endfunc


; ReturnAllSubkeys()
; returns all the subkeys of a registry key as an "AutoIt array" of key names..
; eg. $array = ReturnAllSubkeys("HKCU\SOFTWARE\corz")
;
; requires MakeLongRegPaths($reg_key)
;
func ReturnAllSubkeys($key)
    $key = MakeLongRegPaths($key)
    local $keys = ""
    local $x = 1
    while $x
        local $var = RegEnumKey($key$x)
        if @error <> 0 then exitloop
        if $var <> "" then $keys &= $var & "|"
        $x += 1
    wend
    $keys = StringTrimRight($keys, 1)
    return StringSplit($keys"|")
endfunc



; ReturnAllValueNames()
; returns all the names of a registry key as an "AutoIt array" of names..
; eg. $array = ReturnAllValueNames("HKCU\SOFTWARE\corz")
;
; requires MakeLongRegPaths($reg_key)
;
func ReturnAllValueNames($key)
    $key = MakeLongRegPaths($key)
    local $names = ""
    local $x = 1
    while $x
        local $var = RegEnumVal($key$x)
        if @error <> 0 then exitloop
        if $var <> "" then $names &= $var & "|"
        $x += 1
    wend
    ;if $names <> "" then
    $names = StringTrimRight($names, 1)
    return StringSplit($names"|")
    ;endif
endfunc



;
; ReturnAllPairs()
;
; returns all the name/value pairs from a registry key as a
; 2-dimensional "AutoIt array" of name/value pairs, starting at
; array[1][0]. array[0][0] contains the total number of pairs
; returned.  Empty registry values can be skipped by passing the
; optional second parameter as true.
;
;    ReturnAllPairs("HKCU\SOFTWARE\corz")
;
#cs
 ReturnAllPairs example:
;
; display programs that run at startup for all users..

#include "corz_registry.au3"

    $str = ""
    $foo = ReturnAllPairs("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run")
    for $i = 1 to $foo[0][0]
        $str &= "key: " & $foo[$i][0] & "    value: " & $foo[$i][1] & "    " & @LF
    next
    MsgBox (0, "These programs run at startup.."$str)
    exit

; or the whole lot..

    dim $startup_places[4] = _
    [    "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",            _
        "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",            _
        "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",        _
        "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx"    ]

    for $place in $startup_places
        $foo = ReturnAllPairs($place)
        for $i = 1 to $foo[0][0]
            $str &= $foo[$i][0] & " :    " & $foo[$i][1] & "    " & @LF
        next
    next
    MsgBox (0, "These programs run at startup.."$str)

#ce
func ReturnAllPairs($key$skip_empties=false)

    local $x = 1
    local $y = 1
    local $pairs[1][2]

    while $x
        local $var = RegEnumVal($key$x)
        if @error <> 0 then exitloop
        local $this_value = RegRead($key$var)
        if (not $skip_empties) or ($skip_empties and $this_value <> "") then
            redim $pairs[$y+1][2]
            $pairs[$y][0] = $var
            $pairs[$y][1] = $this_value
            $y += 1
        endif
        $x += 1
    wend

    $pairs[0][0] = $y - 1
    return $pairs

endfunc




;
; SetExplorerContextMenu
;
; This sets an Explorer context item for an application. It can be either the default
; command for a particular filetype, or else simply another command on the context menu.
;
; This function relies on my $my_name convention, where $my_name is a global variable
; containing a string which is the name of the application, used to create subkeys, etc.
;
; Uses KeyIsEmpty()    - Also in this collection.
;
; Parameters..
;
;        1. $ext                File Type extension to work with (minus the dot)
;        2. $switch            $ON or $OFF$GUI_CHECKED & $GUI_UNCHECKED, 1 or 4, whatever
;                            This switch enables or disables the explorer menu item, depending.
;        3. $default            True if you wish to set the Explorer default command $ON/$OFF
;        4. $menu_item        The string of text that will appear in the Explorer context menu
;                            Defaults to $my_name if left blank
;                            You can force the key name by putting it after a pipe character..
;                            e.g.. "Edit KeyBind Script|Edit"
;        5. $fallback        If no file type has been set for this file extension, you can
;                            specify one here. Will only be used if the file extension
;                            doesn't already have a type. It will not steal an extension.
;        6. $switches        Any switches you would like to place in the command-line
;                            (they are placed between <app> & <path>, with a space added at either side)
;
;        7. $app_override     Sets a different app as the default app. specify the full path to the app.
;                            Or provide the short name if the app is in the path, e.g. "notepad.exe"
;
;        8. $icon            Specify the full string: "C:\path\to\resource.exe,0"
;
;    
;    You can use Default as any value except the first.
;
;    If there are any issues, the function will set @Error to some non-zero value and return
;    a useful message as the return value, which you can use directly. Successful operartions
;    also return a message letting you know exactly what happened.
;
;
;    Here is an example of setting TWO context commands..
;
;    SetExplorerContextMenu("kc"$associate_kc_files, true, "Run The Script", _
;                                    "KeyBind Commands File""", @ScriptFullPath, @ScriptFullPath & ",4")
;    SetExplorerContextMenu("kc"$associate_kc_files, false, "Edit KeyBind Script|Edit"""""$user_editor)
;
;
;    Note the $associate_kc_files variable. If this is set to $ON and we run the two commands
;    above we setup the context menu. Set that variable to $OFF and the entire registry 
;    structure will be cleanly removed.
;
func SetExplorerContextMenu($ext$switch=$OFF$default=$OFF$menu_item="", _
                            $fallback="my-unique-key"$switches=""$app_override=""$icon="")

    if $switch = Default then $switch = $OFF
    if $default = Default then $default = $OFF
    if $menu_item = Default then $menu_item = ""
    if $fallback = Default then $fallback = "my-unique-key"
    if $switches = Default then $switches = ""
    if $app_override = Default then $app_override = ""
    if $icon = Default then $icon = ""
                            
    if not $ext then return SetError(1, 0, "no extension given")

    local $key = $my_name
    if not $menu_item then $menu_item = $my_name

    if $default = $ON then
        $key = "open"    ; set the default app for this file type
    else
        local $menu_array = StringSplit($menu_item"|")
        $menu_item = $menu_array[1]
        $key = $menu_array[2]
    endif

    local $reg1$reg2$reg3$reg4
    local $filextkey = "HKEY_CLASSES_ROOT\." & $ext
    local $file_type = RegRead($filextkey"")
    if not $file_type then $file_type = $fallback
    local $regbase = "HKEY_CLASSES_ROOT\" & $file_type
    local $shell = $regbase & "\shell"
    local $shellkey = $shell & "\" & $key
    local $BAX_key = $regbase & "\" & $my_name & "_Backup"
    local $my_app

    if $app_override then
        $my_app = $app_override
    else
        if @compiled then
            $my_app = @ScriptFullPath
        else
            $my_app = ".\" & $my_name & ".exe"
        endif
    endif

    ; user has this enabled.
    ;
    if $switch = $ON then

        debug("Adding Context Menu (" & $menu_item & ") for.. =>" & $ext & "<=", @ScriptLineNumber);debug

        local $extexist = RegRead($filextkey"")
        if not $extexist then
            RegWrite($filextkey"""REG_SZ"$file_type)
        endif

        ; check if it's still enabled..
        local $regexist = RegRead($shellkey & "\command""")
        if StringInStr($regexist$my_app) then return SetError(2, 0, "still enabled!")

        ; backup current key..
        local $bax1$bax2$bax3$bax4$old_val$old_key    ;    default shell command: "open"
        ; we don't simply set this to the \my_name command, because they could be two different commands.
        ; this is more flexible

        ; replacing default shell command..
        if $default = $ON then

            $old_key = RegRead($shell"")                                            ;    "open"    or "02.other_command", etc.
            $bax1 = RegWrite($BAX_key"""REG_SZ"$old_key)
            $old_val = RegRead($shell & "\" & $old_key"")                            ;    "DO THIS.."
            $bax2 = RegWrite($BAX_key"menu""REG_SZ"$old_val)
            $old_val = RegRead($shell & "\" &  $old_key & "\command""")            ;    C:\Program Files\other-apps\some-app.exe "%1"
            $bax3 = RegWrite($BAX_key"cmd""REG_SZ"$old_val)                    ;    "cmd" because "command" is reserved!
            $old_val = RegRead($regbase & "\defaulticon""")
            $bax4 = RegWrite($BAX_key"icon""REG_SZ"$old_val)

            if not $old_key then RegWrite($BAX_key"created""REG_SZ""yes")
            if not $bax1 or not $bax2 or not $bax3 or not $bax4 then return SetError(3, 0, "no backup")
        endif

        ; write new key..
        $reg1 = RegWrite($shellkey"""REG_SZ"$menu_item)
        $reg2 = RegWrite($shellkey & "\command""""REG_SZ", '"' & $my_app & '" ' & $switches & ' "%1"')
        if $default = $ON then RegWrite($shell"""REG_SZ""open")
        if $icon then RegWrite($regbase & "\defaulticon""""REG_SZ"$icon)
        if $reg1 and $reg2 then return SetError(0, 0, "Written OK!")



    else ; Switch OFF..

        debug("Removing Context Menu for.. =>" & $ext & "<=", @ScriptLineNumber);debug

        $regexist = RegRead($shellkey & "\command""")
        if not StringInstr($regexist$my_app) then return SetError(4, 0, "already off!")

        ; okay, reg is in place, let's restore backup, if available, or delete keys..
        local $old_key1$old_key2$old_key3$old_key4$old_key5

        ; default command..
        if $default = $ON then
            $old_key1 = RegRead($BAX_key"")
            $old_key2 = RegRead($BAX_key"menu")
            $old_key3 = RegRead($BAX_key"cmd")
            $old_key4 = RegRead($BAX_key"icon")
            $old_key5 = RegRead($BAX_key"created")

            ; restore backup registry values..
            if ($old_key1 and ($old_key2 or $old_key3 or $old_key4)) or $old_key5 then

                if $old_key5 <> "yes" then
                    if $old_key1 then
                        $reg1 = RegWrite($shell"""REG_SZ"$old_key1)
                        if $old_key2 then $reg2 = RegWrite($shell & "\" & $old_key1"""REG_SZ"$old_key2)
                        if $old_key3 then $reg3 = RegWrite($shell & "\" & $old_key1 & "\command""""REG_SZ"$old_key3)
                        if $old_key4 then $reg4 = RegWrite("HKEY_CLASSES_ROOT\" & $old_key1 & "\defaulticon""""REG_SZ"$old_key4)
                    endif
                endif

                if $reg1 and $reg2 and $reg3 and $reg4 then RegDelete($BAX_key)
                if $old_key5 = "yes" then
                    RegDelete($regbase)
                    RegDelete($filextkey)
                endif
                return SetError(0, 0, "SUCCESS!")
            endif
        else
        ; regular menu item, simply delete it..
            local $restored = RegDelete($shellkey)
            if $restored then return SetError(0, 0, "Deleted!")
        endif
    endif

    return SetError(-1, 0, "nothing happened!")
endfunc











#cs

    Changes:

        0.2

            Added..

                SetExplorerContextMenu()

            which I cooked up for LoopDropZ & MangleeZee. All yours!


        0.1

            A small selection of useful registry functions..

                MakeLongRegPaths()
                GetContextCommands()
                KeyIsEmpty()
                ReturnAllSubkeys()
                ReturnAllValueNames()
                ReturnAllPairs()


#ce
back to the source menu
test

Welcome to corz.org!

I'm always messing around with the back-end.. See a bug? Wait a minute and try again. Still see a bug? Mail Me!