REBOL
Docs Blog Get-it

REBOL/SDK - Windows Registry Functions

SDK Documentation

Access to the Microsoft Windows registry.

Contents

Purpose
Registry Structure
Functions
Standard Key Handles
Create-Reg Function
Exists-Reg? Function
Set-Reg Function
Get-Reg Function
Delete-Reg Function
List-Reg Function
Unset-Reg-Funcs Function
Examples
Registry Keys in HTML
Registry Key Browser
Install Program
Uninstall Program
Check for Install

Purpose

The SDK extends REBOL with a subset of Windows registry access functions. These functions are useful for installing and uninstalling your REBOL programs and can also be used for storing important program configuration options within the registry (although to enable scripts to run on a variety of platforms, we recommend that values be stored in regular text files whenever possible).

Because these functions are intended primarily for program installation and configuration, they are not fully general purpose Windows registry operations; nevertheless, a broad range of registry operations can be performed with what is supplied.

Access the windows registry at your own risk. Be very careful with these registry functions. Mistakes can cause problems with your computer and even render it unbootable. The Windows registry access functions do not warn you about improper values or deletions, they just "do" it.

We strongly recommend that you backup your registry before using any of these functions. There are many ways to do so.

Also note that if you use these functions to access values other than those stored by REBOL, various programs save data in different formats. For example, one program may save a filename as a string, while another saves it as a binary value.

Registry Structure

For the purposes of writing REBOL installation programs, you do not need a deep knowledge of the registry. The functions we provide are easy to use. See Microsoft's documentation if you need a more complete description of the registry and how it works.

The Windows Registry is composed of three primary sections. Each of these sections includes a set of key-names and values, and each may contain groups of sub-keys (forming a tree, very similar to that of files and directories.) The HK letters are Microsoft's standard abbreviation for a "Handle to a Key".

HKLMHolds keys and values related to the local machine. This information is related to the computer as a whole (rather than for a specific user of the computer). HKLM includes information about the hardware, device drivers, services, security, and software application info.
HKUHolds values related to specific users. Each user gets different settings here. Includes information about user's control panel settings, keyboard layout, selected event sounds, and software application settings.
HKDDHolds dynamic data. This information is not saved to disk and is built each time the system is booted.

In addition to those areas above, there are a few sections that are important enough to have their own aliases. These point into the above structures.

HKCUCurrent user. Points into HKU at the current user.
HKCRClasses root. Points into HKLM software/classes.
HKCCCurrent config. Points into HKLM/config/profile.

For the purposes of REBOL application installation, HKCU (current user information) will be the most common, and it is the default for the functions described below.

Functions

The REBOL registry access functions have been designed to be consistent with the methods provided by Microsoft (thus making them easier to learn and understand relative to existing registry books and documentation).

However, one difference is that these functions will always close their registry access each time they are called. The registry is never left open, so you don't need to be concerned with registry corruption when errors in your code cause your program to stop.

These functions use and require standard access permissions to the registry. In some environments such as schools or businesses access to the registry may be restricted. In such cases if the user cannot login as the system administrator, then you may have no choice but to save your configuration information in local files, rather than in the registry.

Standard Key Handles

All of the functions below allow you to specify any one of the standard reserved handle mentioned above. They are provided as refinements. The list includes:

Refinement Description
/HKCU current user (default)
/HKCC current config
/HKCR classes root
/HKLM local machine
/HKDD dynamic data
/HKU user data

Create-Reg Function

Create a registry key. The function syntax is:

create-reg key

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

The function returns TRUE if it was successful, or FALSE if it failed.

A typical example using create-reg to install a new "Product" made by "Maker":

either create-reg "Software\Maker\Product" [
    print "key added"
][
    print "cannot add key - contact administrator"
]

Notes:

Exists-Reg? Function

Return TRUE if the key exists, else return FALSE. The syntax is:

exists-reg? key

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

This function provides an efficient way to detect if your product has been installed (to prompt for installation if necessary). For example:

if not exists-reg? "Software\Maker\Product" [
    print "product has not been installed"
]

Set-Reg Function

Set a value within a key. The syntax is:

set-reg key name value

This function stores data in a new or existing value field of an existing registry key.

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

The name is a a string containing the name of the value to set. If the name does not already exist in the key, it will be added.

For example, to add a value to the key created in the prior section:

set-reg "Software\Maker\Product" "version" "1.2.0"

Notes:

Get-Reg Function

Get a value from within a key. The syntax is:

value: get-reg key name

This function retrieves data from an existing value field of a registry key.

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

The name argument is a string containing the name of the value to fetched. If either the key or the name do not exist, a NONE value is returned.

This example fetches and prints the value stored in the previous section:

value: get-reg "Software\Maker\Product" "version"
print value

Notes:

Delete-Reg Function

Delete a registry key. The syntax is:

delete-reg key

This function removes the specified key from the registry including all of its values.

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

A TRUE is returned on success and a FALSE is returned on failure.

Notes:

List-Reg Function

Returns subkeys for an existing key. The syntax is:

keys: list-reg key

This function returns a block that contains the names of all subkeys that belongs to the specified key. The order of the subkeys is not specified and may vary.

The key is a string that describes a path within the registry. The path uses backslashes "\" rather than forward slashes to specify higher level keys. The path is relative to HKCU (current user) unless another refinement is used.

This example will print the names of all keys found in the current user software key:

foreach key list-reg "software" [
    print key
]

If the key does not exist, a NONE is returned.

Unset-Reg-Funcs Function

Disable the above functions. Syntax is:

unset-reg-funcs

This function will remove all of the above functions from REBOL. This should be done for security purposes when your code no longer needs these functions after boot each time.

Examples

These are provided as simple examples for your use and revision. Verify the proper operation of all examples before using them in your applications. It is suggested that you backup your registry before experimenting with these functions. REBOL Technologies will not be responsible for damage to your system.

Registry Keys in HTML

This program creates an HTML file that shows all subkeys for your current user (HKCU) software key.

Note that this output can get rather large on systems that have a lot of software installed.

REBOL [Title: "Dump Registry Keys in HTML"]

html: make string! 2040
emit: func [data] [append repend html data newline]

emit-reg-keys: func [path /local keys] [
    if not keys: list-reg path [exit]
    emit <UL>
    foreach key keys [
        emit [<LI> key]
        emit-reg-keys rejoin [path pick ["" "\"] empty? path key]
    ]
    emit </UL>
]

title: "Registry Dump for Current User Software" 

emit [
    <HTML>
    <TITLE> title </TITLE>
    <BODY BGCOLOR="WHITE">
    <H2> title </H2>
]

emit-reg-keys "Software"

emit [
    </BODY>
    </HTML>
]

write %reg-out.html html
;browse %reg-out.html

Registry Key Browser

The following example lets you interactively browse the keys of the local machine (HKLM) section of the registry:

REBOL [Title: "Registry SubKey Browser"]

list-reg-path: func [path /local keys val n] [
    print ["Keys for:" mold path]

    ;-- Get list of subkeys:
    if not keys: list-reg/HKLM path [
        print ["Invalid key:" path]
        clear any [find/reverse tail path "\"  path]
        list-reg-path path
        exit
    ]

    ;-- Print subkey list:
    n: 1
    foreach key keys [
        print [n "-" key]
        n: n + 1
    ]

    ;-- Ask user for subkey:
    val: ask "Key number, enter to backup, escape to quit: "
    either integer? attempt [val: load val] [
        if val: pick keys val [
            if not empty? path [append path "\"]
            append path val
            list-reg-path path
        ]
    ][
        clear any [find/reverse tail path "\"  path]
        list-reg-path path
    ]
]

list-reg-path ""

Install Program

Here is the main function for installing a new program in the registry. It adds HOME, VERSION, and DATE registry values to a new key that it creates in the current user software subkeys. (This is nearly identical to how REBOL products install themselves).

This function will also set up an "uninstall" entry (for add/remove programs). The uninstall calls your program with a -u option, which you must provide.

;-- Primary software keys:
ms-base: "Software\Microsoft\Windows\CurrentVersion"
ms-uninstall: join ms-base "\Uninstall\"

;-- Function to build our key:
reg-base: func [maker name] [
    rejoin ["Software\" maker #"\" name #"\"]
]

register: func [
    "Install program by setting registry values."
    maker [string!] "company name"
    name [string!] "application name"
    version [tuple!] "application version"
    home [file!] "application home directory"
    target [file!] "application executable file"
    /local key
][
    ;-- Create the uninstall link (optional):
    key: join ms-uninstall reform [maker name]
    if not create-reg/hklm key [return false]
    set-reg/hklm key "DisplayName" reform [maker name]
    set-reg/hklm key "UninstallString" rejoin [
        {"} to-local-file target {" -u}
    ]

    ;-- Create main registry key:
    key: reg-base maker name
    if not create-reg key [return false]
    set-reg key "Home" form to-local-file home
    set-reg key "Version" form version
    set-reg key "Date" form now
    return true
]

The function will return TRUE on success and FALSE on failure.

Uninstall Program

Here is a simple uninstaller function. It will remove the key for an application as installed above, and will remove the company key if it is empty as a result.

Due to inconsistent Microsoft Windows registry API implementations (between 98 and NT versions), the following function is required to delete subkeys:

delete-keys: func [
    "Recursively delete registry keys."
    path ; registry path
    /hklm
    /local keys
][
    keys: either hklm [list-reg/hklm path] [list-reg path]
    if none? keys [exit]
    foreach key keys [
        delete-keys rejoin [path #"\" key]
    ]
    either hklm [delete-reg/hklm path] [delete-reg path]
]

Here is the uninstaller function:

uninstall: [
    "Uninstall the program from Windows registry."
    maker [string!] "company name"
    name [string!]  "application name"
    /local keys
][
    if not confirm rejoin [
        "Please confirm that you want to uninstall " name "."
    ][quit]

    ;-- Remove product key:
    delete-keys reg-base maker name

    ;-- Find all products. Delete base key if no more products.
    keys: list-reg join "Software\" maker
    if all [keys empty? keys] [delete-keys join "Software\" maker]
    delete-keys/hklm join ms-uninstall reform [maker name]
]

Check for Install

This function can be called each time your application starts to determine if it needs to be installed. It also checks for the +i and -i options (+i for reinstall and -i for do not install).

The function will return TRUE if installation is required, and you can call the Register function described above.

install?: func [
    "Return true if program needs to be installed."
    maker [string!] "company name"
    name [string!]  "application name"
    version [tuple!] "current version"
    /local vers program-args
][
    program-args: system/options/args

    ;-- Reinstall option +i specified. Always force reinstall.
    if all [block? program-args find program-args "+i"][return true]

    ;-- Command line -i option forces program to run w/o installing
    if all [
        block? program-args
        find program-args "-i"
    ][return none]

    vers: attempt [load get-reg reg-base maker name "Version"]

    ;-- If the reg version is less than the current version,
    ;   then a reinstall will happen.
    any [
        system/options/install = 1  ; command line reinstall flag
        not tuple? vers ; invalid version, force reinstall
        version > vers ; older version, force reinstall
    ] ; returns NONE otherwise
]

This function can be called to check for the uninstall (-u) option:

uninstall?: has [program-args] [
    "Return true if program needs to be uninstalled."
    program-args: system/options/args
    any [
        all [
            block? program-args
            find program-args "-u"
        ]
    ]
]
About | Contact | PrivacyREBOL Technologies 2024