Target Designer, Inside and Out
August 22, 2002
Summary: Walks through the important features and functionality of the Microsoft Windows XP Embedded tool, Target Designer. (9 printed pages)
Howdy, folks! Another month means another Microsoft® Windows® XP Embedded article. We've been talking so much about Component Designer and Component Database Manager the past few months that it's time for a change! We're going to cover the features and functionality of the tool that brings everything together, namely Target Designer. We'll start by opening the tool and going over what it gives to us.
The Field of Battle
Go ahead and open Target Designer. The first thing you'll notice is the splash screen describing the initialization tasks being performed. When that's done, you'll see an empty Target Designer window with three panes—two side-by-side and one on the bottom. We'll discuss each of these in detail as we go along.
On the File menu, click New... to create a new configuration. You'll be presented with a New Configuration dialog, allowing you to name the configuration and select a platform. Since there's only one platform currently available, leave that setting as is (there's only one to select anyway). Name the configuration anything you'd like, and then click OK.
Target Designer will begin creating the configuration, and populate the window. The first thing it does is to show some status messages in the lower pane, called the Task List. This pane serves three purposes: It holds a list of tasks to be done, displays status messages, and displays debug messages. Each function can be selected by clicking the appropriate tab at the bottom of the pane. We'll go over these functions a little later.
The left pane is called the Component Browser. It's a list of all the components in the database (with a minor caveat we'll discuss later). At the top of the Component Browser are a drop-down combo box, a text-edit box, and two buttons. The combo box and the button next to it control filters, which can be used to restrict the contents of Component Browser to a well-defined subset (we've discussed filters in a previous article). The edit box and its associated button allow you to search the Component Browser for specifically named components. Under these fields are two selector buttons and a count of the number of components being displayed. The two selector buttons change the view of the components from a hierarchical tree view to an alphabetical list view—the same components are displayed, just the view of them is altered. The main part of the pane is the actual list of components.
You'll notice that, when you created the configuration, the right pane was divided into two sections. The middle section is called the Configuration Editor, and is where the current configuration is displayed and can be edited. The right section is the Details Pane, and is where details about the currently selected object in the Configuration Editor are displayed. When a new configuration is created, the basic configuration properties are displayed. These include the name, version, owner, author, vendor, copyright, and a description. The Details Pane shows other information as well, which we'll get into later.
The reason for a configuration to exist is to give you a place to combine and configure components (called instances when they are placed into a configuration). This means you need a way to add components, remove instances, select items, and configure them. Configuration Editor is where all this happens.
Configuration Editor displays your configuration in a tree view, with the configuration itself as the root of the tree. Under that root are five branches: Settings, Extra Files, Extra Registry Data, Extra Resources, and Components. The "Extra" branches are places where you can add resources that are not in any components; this is good for troubleshooting and testing things. The Settings branch opens the configuration settings DHTML page in the Details Pane. This is where configuration-wide settings can be changed and edited. The Components branch is where each component instance that is a part of the configuration is shown. Each instance shown in the Components branch has its own branches showing the Files, Registry Data, Resources, and Settings for that particular instance.
The use of the words "component" and "instance" is not just an issue of terminology, but also of architecture.
A component is a pattern for a particular piece of functionality, containing files, registry, and other resources necessary to actually build that piece of functionality properly. Components live in the database and are statically defined. They don't change in the database, and are not executed or built there.
Instances are the actual objects created from the component patterns. They are alterable down to the resource level, and are what we use to perform a run-time build. It's important to note that changing an instance (disabling or adding resources, or changing settings) does not change the underlying component, only that particular instance. If you're an object-oriented programmer, it's the difference between a class and its object; if you're not, it's the difference between a cookie cutter and the cookie it creates. (And if neither of those analogies means anything to you, then it's the difference between a green roller-skating giraffe and a truck full of used sports equipment. Makes sense now? Good.)
Component and Instance Manipulation
Adding components is easy. There are actually six (that's right, six), different ways to add a component to a configuration:
- Drag the component from Component Browser to the Configuration Editor.
- Double-click the component in Component Browser.
- Right-click the component in Component Browser and click Add from the context menu.
- Highlight the component in Component Browser, and on the Configuration menu, click Add Component.
- Highlight the component in Component Browser, and on the toolbar, click Add Component.
- Copy the component from Component Browser and paste it into Configuration Editor.
Pick the method that works best for you. I find double-clicking the component in Component Browser is the quickest and easiest, since Component Browser doesn't support multi-select.
Removing instances is similarly easy and extensively provided for—there are nine ways to remove an instance from Configuration Editor:
- Highlight the instance and hit the Delete key.
- Highlight the instance, and on the Edit menu, click Delete.
- Highlight the instance and click the delete button on the toolbar.
- Highlight the instance and click the delete component button on the toolbar.
- Highlight the instance and cut it using CTL-X.
- Highlight the instance and on the Edit Menu, click Cut.
- Highlight the instance, and on the toolbar, click the cut button.
- Right-click the instance and click Delete on the context menu.
- Right-click the instance and click Cut on the context menu.
Again, pick one that works for you and run with it. The Delete key on the keyboard works well for me. However, there is an alternative to deleting an instance. You can disable it, which means it's still in your configuration, but won't be considered when checking dependencies or building. It's like commenting out a line of code. You're not getting rid of the line, which may be useful later; you're just removing it from the build. And in a refreshing change, there's only one way to disable an instance: right-click the instance and click Disable on the context menu.
Configuring instances is another easy process. In Configuration Editor, each instance has a Settings branch under it. Click Settings, and the Details Pane should provide you with a DHTML page to change the settings of the instance. Not all instances have DHTML settings, while others may have two or more. Since the settings pages are all DHTML, they're all standard controls you should be able to decipher.
You can also manually modify advanced properties of each instance. By highlighting an instance and then clicking Advanced in the Details Pane, you can see all of the advanced properties of an instance. Normally, you wouldn't bother to look here—if there are configurable properties, they should be exposed in the settings DHTML for the instance—but in some circumstances it's necessary. For example, you need to manually set the cmiResealPhase in the "System Cloning tool" component if you want to manually reseal the device—it's not listed as a configurable setting.
You can't multi-select instances directly in Configuration Editor, but you can by using the Details Pane. To accomplish this, highlight the Components branch of the configuration. The Details Pane now contains a list of all the instances in your configuration. You can use standard multi-select syntax (hold down CTRL and SHIFT while clicking), and then disable or delete a group of instances—much easier than doing it one by one.
The Battle Joined
Once you've got a configuration full of instances you've added (or perhaps imported from a PMQ file—we'll cover TAP next month), what do you do with them? Oh sure, they're pretty to look at, but they're not just eye-candy; they really come into their own during a dependency check. You can start a dependency check in three ways:
- On the Configuration menu, click Check Dependencies.
- Click the check dependencies button on the toolbar.
- Hit F5. (This one sounds like a winner!)
If you remember a few months ago when we were discussing components, we defined dependencies as components that are required for your component to operate properly. When we do a dependency check, we go through all the dependencies in the instances in your configuration and try to resolve them. Usually that means adding another component to the configuration to satisfy a dependency—but not always. It can also mean disabling an instance, or possibly giving the user a choice.
Remember the types of dependencies we can have: component dependencies, component conflicts, and group dependencies (in a number of flavors, including conflicts). Simple component dependencies are easy to resolve—add the required component and move on. However, if there is a conflict between two instances, then one must be disabled. And in the case of group dependencies, the component can specify zero, one, or more components from a particular group to require or conflict with. In these last two cases, Target Designer can't simply take action; it needs direction. This is where the Task List comes in.
The Resolve Dependency Dialog
When Target Designer comes across an unresolved dependency it can't resolve on its own (which means anywhere a choice needs to be made), it adds an item to the Task List. The title of the Task List item reflects what needs to be done, and, if the cursor hovers over it, a list of components that are affected will be shown as well. Double-clicking the item will display a Resolve Dependency dialog, which tells you what needs to be done, and gives a list of components that will be affected.
There are five basic types of resolve dependency dialogs: add only one component, add one or more components, add all components, remove one component, and remove one or more components. In each case, the dialog is the same, but the behavior is different. For example, if you have to add only one of a list of components, then the dialog will prevent you from selecting more than one component (the OK button will be disabled until only one is shown).
The Resolve Dependency dialog allows you to view hidden components as well. These are components that are below the current visibility setting (more on that in a few). You can also highlight a component in the list and view its properties using the appropriately named Properties button.
Tailoring the Dependency Check
There's one other feature in Target Designer that controls the action of a dependency check. If from the Tools menu you click Options, you'll see the Options dialog. There is a Dependency Check tab, which contains a single, solitary, lonely check box. If this box is checked, then a dependency check will resolve everything it can, and only report those items that require human intervention. This is called auto-resolve, and the box is labeled with similar language. If the box is unchecked, then a dependency check will report each and every discrepancy it finds—it won't resolve anything, listing every dependency in the Task List for you to handle.
Why would you do this? After all, in a normal configuration, a dependency check can add one hundred or more components automatically—why do all that work manually? Simple. You wouldn't, not on a normal configuration anyway. But if you want to know what a particular component's dependencies are, or are testing your own component, it makes sense to uncheck the auto-resolve check box to see exactly what's happening. And if you forget to turn it back on before doing a full dependency check, no problem: go back and check it, then restart the dependency check. The Task List will be cleared, and Target Designer will auto-resolve what it can and report the rest, just as it should be.
The Shape of the Battle
The Options dialog is pretty useful; let's take a look at the other options that are configurable. Remember, these are saved between configurations, and between sessions as well. (A session starts when Target Designer is started and ends when Target Designer is exited.) So anything you set here will be there the next time you fire up Target Designer.
The Mode Tab
The first tab on the Options dialog is Mode. The radio buttons here let you select a starting operating mode, either Basic or Expert. The big difference between these two settings is simple: If you're in Basic mode, any Expert mode actions you take will cause a caution dialog to appear. Expert mode actions include:
- Adding extra files, registry data, or resources to a configuration.
- Viewing Advanced Properties of the configuration or an instance.
- Viewing the files, registry data, or resources of an instance.
The dialog that appears will let you switch the Expert mode to complete the action, but that setting isn't saved between sessions. It will be saved for the remainder of the current session, though.
The Build Tab
The Build tab shows three directories Target Designer uses during the build process. The Extra Files Folder is where Target Designer will search for file resources it can't find in the repositories (namely extra files added to the configuration). The Build Log Folder specifies where the build logs will be placed by default. The Default Image Folder tells us where to put the run-time images we create. The buttons next to each edit box bring up folder browser dialogs to select the folders dynamically.
The Advanced Tab
The Advanced tab has three controls that are interesting. (Actually, it's only got three controls to discuss, but they're all very interesting—compelling, even.)
Remember that caveat I mentioned way back when we were talking about Component Browser, about it letting you see all the components? Well, here's the deal: The Minimum Visibility field allows you to set the level at which Component Browser and Configuration Editor will hide components and instances. The allowable range starts at 100 and tops off at 10,000; however, most useful components have a visibility of 1,000, and all of your custom components, unless you change it manually, will be at visibility 1,000. You can set this as high or as low as you want—it doesn't affect what components are available, just which ones you can see.
The Configuration Upgrade check box controls whether Target Designer will automatically upgrade instances when you open a configuration that has upgradeable instances. What are upgradeable instances? Well, let's hearken back to our discussion of version, revisions, and released components a few months back. If there is a released component in the database with a later revision than the instance currently in your configuration, then that instance is upgradeable. This check box means Target Designer will automatically upgrade any instances it can. If it's unchecked, Target Designer prompts you to perform an upgrade. If you want to upgrade a configuration manually, you can do so in two ways:
- On the Configuration menu, click Upgrade Configuration.
- On the context menu, right-click the Components branch and click Upgrade.
You can also upgrade individual instances if you'd like; they're marked in Configuration Editor with a blue arrow. There are two ways to do that as well:
- Right-click the instance you want to upgrade and on the context menu, click Upgrade.
- Highlight the instance and on the Configuration menu, click Upgrade Component.
The Restore All Default Options check box does exactly what it says: returns everything in the Options dialog to default values. However, it doesn't do it immediately. In fact, it won't change the values back until after Target Designer is closed and restarted. When you check this box, you'll see a dialog to that effect.
The Battle's Climax
All of these options and features are there to support one thing: the actual building of a runtime. And in keeping with our theme of multiple paths to a goal, you can start a build in three ways:
- Click the build image button on the toolbar.
- On the Configuration menu, click Build Target Image.
- Hit F7. (We have another winner!)
When you start the build process, Target Designer displays the Build dialog. Here you can select the build type (Release or Debug, in case you have mixed instance types in your configuration), where to put the image (this is where the Default Image Folder option is used), and where to put the log (specified by the Build Log Folder option). You can change any of these to suit your purposes. The Build button at the bottom of the dialog starts the build process.
The Build Process
The first thing Target Designer does is to check the Task List for unresolved dependencies. It prompts you to do a dependency check if anything is unresolved there. You'll also be prompted to do a dependency check if the configuration has changed since the last dependency check. There's only one problem here: Any configuration change marks the configuration as dirty and requiring a dependency check. The revision property is updated when a configuration is saved, and this counts as a change to the configuration. Therefore saving the configuration means the build process will want a dependency check. You can always skip this check if you wish.
After the dependency check is done, the build process checks to see if the target folder is empty. If it's not, it will prompt you to clear the folder. Make sure this is what you want—we're deleting files, not sending them to the recycle bin, so there's no recovery option. Just as with anything else, we can't delete files that are currently being used.
The build process then starts, logging its progress to the log file that's given, as well as to the log window on the build dialog. The build progress is shown on the progress thermometer in the middle of the window. But what is it really doing?
Well, first, it goes through the list of components and checks the build order for each of them. Any components with the same build order number are built alphabetically, just the way they're displayed. After the order is set, we create a base set of registry hives, and we process any configuration settings. Then we grab the first component and tell it to build itself. The component knows how to write its files and registry data, as well as how to process its other resources. When it's done, we move on to the next component. When all the components are done, we close all the files and dump an estimate of the component sizes.
What's this about configuration settings you say? Well, if you highlight the Settings branch of the configuration in Configuration Editor, you'll see five groups of settings in the Details Pane. Each has a Show link under it to display the settings for that group.
The first group, Run-time Image Licensing, allows you to enter a PID for the runtime. This enables you to ship the runtime. Without a PID, the runtime is an evaluation runtime, good for only 90 days.
Target Device Settings tells us how the target device media is setup. We need to know where the boot files will be located, where to put the basic Windows XP folders (Windows | Program Files | Documents and Settings), and some BOOT.INI settings. We also need to know how big the system partition is. This is crucial. If the size given for the Boot Partition Size is not the same as the actual size of the boot partition, then you may have activation problems. Make sure these numbers match (or are reasonably close). The last setting here is the cluster size, which lets us better estimate the component sizes—not crucial, but nice to know.
The options under "Configuration Update and Refresh Settings" control, at the configuration level, whether instances in the configuration should automatically refresh and upgrade themselves. (Refreshing is like upgrading, but affects unreleased components as well. If a newer component exists in the database, we can refresh it in the configuration, even if it's not released or subject to upgrading).
The Deployment Identification Settings are strictly for OEM use. They're fields where you can identify your device internally. We don't really care what's there; we just stuff it into the registry.
The Other Settings group contains options to copy help files or not (this can really save on disk space), whether to display the Windows XP logo during boot (it adds the /noguiboot option to the BOOT.INI line for the image), and an additional build path to append to the Default Build Path for this configuration (helpful for keeping multiple runtimes straight).
As you've seen, Target Designer is a feature-laden, data-driven application that's absolutely the meat of Windows XP Embedded. It allows you to combine components, resolve dependencies, and build those components into a customized operating system image. Next month, we'll talk about how to get that image actually up and running.