REBOL/SDK - Windows Registry Functions
Access to the Microsoft Windows registry.
Contents
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.
- Run the ScanReg program provided by Microsoft (note that windows will run this program automatically once a day).
- Use RegEdit to save a .reg file with the contents of the registry.
- Use the Microsoft backup utility.
- Manually copy your system.dat and user.dat files if necessary.
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".
HKLM | Holds 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. |
HKU | Holds 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. |
HKDD | Holds 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.
HKCU | Current user. Points into HKU at the current user. |
HKCR | Classes root. Points into HKLM software/classes. |
HKCC | Current 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:
- The newly created key will have no values, but you can use the set-reg function described below to set specific key values.
- Note that you cannot create keys directly under HKU or HKLM.
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:
- If the registry key does not exist, this function returns NONE.
- If a binary datatype is provided at the value, the registry entry will be tagged as a binary type.
- BETA 1 version of this function does not properly handle registry datatypes other than string and binary values. This will be fixed in a future BETA release.
- If the value string is longer than 2048 bytes, it should be stored a file with the filename stored in the registry. This helps the registry perform efficiently. Do not store application elements such as icons, bitmaps, and executable files in the registry.
- If the name field is an empty string this function sets the default value stored for the key. (A Win95 compatibility option).
- If the value begins with a "%", it will be treated specially and marked as expanded reference to an environment variable. When the value is fetched with get-reg, it will automatically be expanded.
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:
- BETA 1 version of this function does not properly handle registry datatypes other than strings. This will be fixed in a future BETA release.
- If environment-variables are stored as part of the value field, this function will expand them according to the Windows ExpandEnvironmentStrings function.
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:
- The behavior of this function varies between versions of the Windows operating system. For example, under 95 type systems, this function deletes a key and all its descendents. Under NT systems, the function deletes the specified key and will not delete a key that has subkeys (you will need to do that manually yourself).
- We will be providing a delete-reg/deep refinement in a future BETA release to solve the above problem.
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" ] ] ]