The Desktop FilesExtending Windows PE
Even before we released Windows PE over five years ago, eager customers were already asking for more features. Unfortunately, Windows PE wasn’t designed to be easily extended the way that, say, Windows XP Embedded can be—by adding in additional layers of the operating system. Of course, Windows PE had to have rudimentary
Win32® support (so most Windows® applications would work), and networking and mass-storage support (to communicate over the network and be able to install Windows). But even from the start the shell was something we wanted to constrain; by using cmd.exe instead of the traditional Windows Explorer shell, we limited what the Windows PE environment could do and, more importantly, we made it so the default environment was easily scriptable for all automation tasks.
Still, you can extend Windows PE—you just have to remember that it is limited. You can expect that your application may not work or may behave incorrectly if it requires any of the technologies listed in Figure 1 (this list is not comprehensive).
Figure 1 Missing Windows APIs
|.NET Framework (any version)|
|Active Directory® Services Interfaces (ADSI)|
|Microsoft Data Access Components (MDAC)|
|Visual Basic® (pre-.NET versions included)|
|Any executable type that requires a framework that isn't installed with Windows natively.|
|Windows Explorer or Internet Explorer|
|Windows Media® Player|
|SAPI, MAPI, TAPI (Windows Speech, Mail, Telephony APIs, respectively)|
If you don’t know what your application depends on, you need to find out. But how? When we were trying to get the ADO, HTML Applications (HTA), and Windows Script Host (WSH) components to work under Windows PE before we released it, we faced the same issue. It should be noted however, that while this article will describe ways for you to track down these dependencies, adding any Windows binaries to your Windows PE image beyond what the MKIMG command includes is not covered by the End User License Agreement (EULA). You’ll need to acquire a licensing addendum from Microsoft in order to implement changes of that nature in your environment.
If you open up an application’s .inf file in Notepad and carefully examine it, you can learn a great deal. In fact, this is often the easiest way to make sense of an application and see what dependencies it has. The important thing to know about Windows PE is that generally it’s so pared down that you’ll have to debug multiple levels of dependencies—both your application’s own direct dependencies and the dependencies that each of those may bring in—in order to get your application running reliably. In essence, a pretty big cascade of dependencies can occur if you aren’t careful. With a few accidental (or purposeful) component additions, your image can grow considerably in size and complexity.
If you do have a .inf file that describes the application, you can get clues about dependencies by finding registry keys and files that the .inf adds to your system. Look for the CopyFiles and AddReg sections. These entries will point to apps, DLLs, and other files that your application depends on. Of the three add-ins for Windows PE (ADO, HTA, and WSH), WSH was the simplest to create. Because a redistributable version of WSH was still available for older Windows versions, and because there is a .inf built into Windows today that performs the file associations for WSH (at %windir%\inf\wsh.inf), installing it into Windows PE was relatively easy.
Orca and Snapshotting
If the application in question is distributed as a Microsoft® Installer (MSI) file, you can do two things to locate dependencies. If you’re an MSI guru, you can use Orca (a tool for editing Windows Installer files that is distributed as a part of the Windows Server® 2003 R2 Platform SDK: go.microsoft.com/fwlink/?LinkId=77941) to view it. You can also install the MSI for the components you want, performing a before-and-after analysis of the files and registry keys that have changed. You can do a dump of the registry, install the app, export the registry again, and then run WinDiff against it (see the "Using WinDiff" sidebar). The result can then be used as a template for changes that need to be made to the registry. The problem is that the number of changes can be mind-numbing. Nevertheless, it may be the best option if you don’t have a .inf (or the application’s author) handy.
You may be familiar with the process of application snapshotting. In essence, it’s that same before-and-after analysis you perform to get your application to run. Microsoft used to distribute (with Windows 2000) a tool that did this but that tool doesn’t work with any newer version of Windows. A number of commercial applications (installation repackagers) can do it, but so do some free utilities. For one solution, install the Platform SDK (see the link in the previous paragraph), which includes WinDiff. Note that to perform the WinDiff comparison, you ideally want to install the application on Windows Server 2003, Service Pack 1 (SP1) because that’s the version of Windows PE you should be using—Windows PE 1.6 as built from Standard Edition or Enterprise Edition (with SP1). By performing this task on Windows Server 2003 you’ll have the environment closest to what you would get on Windows PE (where obviously you can’t execute an MSI). Follow the steps in the "Using WinDiff" sidebar.
This will show you a fair amount of information that has changed. Regrettably, there isn’t an easy way to export the changed information from registry or file captures to create a manifest of some type to install your application. You need to incorporate the changes manually. This is where we encountered some of our toughest issues with the first version of Windows PE. Getting the HTA components working at all was complex since there was no definition for them (outside of Internet Explorer®) within Microsoft. By using differencing, we were able to hand-stitch enough HTA support so it would function. While you can manually add these keys into the Windows PE registry, you may want to add the keys after Windows PE has started. You can look at the OC.bat and OC2.bat files used to install HTA, WSH, and/or ADO support into Windows PE via the buildoptionalcomponents.vbs script included in the Windows PE build tools.
Even after isolating the direct dependencies, you often can’t find every binary your application depends on. You won’t know, for example, if it requires another DLL or OCX to perform some task. So, how can you tell? Mark Russinovich of Sysinternals fame (now a Technical Fellow at Microsoft) wrote a handy utility called listdlls that does exactly that. Listdlls can be downloaded from microsoft.com/technet/sysinternals/utilities/ListDlls.mspx. To use the utility, run the command listdlls.exe > dlls.txt and then examine the output. Figure 2 shows the output of listdlls run on itself. You can compare this list to the DLL and OCX files included in Windows PE to determine whether all of your application’s dependencies are in place or not (in the case of listdlls, they’re already present). For HTA support in Windows PE, listdlls was critical for identifying some dependencies that could not be identified otherwise.
Figure 2** Output of Lisdlls Run on Itself **(Click the image for a larger view)
But just because a DLL is listed doesn’t necessarily mean the application requires it to function. If you load Notepad, for example, you’ll see it loads uxtheme.dll. Under Windows PE, this DLL isn’t available and, in fact, since Windows themes aren’t used, it will never be loaded. Learning which of the DLLs listdlls shows you are actually required versus which are loaded on demand by Windows is, unfortunately, a dark art that will require either a fair amount of trial and error or that you become very familiar with low-level aspects of Windows (For this, I recommend Mark Russinovich and David Solomon’s book, Microsoft Windows Internals, Fourth Edition (Microsoft Press®, 2004).
In fact, Mark also includes the same functionality in the freely available Process Explorer replacement for Windows Task Manager. The difference is that listdlls creates output that, in my opinion, is more easily scripted and used for finding and collecting missing dependencies.
Note that even once you add a DLL to your image, you may still have some work to do. That is, there are two types of DLLs: those that require registration and those that do not. Unfortunately, there isn’t an easy way to tell them apart, short of trying to register each one. In order to register a DLL (or an OCX), you run regsvr32 dllname.dll. If it works correctly, you receive a dialog telling you the DLL was registered. If not, you may not receive a message or more likely you’ll see a dialog box informing you either that the DLL failed to register or that it couldn’t be registered. While developing the HTA and ADO optional components for Windows PE, we discovered that DLLs require writable storage when performing their registration, either to temporarily write a .inf file for installation or to record some other dependency (say, a specific directory they require). In Windows PE, this used to mean failure. Thankfully, with Windows PE 2.0, tasks like these will just work, since there is scratch space available by default.
A third tool Mark created and recently released is called Process Monitor. Process Monitor can be viewed as a superset of Regmon and Filemon, yet provides significantly more detail than either while adding a whole new layer of interprocess communication. This incredibly powerful tool can help you troubleshoot applications in Windows as well as help you answer questions about what’s really happening with DLL interdependencies. Process Monitor can be downloaded.
Removing Windows PE files
Along with the ability to add things to Windows PE, another frequent request was for instruction on how to make Windows PE smaller. There are steps you can take to reduce the size of Windows PE a bit. Your licensed copy of Windows PE should include a collection of build tools and some documentation. One of the documents is a help file named winpe.chm. If you open this file and explore the Windows Preinstallation Environment User’s Guide section, you should see a topic entitled Reducing the Size of Windows PE. This section lists a collection of files you can safely remove (assuming you don’t need them). You’ll find three sections regarding the removable files:
- Font files can always be safely removed.
- Networking-related .inf files and utilities can be removed, but only do this if you don’t plan to use your build on the network at all.
- Command-line utilities should not be removed. I don’t recommend removing any of these unless you explicitly know what it does and what might happen if you remove it.
Once you’ve determined which files you can safely exclude, you can simply write a batch file or other script and remove them from your Windows PE build once mkimg.cmd has completed the build.
Modifying the Windows PE Registry
You can see that we made a conscious choice to not install the optional components at build time. Though this meant a bit more time at run time, it also meant we didn’t have to engineer a completely new way to stitch these components back into Windows PE—something we didn’t have time to do and that would have most likely meant omitting them entirely. But what if you want to make a registry change, such as adding in the delta of registry changes for your application, or you simply want to edit a key that might be keeping the application working? This is accomplished easily, using regedit, which is shown in Figure 3. Follow these steps:
- Run regedit and select the HKEY_LOCAL_MACHINE hive.
- Select File | Load Hive, then browse to the location of your Windows PE build. Select setupreg.hiv under I386\System32\ (or MiniNT\System32, if this is an image you are putting on a hard drive).
- Enter a temporary name for the hive, such as WinPE, and browse to that node under HKLM.
- Modify this key accordingly. Interestingly, note that this node is effectively the same as the node HKLM\System would be on a normal Windows installation.
- Once you’ve made your modifications, select the key under HKLM you created in Step 3 (it is very important to do this correctly or you could damage your system).
- Select File | Unload Hive... and confirm the Yes | No dialog, and ensure you dismount the registry every time, as having it locked will prevent a successful build of Windows PE.
Figure 3** Opening the Windows PE Registry **(Click the image for a larger view)
By following these steps you can modify HKLM\System. There are also two other keys located under I386\System32 that let you modify other areas of the registry: DEFAULT is the default hive for users (even SYSTEM, which you run as while using Windows PE), and SOFTWARE, which is the same as HKLM\Software. As always, modify the registry with care and only as required.
Now you have some insight that should help you get started moving your favorite troubleshooting or recovery tool onto Windows PE. Next month, I’ll discuss the PSTools suite—which is a collection of very useful system management tools also written by Mark Russinovich.
WinDiff can help you find your application’s dependencies. Just follow these steps for successful installation and execution:
- Get your system prepared for the installation—you want to minimize the time and any file or registry changes between the initial and final snapshot.
- Open a command prompt and run reg export HKLM C:\HKLM1.reg to perform a complete export of the HKEY_Local_Machine registry hive.
- Run dir C:\*.* /S > C:\C1.txt to perform a compete dump of all files on the C: drive (assuming C: is your system drive).
- Install your application and configure any post-install settings.
- Run reg export HKLM C:\HKLM2.reg.
- Run dir C:\*.* /S > C:\C2.txt.
- Open WinDiff, and select File | Compare Files... and select HKLM1 .reg in the first File Open dialog, and HKLM2.reg in the second.
- You should see a message in red denoting which is newer. Be patient; this may take some time as the HKLM exports can be quite large.
- Double-click the text in red to expand the differences.
- You may want to configure what is shown in the comparison by checking Options | Show Right-Only Lines. This will enable only newly added lines in the second compared file to show up (so only new files and new registry keys will appear).
Note that you may need to use the Find function to locate keys related to your application. In Figures A and B, you can see file and registry changes for a fictional application I created. Happily, copy and paste are available in WinDiff. To use these functions simply click on the !> line and select the desired lines.
Figure A** WinDiff Entries **(Click the image for a larger view)
Figure B** Specific Key in WinDiff **(Click the image for a larger view)
Wes Miller is Development Manager at Pluck www.pluck.com in Austin, Texas. Previously, Wes worked at Winternals Software in Austin, and at Microsoft as a Program Manager and Product Manager for Windows. Wes can be reached at email@example.com.
© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.