Export (0) Print
Expand All
Expand Minimize
This topic has not yet been rated - Rate this topic

Component Designer: Pulling It All Together

 

Jon Fincher
Microsoft Corporation

June 19, 2002

Another month has gone by, and here I am again. I wanted to use this column to bring together everything we've discussed in the last few months about component authoring using Component Designer. In this column, we'll create a component from a non-trivial application. I'll walk you through all the steps I go through to get a component ready for inclusion in a Microsoft® Windows® XP Embedded runtime. You might want to look through the last few columns for a quick refresher as we go along.

Disclaimer: I'll be componentizing the Microsoft® Reader 2.1 application. This doesn't mean that I, or Microsoft for that matter, think this is a good embedded application—I picked it somewhat at random. I wanted an application that would be fairly easy to see working in a runtime, but one more useful than a contrived application of my own design.

Step 1: Make a Clean Machine

The first step is to make a clean Windows XP machine. We'll install Microsoft Reader on the clean machine to determine the file and registry resources it contains.

Note that you can use your development machine for this step if you like. You'll wind up having Microsoft Reader on your main work machine, which is not necessarily a bad thing—better to pass the time during compiles with a book than playing Freecell&#151but; there's another reason to use a clean machine.

Let's suppose you have Application A on your development machine that has installed FOO.DLL, and Application B (which we're going to componentize) also wants to install FOO.DLL. Application B's setup will see the existing FOO.DLL, and unless it has a newer version, it won't copy its FOO.DLL. The monitoring tools we'll use won't tell us that Application B has FOO.DLL as a file resource, and we won't add it to the component. When we test the component in an actual runtime, we might get a missing DLL error, or maybe something more subtle will happen (functionality may be broken or missing). And if there are versioning issues (DLL Hell), you might actually break Application A when you install Application B. All in all, it's better to use a clean Windows XP install.

Step 2: Logging the Installation

Now that we have a clean Windows XP install, we need to set up some monitoring software. I prefer the shareware tool InCtrl5 from PC Magazine, but any tool that can monitor an install will do. I found InCtrl5 by searching for "uninstallers." The key to a useful tool is whether it can tell you all changes that were made to your system by a setup program, both files and registry changes.

I won't go into detail on how InCtrl5 works, but I will discuss some of its general features and those of other uninstaller programs. Most of the uninstallers I've used are static tools; that is, they don't actually watch the setup occur, but compare system states before and after a setup. The assumption is that the difference between the two states has to be the work of the setup application. This is accomplished by saving a snapshot of the system before you run your setup—a record of all the files and registry keys that are present in the system. You then run your setup, including any and all reboots that the setup feels are necessary. Then, you restart the uninstaller and snapshot the system again. The true work of the uninstaller comes in comparing the two snapshots and presenting the information to you in a usable manner.

When I installed Microsoft Reader, there was a setup option to activate the system during setup, which I chose not to do. Activating the system for Microsoft Reader requires adding a passport to the system and personalizing it for one and only one person. In a real embedded device environment, this is something you'd probably want your user to do.

For those of you who complain that Microsoft doesn't have its own tool to monitor installs, I've got news: we do. It's called SysDiff, and it has been around for quite a while (I first used it in the Windows NT 4.0 OEM Preinstall Kit [OPK]). You can download it from http://msdn.microsoft.com/isapi/goftp.asp?Target=/bussys/winnt/winnt-public/fixes/usa/nt40/utilities/Sysdiff-fix/SYSDIFFI.EXE. A warning: This tool was originally used for Windows NT 4.0 deployment, and so is a command-line tool, reporting the snapshot differences to a text file. It's a good tool and does the job, but there are nicer and easier-to-use alternatives.

Step 3: Interpreting the Results

When InCtrl5 is done, it creates three different report files: one in HTML format, one in Text format, and the third in CSV format (for opening in Microsoft® Excel). Note that they all have the same data, just formatted differently. The HTML and Text format files are very similar. The HTML report is nicer looking and opens in a Web browser, and the Text report is smaller and opens in Microsoft® Notepad. The CSV files lets you do some formatting to the data in Excel, but is essentially the same and somewhat tougher to read. Use whichever log format suits you best. I used the Text report because I could edit it on the fly, removing the entries I knew were unnecessary, leaving me with a smaller file to work with.

Let's skip past the registry keys for a moment—there are a ton of them, and knowing which ones are signal and which are noise can be tricky.

File Resources

The files and folders list is much easier to manage. There were ten folders added to the system:

  • c:\Program Files\Common Files\InstallShield
  • c:\Program Files\Common Files\InstallShield\Engine
  • c:\Program Files\Common Files\InstallShield\Engine\6
  • c:\Program Files\Common Files\InstallShield\Engine\6\Intel 32
  • c:\Program Files\Common Files\InstallShield\IScript
  • c:\Program Files\Common Files\Microsoft Shared\ClearType
  • c:\Program Files\InstallShield Installation Information
  • c:\Program Files\InstallShield Installation Information\{B6F7DBE7-2FE2-458F-A738-B10832746036}
  • c:\Program Files\Microsoft Reader
  • c:\Program Files\Microsoft Reader\pts

It's pretty easy to see that most of these folders are noise. There are actually three useful folders here. Can you spot them all? Go ahead, I'll wait.

The three folders we need are:

  • c:\Program Files\Microsoft Reader
  • c:\Program Files\Microsoft Reader\pts

and

  • c:\Program Files\Common Files\Microsoft Shared\ClearType

Give yourself 10 bonus points for finding the third folder (no points for just finding the first two—they were too easy). Microsoft ClearType® is a font technology introduced and distributed with Microsoft Reader. If we want Microsoft Reader to work properly, we need to make sure we get the ClearType files as well. (This is also a good reason for the component author to be very familiar with the application he's componentizing—if you've never used Microsoft Reader before, you might miss the ClearType connection.)

So we know the folders we need create; now we need to identify the files that go into those folders. Our report lists 56 files that were added to the system. Knowing this, we can ignore anything that relates to InstallShield, and so we can trim this list to 43 files. We can also ignore anything placed in the \Windows\Prefetch folder, leaving us with 38 files. Of those, two of them are shortcuts, with the extension .LNK. Those will be created by the Shortcut FBA directive. So we have 36 actual, real, live file resources to deal with.

There were also four files that were changed. Two of them are log files used by the system to track installs and uninstalls. The other two are the SOFTWARE registry hive and its log file. All four can be ignored for our purposes.

Registry Resources

Now let's take a look at the registry list. There were 387 registry keys created, but we can group them into categories to make it easier to prune them:

  • HKEY_CLASSES_ROOT (HKCR): Type libraries, COM objects, and files extension associations go here. FBA directives should handle them.
  • HKEY_CURRENT_USER (HKCU): Software-related entries per user.
  • HKEY_LOCAL_MACHINE (HKLM): Software-related entries for the system.

Let's start small. There is one HKCU\Software\Microsoft\EBook key that looks promising. HKLM contains 11 new keys, all but three of which we need (the three we can safely ignore deal with install, uninstall, and application pathing).

The HKCR branch is where most of the excitement is happening. In order to figure out what is going on here, we need to get into the registry and see what is in each of these keys. This step can also be done on a machine that does not contain the application we're componentizing. Anything that we find on that machine is most likely not a part of our application, while missing keys are certainly something we want to put in the component.

Here's the tough part. By using RegEdit, we can prune all the HKCR\CLSID\{guid} branches—they are for the MSI installer. Similarly, we can prune out the HKCR\Interface\{guid} and HKCR\Typelib\{guid} branches. They all deal with the MSI installer.

The easier part just uses the InCtrl5 log file. All the HKCR\Setup.{modifier} keys are unnecessary, as are any keys dealing with installation or uninstallation. This leaves us with four extensions registered (.aa, .ebo, .fls, and .lit), Mime registrations for these extensions, and keys supporting eBook and MSAudible (a feature that reads words from a Microsoft Reader book) for a total of 39 keys.

Now that we know the keys we need to add to our component, you'd think the next step would be to inspect the registry values section of the InCtrl5 log file. Not so. Remember that you can either create a single registry key or a complete branch in Component Designer. Creating the branch actually reads the data from the registry on the development machine. If we install Microsoft Reader on our development machine, we can—using the keys we've identified—simply perform a set of Add Registry Branch operations in Component Designer, rather than perform hundreds of Add Registry Key operations. Installing Microsoft Reader on the development machine also allows us to quickly add File Resources in a similar manner. I like doing less and getting more done, so that's what I'll do.

Notice that, by inspecting and pruning the HKCR\CLSID, HKCR\Interface, and HKCR\TypeLib branches, we've eliminated the possibility that Microsoft Reader contains any COM objects or registered DLLs. Had there been a need to register any DLLs or COM objects, we would have seen GUIDs in the above mentioned keys not associated with the MSI installer.

Step 4: Identifying Dependencies

OK, let's step back to our file resources once more. There's one more thing we need to do with them before we can move forward. We need to know what support files they require to run properly. The easiest tool to help us with this is called Depends. It ships with Microsoft Visual Studio®, but can also be downloaded from http://www.dependencywalker.com/. This is a GUI tool that will tell you what DLLs are called from within an EXE or DLL. You can also use a tool like DumpBin to get the same information.

We need to identify all the executable code in our file resources—basically, all the EXE and DLL files. We then run Depends on each file to determine what other files it calls into. We can then find out what components contain those files as file resources, and list them as dependencies in our component.

Here's the list of executable file resources I found:

  • c:\Program Files\Common Files\Microsoft Shared\ClearType\ctras.dll
  • c:\Program Files\Microsoft Reader\aud_file.dll
  • c:\Program Files\Microsoft Reader\d_Aud1.dll
  • c:\Program Files\Microsoft Reader\dmgr.dll
  • c:\Program Files\Microsoft Reader\EBOOKFX.dll
  • c:\Program Files\Microsoft Reader\ebriched.dll
  • c:\Program Files\Microsoft Reader\imgdecmp.dll
  • c:\Program Files\Microsoft Reader\msls31.dll
  • c:\Program Files\Microsoft Reader\msreader.exe
  • c:\Program Files\Microsoft Reader\player_dll.dll
  • c:\Program Files\Microsoft Reader\utils.dll

My next step is to run Depends on each of these binaries. I start with the ctras.dll file, and discover it calls:

  • MSVCRT.DLL
  • KERNEL32.DLL
  • ADVAPI32.DLL
  • GDI32.DLL

Notice that all I did was take the top level DLLs that were called. I'm assuming that the DLLs each of these calls are handled properly in the database already.

By following these steps on all the file resources in Microsoft Reader, I get the following list of dependent modules:

  • MSVCRT.DLL
  • MSVCIRT.DLL
  • KERNEL32.DLL
  • USER32.DLL
  • GDI32.DLL
  • ADVAPI32.DLL
  • SHELL32.DLL
  • OLE32.DLL
  • OLEAUT32.DLL
  • WININET.DLL
  • MPR.DLL
  • URLMON.DLL
  • WINMM.DLL
  • EBOOKFX.DLL
  • DMGR.DLL
  • UTILS.DLL
  • IMGDECMP.DLL
  • MSLS31.DLL.DLL
  • AUD_FILE.DLL

The last six reported dependant files are actually file resources in our component. We don't need to consider them when figuring out our component dependencies.

Now we need to map those files to their owner components. This is where the Filter Manager feature of Target Designer and Component Database Manager comes in handy. We can filter the component list, including only those components that contain a particular file. To use this feature, open Target Designer and create a new configuration. At the top of the component list, click the funnel icon next to the filter drop down menu to access Filter Manager. Make sure your visibility is set to 100, and that you're looking at the list view of the component list rather than tree view. It's easier to pick the filtered components out of a short list than from a pruned tree.

Note that I'm not using Component Database Manager, even though it's faster than Target Designer to open. That's because I can configure the visibility of components in Target Designer. Some of the dependent components have a visibility less than 1000, and it's easier to see them in Target Designer than in Component Database Manager.

Now, click on New to create a new filter. Name the filter something memorable—it will be saved for future use. In the Filter Rules list, select the rule, Component contains the following file: [filelist], then click Add Rule. In the Filter Description box, double-click the rule we just added to edit the name of the file. Enter the first file in our list, MSVCRT.DLL. Click OK to save the file name, and then click OK again to close the Filter Editor. Finally, click Apply Filter to apply the filter to the component list.

When the component list reloads, there should be two components shown, namely Microsoft Visual C++® Run Time, and Visual C++ Runtime Libraries (Side X Side). Do we need both? In this case, no. We only need the first one. The second component provides support for side-by-side assemblies (where two applications need different versions of the same DLL). While this may be a concern for some devices and applications, it's not for us.

We do these steps for each DLL in our list, giving us the following complete list of dependant components:

  • Microsoft Visual C++ Run Time
  • Standard Template Libraries (STL)
  • Win32 API – Kernel
  • Win32 API – User
  • Win32 API – GDI
  • Win32 API – Advanced
  • Primitive: Shell32
  • Primitive: Ole32
  • Primitive: Oleaut32
  • Primitive: Mpr
  • Primitive: Winmm
  • Wininet Library
  • Urlmon Library

Note that when filtering the OLE32.DLL file, two components were displayed: Primitive: Ole32, and MCI Support. Both components were added to the configuration and the File Resources for each examined. The Primitive: Ole32 component was selected as our dependency because the MCI Support component did not contain the OLE32.DLL file resource. Why did it show up in the filtered list? Because filtering adds implicit wildcards to the front and back of the filtering string, and MCI Support has a File Resource called MCIOLE32.DLL.

Also note that just because we've been exhaustive in determining our dependent files and component, this doesn't mean the component will work right away. There may be delay load dependencies that Depends can't figure out. These will have to be discovered at runtime, using other tools we'll discuss later in this article.

Step 5: Bring It All Together

We've identified the following resources for our component:

  • 36 file resources
  • 39 registry branch resources
  • 13 component dependencies
  • 2 Shortcut FBA directives

Now we can open Component Designer and start crafting our component.

The first thing to do is to name the component something interesting, like Microsoft Reader (actually, I like the name Cornelius, but it's confusing to other people using my component). Fill in the Author, Owner, Copyright, and Version information, and put something pithy in the Description. (I've always felt development work is far too serious and dry. Entertain the users of your component, and they'll come back for more.)

Next we use Add Files in Folder to grab the entire C:\Program Files\Microsoft Reader folder and the C:\Program Files\Common Files\Microsoft Shared\ClearType folder. Then we can use Add Multiple Files to grab the fonts installed into the C:\Windows\Fonts folder.

Note   To add multiple fonts using the Add Multiple Files dialog, you need to type in the names of the font files. You can't simply click on each file to add it. Make sure to type the names as they appear in the log file, and surround each file name with double quotes.

Now we can add our registry branches. Perform an Add Registry Branch on the branches you have left. You probably won't have to do 39 Add Registry Branches, since some of the reported branches are actually children of an earlier listed branch.

Next come our dependent components. These get added, oddly enough, in the Component or Group Dependency section. Right-click this section and select Add Component Dependency. Now we can find all the dependent components we identified above. We can do this either manually (searching the list for the identified components), by applying the filters we created to find them in the first place, or by creating new filters on the names of the components. However you do it, you should have 13 component dependencies when you're done.

Now comes the fun part—specifying the shortcuts. We'll do this Resources section of the component. Right-click and click Add Shortcut. Fill in the name, and set the properties to these values:

Property Value
DstName Microsoft Reader.lnk
DstPath %16409%
Overwrite True
TargetPath %16422%\Microsoft Reader\msreader.exe

This puts a shortcut to Microsoft Reader on the Desktop (specified by the DstPath=%16409%). We can put another shortcut on Start/All Programs menu by changing the DstPath to %16407%.

We also need to create a repository for our files. Remember that a repository is a flat folder containing all the files our component lists as resources. The easiest way to do this is to save the component into a subfolder on your machine somewhere (let's say I created mine at C:\MSReaderComp). Using Microsoft® Windows Explorer, I can then create the C:\MSReaderComp\Rep folder to hold my repository. Next, I copy the files from C:\Program Files\Microsoft Reader, C:\Program Files\Common Files\Microsoft Shared\ClearType, and C:\Windows\Fonts folders to the C:\MSReaderComp\Rep folder. There are no overlapping file names, so I don't need to rename anything this time.

Now, back in Component Designer, add a new repository by right-clicking the Repositories item and then click Add New Repository. Again, name and describe it, then click Browse next to the Source Path box. Drill down to the C:\MSReaderComp\Rep folder and click OK. The Source Path box should now display \Rep. Next, click on the component name in the tree, and locate the Repository box in the Details pane. Click Repositories next to it, and pick the newly created repository; then click OK. This ensures that your component will use your new repository. Without that, your component is going nowhere fast.

There's one last thing we should do, and that's to find a proper category for this component. We do that in Group Memberships. Right-click and then click Add Group Membership. Pick a proper category for your component. It's an easy way for people to find your component without having to search. In this case, I'll pick Software : Applications : Other. Save your component, close Component Designer, and we're ready for the final steps.

Note   One thing I didn't do was release the component. At this point, we're still in the development stage. Once we've fully debugged the component on the embedded system and are sure it works properly, then we can release it (right-click the component and click Release, then save and import the component again). Until then, keeping it unreleased makes it easier to work within Target Designer.

Step 6: Import and Test

Now we get to import the component. Open Component Database Manager and click Import. In the SLD File box, enter the path to the SLD file, or click "..." and browse for the file. Make sure the "Copy repository files to repository root" check box is selected (else our repository won't be created), and then click Import. Assuming we authored the component correctly, we should see no errors. Close Component Database Manager.

Now we can open Target Designer and build a runtime with our component. You can import a PMQ generated by Target Analyzer for your device, add the Microsoft Reader component (Software : Applications : Other, remember?), check dependencies, and build the runtime. Remember, since we didn't release the Microsoft Reader component, you'll get at least one warning from building an unreleased component. It can be safely ignored. When the runtime boots fully (let it get all the way through FBA), you should be able to find and run Microsoft Reader without any problems. But if there are problems...

Testing

At this point, it's probably a good idea to talk about component testing. I recommend testing your new component on a normal PC whenever possible. The setup of a good testing PC for Windows XP Embedded consists of a machine with two hard drives or partitions. The C:\ partition contains a normal Windows XP installation, called a safe build. The D:\ partition is where the Windows XP Embedded runtime will be located. You'll need to add an entry to your BOOT.INI file on the C:\ drive:

   multi(0)disk(0)rdisk(1)partition(1)\Windows="Microsoft Windows XP Embedded" /fastdetect

If you've got one hard drive instead of two, change this to:

   multi(0)disk(0)rdisk(0)partition(2)\Windows="Microsoft Windows XP Embedded" /fastdetect

You may also want a way to turn on the kernel debugger. Add another entry as shown above, but add the /debug switch to the end of it.

Now, to test numerous Windows XP Embedded runtimes, all you need to do is format the D:\ drive, copy the files from your development machine, and reboot into the runtime. You can also use the safe build to hold debugging tools, such as FileMon, RegMon, or the kernel debugger. You can also get to all the Windows XP files from the C:\ drive. If it turns out you are missing a file or a dependency, fire off C:\Windows\System32\CMD.EXE, and copy the files from the C:\Windows tree to the D:\Windows tree.

One caveat with this setup is that you need to build the runtime so it knows it's living on D:\ instead of C:\. Do this by changing the settings for the configuration. Under Target Device settings, change the Windows folder, Program Files folder, and Documents and Setting folder to reflect the D:\ pathing. Keep the Boot drive set to C:\. When you build the runtime, a DriveD folder will be created. Copy the contents of that folder to the D:\ drive on your target system, and reboot.

Only One Problem...

I noticed one problem when I ran Microsoft Reader on my runtime: the fonts weren't being picked up correctly. I stopped Microsoft Reader, loaded FileMon, then restarted Microsoft Reader, and wouldn't you know it, Microsoft Reader fixed itself.

In this case, there are two things I would do to make sure this didn't get out to a customer with this first-time run problem. Either run Microsoft Reader once or twice during the capture process, or add the System Cloning component to my runtime and run Microsoft Reader on the device before shipping it.

Summary

We've gone through a complete walk-through of creating a component from a non-trivial application. We've discussed tools and techniques you can use to componentize your own application, and hopefully we've cleared the waters a little when it comes to componentization.

Next month: Target Designer Basics.

 

Get Embedded

A native New Englander, Jon Fincher worked as a UNIX System Administrator and database programmer before joining Microsoft Product Support Services in 1995. In 1999 he started supporting Windows NT Embedded 4.0, and is now a Software Test Engineer for Windows XP Embedded. He can be seen year round, in all weather, riding his Harley to and from work and play.

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.