Webocreation

Tuesday, November 24, 2009

Schema Numbering

Schema Numbering

Over time, and given changes in versions, a program often changes the data set contained within its document class. This could become a source of serious errors, because a file saved with a previous version of a program could be erroneously loaded into a newer version. For example, suppose a document contains a pointer to an object of class CSerializedPhrase, version 1. If the class CSerializedPhrase is then updated to version 2 to include additional data members, the application must keep the document from inadvertently using the new version, or errors will result.

To guard against version changes that cause errors, your application can use and check a schema number, which represents the version of the dataset composition or format of your serializable class. When you change the data members in the serializable class, you should also change the schema number of that class. In order to take advantage of schema numbering, there are issues to be handled in both the serializable class and in the document class.

Using a Schema Number in the Serializable Class

To use schema numbering in a serializable class, you need to add code. To see sample code that shows how to add serialization with schema numbering to the serializable class, click this icon.
// Serializ.cpp : implementation file
// Defines version as 1 and "versionable"
IMPLEMENT_SERIAL(CSerializedPhrase, CObject, VERSIONABLE_SCHEMA | 1)
CSerializedPhrase::CSerializedPhrase()
{
}
void CSerializedPhrase::Serialize(CArchive & ar)
{
int nVersion;
// The base function is called first.
CObject::Serialize(ar);
if (ar.IsLoading())
{
nVersion = ar.GetObjectSchema();
switch (nVersion)
{
case -1:
::AfxMessageBox("Unknown Version");
break;
case 1:
::AfxMessageBox("Version 1");
ar >> m_phrase >> m_location >> m_color;
break;
default:
::AfxMessageBox("Future version");
}
}
else
// Files are always saved in the current version.
ar << m_phrase << m_location << m_color;
}

Using a Schema Number in the Document Class

In addition to adding the necessary code to a serializable class to use schema numbering, there are conditions in the document that must be met in order to get the correct schema number.

If the document calls Serialize directly, the call to CArchive::GetObjectSchema in the serializable class's Serialize function will always return – 1, indicating an unknown version number. To see sample code that illustrates this problem, click this icon.
// An Example of Problems with Schema Numbering
class CPhraseDoc : public CDocument
{
...
CSerializedPhrase m_Phrase;
// or
CSerializedPhrase * m_pPhrase;
...
};
CPhraseDoc:: CPhraseDoc()
{
m_pPhrase = new CSerializedPhrase;
}
void CPhraseDoc::Serialize(CArchive & ar)
{
//Warning: In both cases below, a -1 is returned
// in the serializable class instead of
// the object's schema number
m_Phrase.Serialize(ar);
// or
m_pPhrase ->Serialize(ar);
}
Taking Advantage of Schema Numbering
To guard against serious errors, use the following steps to have your application use and check a schema number.

To get schema numbering to work correctly

1. Define a pointer to the serializable class in the document's definition file.

2. Initialize that pointer to 0 in the document's constructor.

3. Use the archive class's overloaded << and >> operators for serialization on that pointer.

To see sample code that shows the method of doing serialization in the document so that schema numbering will work correctly, click this icon.
// PhrasDoc.cpp : implementation file
CPhraseDoc :: CPhraseDoc()
:m_pPhrase(0)
{
// ...
}
void CPhraseDoc::Serialize(CArchive & ar)
{
if (ar.IsLoading())
ar >> m_pPhrase;
else
ar << m_pPhrase;
}
BOOL CPhraseDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
m_pPhrase = new CSerializedPhrase;
// fill object as appropriate
return TRUE;
}
void CPhraseDoc::DeleteContents()
{
delete m_pPhrase;
m_pPhrase = 0;
CDocument::DeleteContents();
}


For more information about persistence and schema numbering, search for "TN002: Persistent Object Data Format" in Visual C++ Help.

The Registry
One purpose of the registry is to store information that will be used by an application from one session to the next. Most recently used files, application-specific folders, and user-selected options are commonly stored in the registry.

In past versions, Windows stored application information in .ini files. This storage method posed a number of problems, however, because the settings for each application were stored in a separate file that could be easily deleted, moved, or modified by the user. The registry makes the storage of configuration information for all applications more manageable by placing it in a single location: the registry database.

Another difference between the registry and .ini files is how the data is stored. While .ini files are written to as text — either by an application or by someone using a text editor — the registry is binary. Its contents are accessible through a tool, RegEdit, or accessible programmatically by means of CWinApp methods.

This section explains the registry in more detail. First, it discusses the organization of the registry database. Then it explains how to view and edit the information contained in the registry using the registry editor. Finally, it shows you two techniques for manipulating the registry from within your application: through registry entry files and programmatic access to the registry through CWinApp methods.

This section includes the following topics:

Registration Database Structure

The registration database (another name for the registry) is a hierarchical database of configuration information. At the root of the hierarchy are six predefined primary keys, or branches, that provide entry points into the registry. The primary keys contain keys, which can contain other keys. Keys can also contain values. A value associates a keyword parameter with a configuration value, which is similar to the entries in an .ini file, except that the data itself is binary. To see an illustration that contains sample keys and their values, click this icon.





Predefined Primary Keys

The following table lists the six primary keys that provide entry points into the registry, and their purpose.

Key name Purpose

HKEY_CLASSES_ROOT Contains software configuration information, particularly for use with COM objects. Includes file extensions /application associations, drag-and-drop protocols, printing configurations, and what to do when a file name receives a double-click.HKEY_CURRENT_USER Contains user-specific settings for the system and applications. Created when the user logs on, and is loaded to this key from that user's entry in HKEY_USERS. MFC applications store registry information under this primary key.HKEY_LOCAL_MACHINE Contains specifications for the computer and drivers and other system settings for the type of hardware installed. Entries in this section are shared by all users of the system.HKEY_USERS Contains information about all the 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 information about the current configuration of the hardware that is attached to a dockable computer that supports multiple configurations.HKEY_DYN_DATA Contains the dynamic status information for various devices. This information is used in the implementation of Plug and Play technology.The Registry Editor

The registry editor provides a graphical interface to view and edit the key hierarchy and values within the registration database.

Viewing the Registry

To view the registry, run RegEdit. The left pane of RegEdit contains a tree view of the database with the primary keys at the root of the view. Key values that contain other keys can be expanded and collapsed in this view. The right view contains keys and their values at the currently selected key in the Tree View pane. Keys can be modified, renamed, or deleted by right-clicking on the key name in the right pane.

To see an illustration that shows how RegEdit displays information about application-specific keys in the registry, click this icon.





Modifying the Registry Safely

You should take care when changing registry settings. Any changes that you make to the registration database take effect immediately. There is no separate Save command in the registry editor.

If there is an error in your registry, your computer may become nonfunctional. If this happens in Windows 95, you can restore the registry to its previous state when you last successfully started your computer.

The following procedure is from the Windows 95 Registry Editor online Help.

To restore the registry in the Windows 95 operating system

1. Click Start, and then click Shut Down.
2. Click Restart the computer in MS-DOS mode, and then click Yes.
3. Switch to your Windows directory. For example, if your Windows directory is C:\Windows, you would type the following:

cd c:\windows

4. Type the following commands, pressing ENTER after each one. (Note that System.da0 and User.da0 contain the number zero.)
attrib -h -r -s system.dat
attrib -h -r -s system.da0
copy system.da0 system.dat
attrib -h -r -s user.dat
attrib -h -r -s user.da0
copy user.da0 user.dat
5. Restart your computer.

Registry Entry Files

A registry entry file is a text file that contains data for the registration database. When the registry editor processes a registry entry file, it uses the information contained there to add and update values within the registration database. Registry entry files cannot be used to remove information from the database.

Registry Entry File Structure

Structurally, registry entry files are simple. The typical file extension is .reg. The first line contains the single word REGEDIT to mark the file as a registry entry file. Comments are marked by an initial semicolon and continue to the end of the line. Individual entries appear one per line in the following format:

branch\key name = value

For example, a registry entry file might appear as follows:
REGEDIT ; This .REG file may be used by your SETUP program.
HKEY_CLASSES_ROOT\.PHR = Phrase.Document


Registry Entry File Use

Setup programs use registry entry files to register their data files for shell activation. A setup program calls the registry editor and passes the registry entry file name to it as a command-line argument. The file is verified by ensuring that the first line of the file contains REGEDIT, and then the individual entries are parsed and added to the database.

Creating a Registry Entry File with AppWizard

You can use AppWizard to create a registry entry file for your application. To see an illustration of the Advanced Options dialog box in Step 4 of AppWizard, which is used to set a default file extension for documents associated with your application, click this icon.





To see a sample registry entry file, click this icon.



; phrase.reg

REGEDIT; This .REG file may be used by your SETUP program.
; If a SETUP program is not available, the entries below will be
; registered in your InitInstance automatically with a call to
; CWinApp::RegisterShellFileTypes and COleObjectFactory::UpdateRegistryAll.

HKEY_CLASSES_ROOT\.PHR = Phrase.Document
HKEY_CLASSES_ROOT\Phrase.Document\shell\open\command = PHRASE.EXE %1
HKEY_CLASSES_ROOT\Phrase.Document\shell\open\ddeexec = [open("%1")]
HKEY_CLASSES_ROOT\Phrase.Document\shell\open\ddeexec\application = PHRASE
; note: the application is optional
; (it defaults to the app name in "command")
HKEY_CLASSES_ROOT\Phrase.Document = Phrase Document

No comments:

Post a Comment