Componentizing Applications (XPe)

4/24/2012

Microsoft Corporation

January 2009

This technical article contains information about componentizing applications and provides a step-by-step example using Winamp Lite.

Component Designer is the tool for developers to create their own custom components. Usually these components are created to enable a third-party driver for inclusion in the run-time image or for a line-of-business application to be in the run-time image when it is deployed. Creating custom components can be a somewhat time-consuming task, and this document will help explain the process.

The most important benefit of componentizing applications is reduced footprint. By componentizing, a developer has complete control of what files and resources are included in the component so no extraneous, unnecessary files are brought into the run-time image when the application is included. Footprint reduction can also decrease costs for media such as CompactFlash, or make room for more functionality. Components are also reusable. An application can be added to multiple run-time image configurations at build time instead of requiring manual installation after the run-time image has started and completed First Boot Agent (FBA).

In addition to helping meet space requirements, componentization has the following benefits:

  • Performance
    Reducing disk and memory use can significantly improve performance of both the platform and your software.
  • Reliability
    Generally, reliability increases with fewer executable files running and interacting with one another, devices, and the user.
  • Customization
    Componentization enables fine-grained customization that is not possible by using traditional setup programs.
  • Licensing
    By using more customization, you can license very specific areas of functionality and more easily guarantee compliance.
  • Security
    Devices that contain only the components that are required for their functionality are more secure, because they have a smaller surface attack area. Security can also be increased with components that add functionality such as encryption or antivirus protection.

We highly recommend applications and driver be componentized, but it is not required. Alternative solutions for including applications in a run-time image include running an .msi file during FBA by using an FBA Generic Command in a custom component, or from the desktop as soon as FBA has finished. Using this approach may require additional components, for example, the Windows Installer component is added to the configuration to support the installer. We emphasize that an application can only install and function correctly when the required dependent components are also included in the configuration. Therefore, dependency analysis of the application must be done.

Risks of not componentizing include larger footprint, which means larger surface attack area. Applications may frequently be packaged with files that you may have to uninstall. This is to support Add/Remove functionality in Windows XP Professional, which is not available in Windows XP Embedded. Applications may also be packaged with files required for servicing, so that an application can be rolled back to an earlier version. The uninstall and servicing files would create a much larger image. Also, Windows XP Embedded has no Windows file protection therefore, any file such as system files, can be overwritten by an application installation.

This section contains a list of steps which can be applied to componentizing most third-party applications and drivers. This step-by-step example uses a lightweight multimedia player from Nullsoft, Winamp Lite 5.08e, as the application to be componentized. To download the example application, visit this Web site.

The self-extracting .exe file name is Winamp508e_lite.exe. The size of this package is 516 KB uncompressed and although the small file size may imply minimal dependencies, small applications can still have big dependencies. For example, an application that is written in managed code would require bringing in the complete .NET Framework.

The basic steps in componentization are as follows:

  1. Start with a clean reference computer
  2. Install a system monitoring utility
  3. Download and install the application
  4. Capture results from the monitoring utility
  5. Analyze the change list and add information to your custom component
  6. Collect files and add to the repository
  7. Analyze static dependencies of the file and add dependency information to your custom component
  8. Import your component and deploy a run-time image with the application testing.

Step 1 - Start with a Clean Reference Computer

To start, you will need a computer running Windows XP Professional as your reference computer. This is the computer that you will monitor the installation of the application on. This computer should be as clean as possible with minimal applications installed and should not contain a similar application, for example, Windows Media Player. We recommended that you install the Windows XP Embedded tools on this computer, this makes it much easier to populate resources to your customer component later.

Step 2 - Install a System Monitoring Utility

There are many system monitoring utilities available such as AShampoo, InCtrl5, and Component Helper. Each of them is similar because they monitor the registry keys and files that are changed, deleted, or added during the installation of an application.

The system monitoring utility takes a snapshot of the state of the computer before the installation of the application, and then another snapshot when the installation is complete, and writes a log of the changes.

For more information about AShampoo, visit this Web site.

For more information about InCtrl5, visit this Web site.

For more information about Component Helper, visit this Web site.

Dd873579.a3081a42-1588-4071-98d0-7ff2cc7ca285(en-us,MSDN.10).gif

Step 3 - Download and Install the Application

After you download the application to your reference computer, start the monitoring tool and start the installation of the application. As soon as the application has installed and you have verified that it starts correctly and seems to function as expected, turn off the monitoring utility so that you are no longer capturing information. Utilities may capture much more Windows activity than bin placing files and adding or changing registry keys. Windows is always doing something in the background, for example, creating prefetch data, or updating the most recently used (MRU) list for Explorer. The sooner you turn off the utility after verifying the application runs, the less noise there will be in the log to sift through.

Step 4 - Capture Results from the Monitoring Utility

Start the monitoring utility, and then install Winamp Lite and capture the change log. After the monitoring process is complete, save the change log to your hard disk drive.

The log should show approximately 20 files that are placed in the Program Files\Winamp folders and subfolders, and a Winamp.ini file dropped into the System32 folder. This log is the basis for building the custom component.

Dd873579.559005b0-fc15-4f74-9fd1-2b4563cf893a(en-us,MSDN.10).gif

This is the list of installed files:

  • Demo.mp3
  • Gen_hotkeys.dll
  • Gen_jumpex.dll
  • Gen_tray.dll
  • In_cdda.dll
  • In_mp3.dll
  • In_wave.dll
  • Out_ds.dll
  • Out_wave.dll
  • Uninstall Winamp.lnk
  • UninstWA.exe
  • Vis_nsfs.dll
  • What's New.lnk
  • Whatsnew.txt
  • Winamp.exe
  • Winamp.ini
  • Winamp.lks
  • Winamp.lnk
  • Winamp.m3u
  • Winamp.q1
  • Winampa.exe
  • Winampmb.htm
  • Winamp.ini (in \Windows\System32)

Step 5 - Analyze the Change List and Add Information to Your Custom Component

Depending on the monitoring utility you use, your installation information may be presented in a UI form or in a text file. Either way, it should output the files and registry keys that are added, deleted, or changed as part of the installation. It is important to analyze the log file to determine whether all the files and registry keys that are part of a typical installation on Windows XP Professional are really necessary for an embedded installation. For example, Windows XP Embedded does not support uninstalling applications from Add Or Remove Programs, therefore, any uninstall files are not needed as file resources for your custom component. You may also want to ignore .lnk files, Help files, or any file in a Temp directory. This also applies to the registry keys. This process will help you streamline your component to be as small and efficient as possible.

In this example, you can ignore the following files:

  • Demo.mp3
  • Uninstall Winamp.lnk
  • UninstWA.exe
  • What's New.lnk
  • Whatsnew.txt
  • Winamp.lnk
  • Winampmb.htm

When you are ready to port your information to the component, the first step in creating a custom component is to create a folder named SLD to hold your application component and one named REP to hold all the physical files that make up the application itself.

In Component Designer create a Component object for example, WinAmp Lite, and a new Repository object, also with an intuitive name like Winamp Lite Repository, and save the .sld file to the SLD folder. Now you can start adding file and registry resources by using the monitor utility’s log file as your guide.

This is where it is so helpful to have the Windows XP Embedded Tools installed on the reference computer. In Component Designer you can choose Add Files in Folder, browse to the folders where the application files are installed, and add those files as resources to your custom component. This automatically resolves the correct path for those file resources.

In the case of the WinAmp Lite, Component Designer may warn about file overwrite because there are two files that have the same name but that exist in two different folders on the reference computer. For example, Winamp.ini may be in both the Program files\Winamp folder and the \Windows\System32 folder.

Because both files eventually have to reside in the same root Winamp file repository, decorate the name of one of the files.

Go to that file resource in Component Designer and double-click on the file entry. The Target Name remains Winamp.ini, but the Source Name entry needs to map to what Target Designer should look for in the Winamp repository.

Change the Source Name to windows_system32_winamp.ini. The registry keys can be added in a similar manner, navigating to the registry branches on the reference computer to add all the keys under that branch.

It is important that the Repository object is associated with the correct Source Path, which points to the folder that will contain all the files for the application. The default REP location is .\, click Browse and browse to the REP folder that you created above. It should now display .\..\Rep.

You can also create a Winamp Package object, which you can associate your component and repository with. In the repository Group Membership node, select Add Group Membership and expand the Packages node to see all available packages in the database and in the .sld. This should include your new package even though you have not imported it yet. You will see the new Winamp Package object; select this in order to associate your Repository object with the package. Do the same for your component.

Having all objects in a .sld associated with a package is useful. If you later have to delete Winamp from the database, you can just delete the Winamp Package from Database Manager and everything associated with it will also be removed. This is especially useful if your .sld contains multiple components.

Next, under the Winamp component, go to the Group Memberships node and select Add Group Membership and assign it to an appropriate category, for example, Test and Development.

Dd873579.00c4c46b-3165-4019-8ab6-57bcf509fad1(en-us,MSDN.10).gif

In this component example, do not add any custom actions in the Resources node of the component. This is where items like RunOnce actions are specified, scripts can run, or DLL's registered. For more information on the different settings that you can specify in the Resources node see this Web site.

Dd873579.ec6b7269-91c2-4ac5-a68d-bd3d4ce4a386(en-us,MSDN.10).gif

Custom components can also have memberships on certain prototype components such as Shell or MUI prototypes.

In this example, if you want Winamp to be the shell that users see when they log in, you should add other properties to your component.

  1. On the Component Properties page, select Prototype and then browse to Software, System, User Interface, Shells, Windows Shell.

  2. Select the Shell Prototype Component and click OK

  3. Set an extended property for this component by clicking Advanced on the Component Properties page and choosing Add in the Advanced Properties dialog box

    The Extended Property dialog box contains three fields: Name, Format and Value.

  4. Set the Name field to cmiShellPath.

  5. Set the Format field to String.

  6. Set the Value field to the path of the executable for your shell, in this case \Program Files\Winamp\Winamp.exe.

  7. Add a Group Dependency on the Shell dependency group (the same way you add a Component Dependency)

Step 6 - Collect Files and Add to the Repository

Now that you have the component file and registry resources completed, it is time to build your repository. Using the file resources as your checklist, collect all the files from your reference computer and put them in the REP folder. Be aware that the component repository has to be a flat folder, it cannot have any subfolders, so make sure that you put all the files in the root. This is the reason why files that have the same name have to be decorated in the repository, so there is no conflict. In your example you decorated the one Winamp.ini file in Component Designer to Windows_system32_winamp.ini. You will need to rename the winamp.ini file found on the reference machine under Windows\System32 to Windows_system32_winamp.ini before adding it to the REP folder. This will make sure that Target Designer will find the correct file in the repository when it builds an image. The size of the repository in this example is 1.84MB uncompressed, 1.24MB compressed.

Step 7 - Analyze Static Dependencies of the File and Add Dependency Information to Your Custom Component

The next step in this process to is to determine the component dependencies.

A dependency is any entity (file, registry key, registry value, process, service) which must be present for an executable binary to function appropriately.

Typically, appropriate behavior in Windows XP Embedded is defined as the same behavior exhibited as on Windows XP Professional. There are two types of dependency analysis: Static and Dynamic.

Start by finding the static dependencies the Winamp files have on Windows features. You can visit this Web site to download and install Dependency Walker on your reference computer. Point the Dependency Walker tool to each of the .dll and .exe files in your repository.

Dd873579.note(en-us,MSDN.10).gifNote:
You do not have to check for dependencies on ASCII files, for example, .log files, .ini files or .inf files.
It will provide a list of dependencies that are recursively satisfied. But all you need is the first order of dependencies, not everything under that first level

This table lists applicable Winamp files and their dependent Windows files found using Dependency Walker. Duplicate dependencies are not listed.

Winamp File Resource Dependent Windows Files

Gen_hotkeys.dll

User32.dll, Kernel32.dll, Gdi32.dll, Comctl32.dll

Gen_jumpex.dll

Ws2_32.dll, Shell32.dll

In_cdda.dll

Ole32, Oleaut32, Winmm.dll

In_mp3.dll

Wsock32.dll

In_wave.dll

Msacm32.dll

Vis_nsfs.dll

Ddraw.dll

Winamp.exe

Comdlg32.dll

With the list of file dependencies, you can use the Filter Manager feature in Target Designer to find the owning component for each file. Notice that some core operating system files like Kernel32.dll may have hidden components, but those components are brought into all configurations, so you generally do not have to worry about how to locate it if the component is hidden in the database.

  1. Open Target Designer, choose Tools, then choose Filter Manager.

  2. Choose New to create a new filter.

  3. Type a name for this filter, for example, Winamp Files.

  4. Under Filter rules, scroll down and select Component contains the following file.

  5. Click Add Rule.

    A new blank rule will display in the bottom window

  6. Double-click the new blank rule in the bottom window and enter one of the static dependency files, for example, Ddraw.dll.

  7. Add a new rule for each file in the list above under the Dependent Files column.

    Be sure that you select the option button for the OR operator for each line. This returns a list of the components that own each file.

  8. When you are finished adding the list of components to your filter, click OK.

    Your filter will resemble this one that has 3 of the files listed:

    Dd873579.7292f7ec-1d4d-4fe0-99c7-ff0f401e057b(en-us,MSDN.10).gif
  9. Now click Apply Filter and Target Designer will search through the database for the components that own each file resource listed in the rules.

    The filter will return a list similar to this one.

    Dd873579.87835273-d72b-4b36-9713-d4b61d45c8c5(en-us,MSDN.10).gif
  10. To add these dependencies to your component, open it in Component Designer, go to the Component or Group Dependency node, select Add Component Dependency and browse for each component returned in the filter list.

    Notice that you may find multiple versions of the components because one might be the Windows XP Embedded version and one might be a later hotfix version. Always select the component with the highest revision number.

Step 7 only covers static analysis of dependencies. This approach can only find load-time .dll dependencies which the program loader must resolve to load the code into memory. This is the most common dependency type and also the easiest to discover because all the information is in the PE header, which is well documented.

Occasionally, dependencies may be missed during development. These dependencies are usually discovered during testing of the component.

Step 8 - Import Your Component and Deploy for Testing.

Now the component can be imported into the database and added to a configuration to see whether it actually works. In this example, you can add it to a configuration that contains Winlogon Sample Macro and TCP/IP Networking with Client For MS Networks components. This is so you have network access if you need additional tools to troubleshoot. If you do not try to optimize the image footprint, at this point the built run-time image will be about 100 MB.

The first test is to play an .mp3 and a .wav file, which will fail. You may hear nothing from the speakers, and the progress bar that displays the current position in the song does not move. Winamp fails silently with no AV or errors.

Next, determine what is missing from the run-time files, or registry key, or both. Use dynamic analysis tools to find the dependency. This approach, if the tool is capable enough, can find all categories of dependencies.

A dynamic analysis tool typically finds dependencies by monitoring API calls made while an application executes. Monitoring every API call generates a large list of information, most of which is not useful, so only dependency-creating API calls are monitored. This still yields a large amount of data because some API functions are called frequently, for example, RegOpenKey, and there are many API functions which can create a dependency. However, the primary limitation of dynamic analysis is that if you do not execute the code which creates the dependency, you will not discover the dependency.

You can use a monitoring tool like FileMon for Windows v7.04 to view all file system activity in real-time. If there is a missing file that Winamp is trying to load to play the .mp3 file, Filemon would show the name of the missing file. You can then add the owning component for this file as a Component Dependency to your component.

RegMon for Windows v7.04 and Process Monitor v2.03 are other invaluable dynamic analysis tools.

For information about installing and using FileMon for Windows v7.04, visit this Microsoft Web site.

For more information about RegMon for Windows v7.04, visit this Microsoft Web site.

For more information about Process Monitor v2.03, visit this Microsoft Web site.

With FileMon running, play the .mp3 file again. The FileMon log will indicate that Winamp.exe is trying to load Dsound.dll but that this file is not found on the system.

As a quick test, you can copy Dsound.dll from the Windows XP Embedded repository, over the network, and place it in the run-time image System32 folder, and then play the .mp3 file again. This time it should play even without having to register the .dll. In this example, this will be the only missing dependency discovered, so add a Component Dependency on the owning component for Dsound.dll, DirectSound, to the Winamp component.

Other non-intuitive dependencies that an application may have are on COM or WMI, or on Fonts and Codepages (specifically in the case of a non-English application). You can also use the FBA log and the Setupapi.log to see whether there are problems with your custom component. The most common issue with custom components is that a dependency is missing from the configuration. If you suspect this is the case, you can always add one of the Compatibility Macro components to your configuration to see whether that satisfies the dependency. If this is the case, you can narrow your search to only the components the Compatibility Macro brought into your run-time image. For example, in this instance, you can add the Multimedia application Compatibility macro to your configuration and see if Winamp works after that. If this is the case, you know that one of the multimedia components is the one that you need to express a dependency in your component.

What you have learned

Using the example outlined above, you should be able to componentize your applications and drivers for inclusion in your Windows XP Embedded run-time image.

Show: