Lesson 3: Accessing the Registry

The Windows registry is a central, hierarchically organized database that holds persistent configuration information for the operating system and for applications. On Windows NT, Windows 95, and Windows 98, the registry provides a secure alternative to the .ini configuration files used by 16-bit Windows platforms. In this lesson, you will learn how to use the registry to save and retrieve user settings for a Windows application.

After this lesson, you will be able to:

  • Recognize the registry's basic organizational structure.
  • Understand how MFC supports programmatic access to the registry and how you can use these features to store and retrieve application settings.
  • Describe the circumstances under which you might use the Win32 API to access the registry, and the principal functions that enable you to perform this action.
Estimated lesson time: 40 minutes

Registry Data

The registry is used to store configuration information for the operating system and settings for applications. It is used to store everything from the IP address of installed network cards to the Regional Settings found in the Control Panel to the view mode (Scientific or Standard) of the Windows calculator. As a result, the registry typically contains at least several megabytes of data.

To facilitate manipulating such large amounts of data, the logical view of the registry is that of a hierarchy. While the underlying physical structure of the files constituting the registry is different under Windows NT than under Windows 95 and Windows 98, the Win32 API hides these differences from users and developers by providing a consistent interface for storing and retrieving registry settings. However, before attempting to programmatically manipulate the registry, you should become familiar with the registry hierarchy. A good way to do that is through the registry editor.

The registry editor for Windows 95 and Windows 98 is regedit.exe, which can be found in the Windows directory. Windows NT users will find an additional registry editor—regedt32.exe—in the Winnt\System32 directory. Regedt32.exe has some additional features useful under Windows NT. (It is able to set security for registry keys and to view or edit the REG_EXPAND_SZ and REG_MULTI_SZ data types.) Most users prefer the search features of regedit, but for exploration under Windows NT, the read-only mode of regedt32 affords the beginning programmer an added level of protection against accidentally corrupting the registry.

CAUTION
Improper editing of your registry entries could cause your applications to stop working, and could even permanently cause your operating system to become unavailable. Before editing the registry, you should first back up the registry files. With Windows 95, you should make copies of System.dat and User.dat, both of which are hidden files in the Windows folder. With Windows NT, you should create an updated Emergency Repair Disk. Consult your operating system documentation for more details.

  • To explore the registry (Windows NT)
    1. On the Start menu, click Run.
    2. In the Open box, type regedt32 and click OK.
    3. The registry editor opens as shown in Figure 6.2.

      click to view at full size.

      Figure 6.2 Exploring the registry using RegEdt32

    4. On the registry editor Options menu, select Read Only Mode.

  • To explore the registry (Windows 95 and Windows 98)
    1. On the Start menu, click Run.
    2. In the Open box, type regedit and click OK.
    3. The registry editor opens as shown in Figure 6.3.

      click to view at full size.

      Figure 6.3 Exploring the registry using RegEdit

    Registry Organization

    The registry is organized as a hierarchically structured database. At the root of the hierarchy is a set of predefined subtrees, which correspond to the most general categories of the system's organization. Notice how the two editors differ in the way they display the subtrees. RegEdit displays all of the subtrees in a single window, descended from a common root. RegEdt32 displays each subtree in its own window.

    Table 6.3 illustrates the five subtrees common to the Windows platforms.

    Table 6.3 Windows 95, Windows 98, and Windows NT Subtrees

    Key name Purpose
    HKEY_CLASSES_ROOT Contains software configuration information. Includes file name extension/application associations, drag and drop protocols, printing configurations, and COM configuration information.
    HKEY_CURRENT_USER Contains user-specific settings for the system. This subtree is created when the user logs on, loaded with information from the user's entry in HKEY_USERS, and deleted when the user logs off.
    HKEY_LOCAL_MACHINE Contains specifications for the computer, drivers and other system set- tings for installed hardware. Entries in this section are shared by all users of the computer.
    HKEY_USERS Contains information about all users who log on to the computer. Includes both user-specific information and generic user information. Generic system settings are available to all users of the system.
    HKEY_CURRENT_CONFIG Contains configuration data for the hardware profile currently in use on the computer.

    If you are working on a Windows 95 or Windows 98 computer, you will see the additional subtree HKEY_DYN_DATA, used to store dynamic data such as performance statistics and plug and play information.

    The subtrees contain keys that can act as containers for other keys. Keys are similar to directory folders in the way that they can be nested, and are referenced using a similar notation. Figure 6.4 shows RegEdt32 being used to view the HKEY_CURRENT_USER\Software\MyCompany\MyApp\Settings key.

    click to view at full size.

    Figure 6.4 Exploring registry keys

    Keys can contain values as well as subkeys. Values are terminating leaf nodes in the registry hierarchy which are used to store registry data. Figure 6.4 shows the User Name value contained within the Settings key.

    A value has three parts—the name, the data type, and the value itself. A key might contain a single unnamed value that serves as the default value for the key. For the sake of clarity however, you should give your registry values names that give a clear indication of their function.

    Windows defines a special set of registry data types. Some of the more commonly used registry data types are shown in Table 6.4.

    Table 6.4 Registry Data Types

    Data type Use
    REG_DWORD A 32-bit number.
    REG_BINARY Binary data in any form.
    REG_SZ A null-terminated string.
    REG_MULTI_SZ An array of null-terminated strings, terminated by two null characters.
    REG_EXPAND_SZ A null-terminated string that contains unexpanded references to environment variables.

    You can see the complete list of registry data types by searching for "RegSetValueEx"—the Windows API function used to set the value and data type of a registry value—in the Visual C++ Help file.

    MFC Support for the Registry

    A document/view application generated by the MFC AppWizard creates the following registry entries:

    • An entry that enables the Windows file manager to associate the application document type with the application. This enables the user to launch an application by double-clicking on a document icon.
    • An entry that determines the location of the application user profile. The user profile is used to store a user's application settings in the registry, so that the user settings can be preserved between application sessions.

    The following sections explain how these registry entries are created, and how they can be used.

    Registering Document Types

    To register an application's document type with the Windows file manager, the AppWizard adds the following line of code to your application object's InitInstance() function:

    RegisterShellFileTypes(TRUE);

    CWinApp::RegisterShellFileTypes() iterates through the list of document templates that the application maintains and adds file association entries to the HKEY_CLASSES_ROOT registry subtree for each document template. RegisterShellFileTypes() also adds an entry specifying a default icon for the document type.

    Since the shell identifies a document type on the basis of its file name extension, you must be sure to specify a document file name extension for your application on the Advanced Options screen in Step 4 of the AppWizard. If you fail to specify an extension, RegisterShellFileTypes() will not be called.

    RegisterShellFileTypes() is called with a TRUE parameter to specify that registry entries should be added for the shell commands Print and Print To, allowing a user to print files directly from the shell, or by dropping the file on a printer object.

    The AppWizard creates a registry file (with a .reg extension) that you can use in conjunction with a setup program to perform registry updates at installation time. Using a registry file in this manner is advantageous because you can instruct the setup program to remove its registry entries if the program is uninstalled, which contributes to more efficient application management. If you omit a file name extension for your document type, no .reg file is created.

    NOTE
    If you specify that your application should be Compound Document Server, additional code is added to your application's InitInstance() function to create OLE-related registry entries.

    Application User Profile

    To specify the location of the application's user profile settings, the AppWizard adds the following code line to your application object's InitInstance() function:

    SetRegistryKey(_T("Local AppWizard-Generated Applications"));

    CWinApp::SetRegistryKey() is called with a parameter that specifies the name of the key under which your application settings will be stored. This key will be created under the HKEY_CURRENT_USER\Software key. You should replace the default key name (Local AppWizard-Generated Applications) with a suitable name for a key containing user profile settings for all of your applications. Typically, this name is the name of the company developing the application.

    NOTE
    If you remove the call to SetRegistryKey() from your InitInstance() function, the framework will create an .ini file in the Windows directory and use it to store (non user-specific) profile information. The .ini files are a feature of 16-bit Windows, and should not be used for 32-bit applications.

    In the following exercise, you will specify a registry key for use in storing application user profile settings for the MyApp application.

  • To set the name of the user profile registry key
    1. Open the MyApp project.
    2. In ClassView, expand the CMyAppApp class icon.
    3. Double-click the InitInstance() member function to edit the code.
    4. Approximately 20 lines into the function, locate the code that reads:
    5. SetRegistryKey(_T("Local AppWizard-Generated Applications"));

    6. Edit the line so that it reads:
    7. SetRegistryKey(_T("MyCompany"));

    8. Build and run the MyApp application.

    Complete the following steps to check that the application has created the key correctly.

  • To locate the user profile registry key
    1. Ensure that you have built and run the MyApp application at least once after specifying a user profile registry key.
    2. Close the MyApp application. On the Start menu, click Run.
    3. In the Open box, type RegEdt32 if you are using Windows NT or RegEdit if you are using Windows 95 or Windows 98. Click OK.
    4. Locate the HKEY_CURRENT_USER subtree.
    5. Double-click the Software key to expand it. Verify that the following key has been created by the MyApp application:
    6. HKEY_CURRENT_USER\Software\MyCompany\MyApp\Settings

    NOTE
    The SetRegistryKey() function creates a registry key with the same name as the application to serve as a root location for the application settings.

    MFC applications write to the application user profile using the MFC profile management functions. These functions, all members of the CWinApp class, are:

    • WriteProfileString()
    • GetProfileString()
    • WriteProfileInt()
    • GetProfileInt()

    These functions store and retrieve string and integer values to and from your application's profile key in the registry. All of these functions take a section name (a subkey of your profile key), and a value name as the first two arguments. If the section or value names do not exist, they are created.

    WriteProfileString() creates a REG_SZ value. WriteProfileInt() creates a REG_DWORD value. Both functions return a BOOL value to indicate the success or failure of the write operation. Both functions take a third argument specifying the actual value to be written.

    For example, the following line:

    WriteProfileString("Settings", "User Name", "Julian");

    will create the HKEY_CURRENT_USER\Software\MyCompany\MyApp\Settings\User Name value, which is assigned the string "Julian." This value is illustrated in Figure 6.4.

    GetProfileString() and GetProfileInt() return a specified value from the registry. Both functions take a third argument that specifies a default value to be returned if the requested registry value cannot be found.

    Working with Application User Profile Settings

    In this exercise, you will learn how to use the MFC profile management functions to save MyApp application settings to the HKEY_CURRENT_USER\Software\MyCompany\MyApp profile key that you created in the previous exercise. This exercise will work with the Connect to Data Source dialog box that you created by completing the exercises in Chapters 4 and 5.

    The Connect to Data Source dialog box contains a check box option that allows users to specify if they want to attempt to connect at application startup.

  • To implement the Connect at Application Startup option
    1. Save the Data Source Name, the User ID, the Access level and the status of the Attempt to connect at application startup check box to the registry. These settings will be saved after the user clicks the Connect button.
    2. Use the settings saved in the registry to initialize the Connect to Data Source dialog box controls.
    3. Alter the InitInstance() function to retrieve the Attempt to connect at application startup check box status. If this check box has been selected, display the Connect to Data Source dialog box to allow the user to connect to the database.

  • To save the dialog box settings
    1. In the MyApp project, locate the CMyAppApp::OnDataConnect() function.
    2. Inside the code branch that reads:
    3. if(aCD.DoModal() == IDOK)

      add the following lines beneath the call to AfxMessageBox():

      WriteProfileString("Settings", "User ID", aCD.m_strUserID); WriteProfileInt("Settings", "Access Level", aCD.m_nAccess); WriteProfileInt("Settings", "Connect at Startup",       aCD.m_bConnect ? 1 : 0); WriteProfileString("Settings", "DSN", m_strDSN);

      m_strDSN is a member variable of the CMyAppApp class, which is set by the CConnectDialog::OnOK() function.

  • To initialize the Connect to Data Source dialog box controls
    1. Delete the following lines from the top of the CMyAppApp::OnDataConnect() function:
    2. aCD.m_nAccess = 1; aCD.m_bConnect = TRUE;

    3. Replace the deleted lines with the following code:
    4. aCD.m_nAccess = GetProfileInt("Settings", "Access Level", 1); aCD.m_strUserID = GetProfileString("Settings", "User ID", ""); aCD.m_bConnect = BOOL(GetProfileInt("Settings",       "Connect at Startup", 0));

      The entire OnDataConnect() function should look as follows:

      void CMyAppApp::OnDataConnect() {      CConnectDialog aCD;      aCD.m_nAccess = GetProfileInt("Settings", "Access Level", 1);      aCD.m_strUserID = GetProfileString("Settings", "User ID", "");      aCD.m_bConnect = BOOL(GetProfileInt("Settings", "           Connect at Startup", 0));      if(aCD.DoModal() == IDOK)      {           CString strMessage;           strMessage.Format("User %s logged in", aCD.m_strUserID);           AfxMessageBox(strMessage);           WriteProfileString("Settings", "User ID", aCD.m_strUserID);           WriteProfileInt("Settings", "Access Level", aCD.m_nAccess);           WriteProfileInt("Settings", "Connect at Startup",                 aCD.m_bConnect ? 1 : 0);           WriteProfileString("Settings", "DSN", m_strDSN);      } }

    5. Locate the CConnectDialog::OnInitDialog() function. Add the code indicated in bold text in the following code example:
    6. BOOL CConnectDialog::OnInitDialog() {      CDialog::OnInitDialog();      m_lbDSN.AddString("Accounts");      m_lbDSN.AddString("Admin");      m_lbDSN.AddString("Management");      CMyAppApp * pApp = dynamic_cast<CMyAppApp *>(AfxGetApp());      ASSERT_VALID(pApp);      CString strDSN = pApp->GetProfileString("Settings", "DSN", "");      int index = m_lbDSN.FindStringExact(-1, strDSN);      m_lbDSN.SetCurSel(index);      OnUpdateUserid();      return TRUE;        // return TRUE unless you set the focus to a control      // EXCEPTION: OCX Property Pages should return FALSE }

      This code retrieves the data source name from the profile settings, and uses it to set the list selection to the appropriate item.

  • To display the Connect to Data Source dialog box (if required)
    1. Locate the CMyAppApp::InitInstance() function. Add the following code just before the return statement near the end of the function string:
    2. if(GetProfileInt("Settings", "Connect at Startup", 0))      OnDataConnect();

    3. Build and run the MyApp application.
    4. Select the Connect option from the Data menu, and fill in the Connect to Data Source dialog box, making sure that the Attempt to connect at application startup check box is selected.
    5. Save the settings by clicking Connect.
    6. Quit and restart the application to ensure that the Attempt to connect at application startup dialog box appears as soon as the application has started, and that the saved settings have been correctly restored. You can also use the registry editor to check that the profile registry values have been created as expected.

    Registry Support in the Win32 API

    The MFC registry functions make storing information in the registry easy, but they are probably not flexible enough to meet all of your needs. The MFC profile functions allow you to write only to a specified profile key under the HKEY_CURRENT_USER subtree. If you wanted to store values at other registry locations, you have to use the Win32 API registry functions. For example, you might want to store application settings common to all users of a computer. To do this, you would need to create a registry key under the key HKEY_LOCAL_MACHINE\SOFTWARE.

    Also, the MFC functions allow you to store only string or integer values. The Win32 API functions allow you to store information using any of the registry data formats.

    Table 6.5 lists some of the Win32 API registry functions. You can search for the functions in the Visual C++ Help file to find out more about how they are used.

    Table 6.5 Win32 API Registry Functions

    Function Purpose
    RegCreateKeyEx() Creates a registry key. If the key already exists in the registry, the function will open it.
    RegOpenKeyEx() Opens an existing registry key.
    RegCloseKey() Closes an open handle to a registry key that has been returned by the RegCreateKeyEx() or the RegOpenKeyEx() function.
    RegDeleteKey() In Windows 95, deletes a subkey and all its descendants. In Windows NT, deletes a single subkey that cannot have descendants.
    RegSetValueEx() Sets the data and type of a value under an open registry key.
    RegQueryValueEx() Retrieves the type and data for a value associated with an open registry key.
    RegDeleteValue() Removes a named value from a registry key.

    Lesson Summary

    The Windows registry is a central, hierarchically organized database that holds persistent settings and configuration information for the operating system and applications. Your applications can use Win32 API functions to store and retrieve registry settings. You can use the registry editor to view and edit data stored in the registry.

    The registry is logically organized around five predefined subtrees that correspond to the most general categories of the system's organization. These categories are:

    • HKEY_CLASSES_ROOT
    • HKEY_CURRENT_USER
    • HKEY_LOCAL_MACHINE
    • HKEY_USERS
    • HKEY_CURRENT CONFIG

    Subtrees contain keys that can act as containers for other keys and for values, which are leaf nodes used to store registry data. A value has three parts: a name, its data type, and the value itself. Windows defines a special set of data types for registry values. These data types include:

    • REG_DWORD
    • REG_BINARY
    • REG_SZ
    • REG_MULTI_SZ
    • REG_EXPAND_SZ

    A document/view application generated by the MFC AppWizard calls CWinApp::RegisterShellFileTypes() to add an entry to the registry to associate the application document type with the application. RegisterShellFileTypes() also adds an entry to specify a default icon for the document type; and entries for the shell commands Print and Print To, to allow a user to print files directly from the shell.

    The application calls the CWinApp::SetRegistryKey() function to add a registry entry to specify the location of the application's user profile. The user profile is used to store a user's application settings in the registry so that the user settings can be preserved between application sessions. You should change the name of the key specified by SetRegistryKey() to a name that is suitable for a key that contains user profile settings for all of your applications—the name of your company, for example. The SetRegistryKey() function creates a registry key under your profile key with the same name as the application, to serve as a root location for the application settings.

    MFC applications write to the application user profile using the following MFC profile management functions:

    • WriteProfileString()
    • GetProfileString()
    • WriteProfileInt()
    • GetProfileInt()

    These functions are used to store and retrieve string and integer values to and from your application's profile key in the registry.

    In cases where the MFC profile management functions are not flexible enough for your needs, you can use the Win32 API registry functions. For example, use these functions when you need to write to a registry location not under the specified profile key. You can also use these functions to create and delete registry keys, and to store and retrieve values. The most commonly used Win32 API registry functions are:

    • RegCreateKeyEx()
    • RegOpenKeyEx()
    • RegCloseKey()
    • RegDeleteKey()
    • RegSetValueEx()
    • RegQueryValueEx()
    • RegDeleteValue()


    Microsoft Press - Desktop Applications with Microsoft Visual C++ 6. 0. MCSD Training Kit
    Desktop Applications with Microsoft Visual C++ 6.0 MCSD Training Kit
    ISBN: 0735607958
    EAN: 2147483647
    Year: 1999
    Pages: 95

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net