Heya folks, Ned here again. Microsoft is legendary for its backwards compatibility. No other operating system family can claim to support as much older software and settings as Windows - heck, companies like Apple seem to proudly cut "legacy" support after a few years and spin it like it's a positive.

image
Man, that is an old app

We maintain legacy protocols for decades. We update our OSes for 10+ years free of charge, and then do best effort support forever. In the past week alone, I worked on two different NT 4.0 issues. I'm not sure how our recent college hires are going to handle those when I'm gone, since they were seven when that OS shipped o_O. We're it for the long haul because we're a software company, not a hardware company pretending to be otherwise.

Every blue moon though, we make changes to an existing component in order to fix a problem or get it in line with modern coding practices, and you’re left holding the bag when migrating between operating systems. Today I talk about one of those scenarios and how USMT can convert a registry data type on the fly in order to preserve your user's customized experience. If you’re instead looking to create a registry setting on the fly, go here.

A Sample Scenario

Windows allows users to choose how to click - double or single, with or without an underline. Any Windows version allows the same behavior and the Folder Options UI is the same:

image

However, XP and later operating systems differ in the storage method. Both values are in the following location, per user:

HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer

 ShellState

 IconUnderline

ShellState is stored in both OSes as a REG_BINARY value. However, IconUnderline is stored on XP as a REG_NONE and on Vista or Windows 7 as a REG_DWORD.

image

image

That means when you migrate from XP to Windows 7, your users keep their click preference, but lose their underline preference and instead get the OS default - which is not to show them underlines except on hover. That's the opposite of XP's behavior.

The Shell development team wrote two included manifests that control this behavior:

C:\usmt\X86\DLMANIFESTS>findstr /i "shellstate" *.man

EXPLORER-DL.MAN: <pattern type="Registry">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer [ShellState]</pattern>

 

<rules context="User">

  <include>

    <objectSet>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\Desktop [Taskbar]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\Desktop [TaskbarWinXP]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects [Settings]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2 [Settings]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\* [*]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [EnableAutoTray]</pattern>

      <pattern type="Registry">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer [ShellState]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage\* [*]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify\* [*]</pattern>

    </objectSet>

  </include>

 

C:\usmt\X86\DLMANIFESTS>findstr /i "iconunderline" *.man

 

SHELL32-DL.MAN:   <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [IconUnderline]</pattern>

<rules context="user">

  <include>

    <objectSet>

      <!-- Advanced Folder Option Settings -->

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState [*]</pattern>

      <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [IconUnderline]</pattern>

    </objectSet>

  </include>

</rules>

All of this behavior is expected and by design, although not an optimal one. That little REG_NONE beauty dates back to Windows 95 and Internet Explorer 4.0. When we were writing Vista, we decided enough was enough and to switched to a normal data type. It wasn't intentional that the manifests fail to convert the setting; that just slipped through the cracks.

So what can you do about it?

ConvertToDWORD

In its large bag of tricks, USMT includes an element named <contentModify> . When used during loadstate, it allows you to change the data before writing to the destination computer. This includes changing types or even writing new values.

In this case, I need the XP type to change to the Windows 7 type, so I use ConvertToDWORD:

<!-- Converts XP's REG_NONE setting to REG_DWORD -->
<
contentModify script=
"MigXmlHelper.ConvertToDWORD('3')">
 <
objectSet
>
  <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern
>
 </
objectSet
>
</
contentModify
>

<include>
 <
objectSet
>
  <
pattern type=
"Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern>

 </objectSet>
</
include
>

ConvertToDWORD('3') means change the data type from whatever it is currently to a DWORD registry value. If there is any problem converting, set the new DWORD value to 0x3. I chose 3 here because that is the default single-click behavior on XP.

It's Not Always Enough

Returning to the example scenario, I test my new XML and it's still not working: the destination Windows 7 computer is receiving the REG_NONE value. Can you guess why?

It's because, even though I am changing the migration behavior, I am doing it in the context of some new XML. I am not unconditionally excluding data, so the other guy copying this data - the included manifests - are overriding my decisions.

There are two ways to fix this:

The "Easier" Way (that is Hard to Control and Risky Long Term)

You could modify SHELL32-DL.MAN to include your new XML settings within its context. This version control nightmare is not recommended (bordering on not supported). We provide override mechanisms so that you don't need to modify the included down level and replacement manifests.

The "Harder" Way (that is Easy to Control and Safer Long Term)

1. Generate a CONFIG.XML on a test XP source computer using scanstate /genconfig config.xml

2. Set the following element to NO in the config.xml and save that file. Copy it to your USMT folder for use on all subsequent XP source computers:

<component displayname="Microsoft-Windows-shell32-DL" migrate="no" ID="http://www.microsoft.com/migration/1.0/migxmlext/cmi/microsoft-windows-shell32-dl/microsoft-windows-shell32-dl/settings"/>

3. Use the following sample in a custom XML file called by scanstate and loadstate. It does all the work of the XP downlevel Shell32 manifest, as well as converts the iconunderline to DWORD. Do not use any of these steps if Vista or Win7 are source computers - they have the correct data type already:

<?xml version="1.0" encoding="UTF-8"?>
<
migration urlid="
http://www.microsoft.com/migration/1.0/CustomIconUnderlineAndShell32">
 <
component context="User" type="Application"
>
  <
displayName>CustomIconUnderlineAndShell32</displayName
>
   <
role role="Settings"
>
   <!--
Used only when migrating from XP, in conjunction with CONFIG.XML where Shell32 is set to NO
-->
     <
rules context="user"
>
     <!--
Converts XP's REG_NONE setting to REG_DWORD
-->
      <
contentModify script="MigXmlHelper.ConvertToDWORD('3')"
>
       <
objectSet
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern
>
       </
objectSet
>
      </
contentModify
>
      <
include
>
       <
objectSet
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState [*]</pattern
>
        <
pattern type="File">%CSIDL_APPDATA%\Microsoft\Windows\Recent [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\* [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\ShellNoRoam\BagMRU\* [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\ShellNoRoam\Bags\* [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\Shell\BagMRU\* [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\Shell\Bags\* [*]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{450D8FBA-AD25-11D0-98A8-0800361B1103}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{450D8FBA-AD25-11D0-98A8-0800361B1103}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{20D04FE0-3AEA-1069-A2D8-08002B30309D}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{20D04FE0-3AEA-1069-A2D8-08002B30309D}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{208D2C60-3AEA-1069-A2D7-08002B30309D}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{208D2C60-3AEA-1069-A2D7-08002B30309D}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{871C5380-42A0-1069-A2EA-08002B30309D}]</pattern
>
        <
pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{871C5380-42A0-1069-A2EA-08002B30309D}]</pattern
>
       </
objectSet
>
      </
include
>
     </
rules
>
   </
role
>
 </
component
>
</
migration
>

4. Fire it up. Example, where I called my new custom code icon.xml:

image

image

image

Simple as that. Hopefully you find this this technique useful for other registry type issues that crop up.

Until next time.

Ned "get your money back" Pyle