Fixing ICE errors

From ORCA we got a pile of errors and warnings. I’ll try to fix all errors and most warnings. To look up the meaning of ICE errors, go to the Help menu in WPS and select Windows Installer SDK Help. (in the search, enter ICE57 not ICE 57 or 57)


ICE33 WARNING Reg key registry5 is used in an unsupported way. ProgId should be registered via the ProgId table. This entry may overwrite a value created through that table.

...

ICE33 WARNING Reg key registry103 is used in an unsupported way. ProgId - CLSID associations should be registered via the ProgId and Class tables. This entry may overwrite a value created through those tables.

...

ICE33 WARNING Reg key registry5 is used in an unsupported way. Extensions should be registered via the Extension table. This entry may overwrite a value created through that table.


ICE33 warnings are next to impossible to fix. The warning message hints to use the ProgId and Class tables. Discussing with other peers reveals that any attempt to fix ICE33 warnings are futile and will break the package.


ICE38 ERROR Component deployment.jssecerts installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file.

ICE38 ERROR Component deployment.properties installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file.


These ICE38 errors seems to be related to the ICE91 warnings. We’ll keep these ones for later. Sometimes fixing one ICE error fixes another or fixes warnings.


ICE49 WARNING Reg Entry 'registry1' is not of type REG_SZ. Default types must be REG_SZ on Win95 Systems. Make sure the component is conditionalized to never be installed on Win95 machines.


Let’s see what “registry1” is in the registry table

HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon

@=%SystemRoot%\SYSTEM32\shell32.dll,32 (as an unexpanded string)


It seems that %SystemRoot% is the part that Windows95 can’t digest. Question is: is it even needed?

So let’s look for “645FF040-5081-101B-9F08-00AA002F954E” in the tables? It doesn’t show up anywhere. So it seems that it is not needed. But what is it? From experience I know that inside Shell32.dll is a bunch of icons. 32 mean it is the 32nd icon in the dll. Using an Icon handler/editor to open the Shell32.dll we find out it is the icon for the empty recycle bin. It must have happened when I deleted the icons off the desktop and start menu or I inadvertently emptied the recycle bin during the capture. Either way, we definitely don’t need it.


Now, is this right? Compile and re-test to find out.

-If the ICE49 error for ‘registry1’ is gone then it’s right.

-If you get more errors, especially related to ‘registry1’, then it’s probably wrong.

In my case, I got 2 extra errors:

ICE02 ERROR Registry key: 'registry1' not found in Registry table.

ICE03 ERROR Not a valid foreign key; Table: Component, Column: KeyPath, Key(s): CurrentUser

It seems something needed ‘registry1’. So let’s do a search for registry1 in the tables:

It turns out registry1 was the KeyPath for the CurrentUser component. No problem, we’ll just change the KeyPath.

In Setup Editor, in the component tab, we find that the CurrentUser component is red meaning a problem. Right-click on it and select Show Errors..

Has an invalid Key Path. The key path should reference the key to a file, registry key, or an ODBC data source.

Ok, we get the message.

To change the KeyPath in Setup Editor we just select a registry key that is part of the component and right-click on it, select Set as Key:


Notice the gold key icon. That the KeyPath.

We now re-compile and re-test to find out that those new ICE2 and ICE3 errors are now gone.


Frame8




ICE57 ERROR Component 'javaws.exe' has both per-user and per-machine data with a per-machine KeyPath.


An ICE57 error means that the 'javaws.exe' component has both User (hive entries or profile files) and Machine (hive entries or files). That’s a no-no according to the MSI SDK.


In the Setup Editor, in the Components tab, we can see that the ‘javaws.exe’ component does indeed have user and machine registry entries.


Since most MSI packages have a special component called CurrentUser for the User hive and Profile stuff, we could change the component “Ownership” to CurrentUser and be done with it.

The problem is that the value for this registry entry is encoded with the full long path name to javaws.exe using the javaws.exe component. If we move it, it will just cause an ICE69 error (for you to try on your own...). The solution is to put the registry entry in the package “unencoded”.

Frame9


[#javaws.exe] is C:\Program Files\Java\j2re1.4.2_03\javaws\javaws.exe encoded.

-From within Setup Editor we can just double-click on the registry entry and change it.

-Click Ok

Now we can change the component.

-From the Setup Editor, either drag-n-drop this to the CurrentUser component or right-click on it and select Move and select CurrentUser. (NOTE: yes, there are other ways to change “component ownership”)


Now, is this right? Compile and re-test to find out.

-If the ICE57 error is gone then it’s right.

-If you get more errors, especially related to ‘registry4’, then it’s probably wrong.

In my case it’s gone.



ICE64 ERROR The directory Sun is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory javaws6 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory Deployment is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory Java1 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory javapi is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory cache is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory v1.0 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory security2 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory ext3 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory file is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory jar is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory tmp is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory tmp4 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory ext5 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory cache7 is in the user profile but is not listed in the RemoveFile table.

ICE64 ERROR The directory log is in the user profile but is not listed in the RemoveFile table.


ICE64 errors are directories in the user profile that will not be removed correctly during uninstall or roaming user scenarios. To fix this you usually create a row for each folder in the RemoveFile table. Before we do that, let’s see what these directories are in this package.

In Setup Expert:

We find that it’s a bunch of empty folders under a folder called Deployment. Hey, look there is that deployment.properties file that is related to the ICE91 and ICE38 errors! To me “deployment” means “install” as in Sun’s installer, so I am inclined to delete this whole Deployment folder and be done with this ICE error business. I know from experience, however, that the Java Plug-in gets some of its configuration information from a file in the user’s profile (Remember: Java is cross-platform and only Windows has a registry.) By looking inside the deployment.properties file, the first line says that it is the Java plug-in applet in the control panel that writes to it. Therefore we must keep it; otherwise it will revert to defaults. This also means all those folders are also need to be added to the RemoveFile table.

So let’s start with the first ICE64 error for the Sun directory.

-FileKey is anything. It’s just an identifying label. Let’s go with dir1

-Component_ usually, is the component that created the Sun folder to begin with. It doesn’t look obvious even by searching for Sun as a folder to locate its component. In this case though we can’t find which component created it. Let’s leave it blank (and cross our fingers...)

-FileName needs to be blank to specify a directory and not a file.

-DirProperty is for a property that contains the full path to the Sun folder in the user’s profile. The SDK says that this must be a property in the Directory table. So let’s look it up:

By using the name in the Directory column (it has the key icon), it seems to be Sun ( NOTE: this is a coincidence)

-InstallMode determines when the file is removed. A setting of 2 means to remove it at package removal time. (These details are in the SDK, search for RemoveFile)

And this gives us:

Now, is this right? Compile and re-test to find out.

-If the ICE64 error for the Sun folder is gone then it’s right.

-If you get more errors, especially related to the Sun folder, then it’s wrong.

I compiled and I got:

To boot, that row I just created in the RemoveFile table is gone!

According to the SDK for the RemoveFile table the Component_ column is not nullable. Translation: cannot be blank.

I found a component called Createfolder that does creates a good part of the folders that cause the ICE64 error but it doesn’t create the sun folder. We’ll try it anyway.

Let’s re-compile. It took the row! Now, is the ICE64 Error for the Sun directory gone?

ORCA says it’s gone.

Frame10


Now, let’s do the javaws6 directory.

-FileKey is dir2 (hey, I like consistency. You can call it FizzleDizzle if you want. It just a label)

-Component_ is like last time. So let’s use CreateFolder

-FileName is blank to specify a directory and not a file.

-DirProperty is for a property that contains the full path to the javaws folder in the user’s profile. The SDK says that this must be a property in the Directory table. So let’s look it up:

By using the name in the Directory column (it has the key icon), it seems to be javaws6. So that means that all the ICE64 errors refer to a property that contains the name of the folder. (They do this to deal with directories with the same name in the same package)

-InstallMode is 2

And this gives us:


And so on for a few of them:


For the ICE64 error with security2, however, I found a component:


So the next row is:


For the ICE64 error with ext3, however, I found it in the CreateFolder component:

The rest of the ICE64 errors show up here, too.

Now, is this right? Compile and re-test to find out.

-If the ICE64 errors are gone then it’s right.

-If you get more errors, especially related to the any of these folders, then we’ll fit it.

I compiled and all the ICE64 errors are gone.



Coming back to the ICE38 and ICE91 errors:

ICE38 ERROR Component deployment.jssecerts installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file.

ICE38 ERROR Component deployment.properties installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file.

ICE91 WARNING The file 'deployment.jssecerts' will be installed to the per user directory 'security2' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.

ICE91 WARNING The file 'deployment.properties' will be installed to the per user directory 'Deployment' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.

ICE91 WARNING The file 'deployment.certs' will be installed to the per user directory 'security2' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.


So let’s go see in Setup Editor in the Component tab if we can fix that.

Looks like neither have registry entries to use as a KeyPath. It seems like we are screwed.

We could, however, move the contents of both components into the CurrentUser component which does have a registry KeyPath to HKCU. It sounds a bit drastic so we take a backup of the WSI file before we do this. Just in case.

Copy Sun_JVM_v1_4_2_03.wsi to

Sun_JVM_v1_4_2_03__2.wsi

Or even

Sun_JVM_v1_4_2_03__2_No_ICE64_works.wsi in the same folder.


Heck, let’s make sure the resulting MSI works (as in runs Java Apps) before we go ahead. (I tested it and it still works)


To move the contents of the deployment.jssecerts and deployment.properties components we could right-click on each file and select move like I did above. In this case it is more efficient to drag-n-drop the files portion of each component into the CurrentUser component like this:

Drag-n-Drop everything out of those 2 components. Once they are completely empty delete them otherwise you’ll get ICE18 errors. Compile again and check what ORCA has to say.

ORCA says that there are no more ICE38 or ICE 91 errors but we do have a new ICE57 error.


ICE57 WARNING Component 'CurrentUser' has both per-user and per-machine data with an HKCU Registry KeyPath.


Now this doesn’t make much sense. We gave it what it wanted. Since it is just a warning maybe we can get away with it. In other words, does it work?

Testing the package shows that something is missing since the “Use Java Plug-In Default” is selected in the Control Panel applet. Looking into it some more shows that all the files that we move to the CurrentUser component never get installed!


Reverting back to a previous backup

Ok let revert back to the WSI file backup before we tried to resolve the ICE38 errors. (You did take a backup, right?) Let’s try something different.


Ok, let’s see if the SDK can help resolve our ICE38 errors.

It seems a bit ambiguous. If our “Component1” is deployment.properties

Translation: Change the 0 in the attribute column to something else and set the KeyPath to an entry in the registry table. Usually that registry KeyPath needs to be part of the component. It seems like there is no such limit in this part of the SDK.

So we go in the Components tab, right-click on the deployment.properties component and select Details.

Now we change the Key Path Type to Registry Key Path, click Ok. The component is now red because we didn’t set a KeyPath. Let’s try to set that in the tables.

I’m picking registry2 since that is an entry in the HKCU even though it’s part of the CurrentUser component. (I doubt that will work but hey, we are running out of options)


I compile and retest with ORCA and:


ICE02 ERROR Registry: 'registry2' cannot be the key registry key for Component: 'deployment.properties'. The RegKey belongs to Component: 'CurrentUser'


OK, it was a bad idea.



I guess we have 2 other solutions to satisfy ICE38:

-Create bogus entries in registry in the HKCU and make them part of the deployment.jssecerts and deployment.properties components.

-Steal (aka move) HKCU entries in registry from the CurrentUser component to the deployment.jssecerts and deployment.properties components.


I hate adding crud to packages so let’s steal one HKCU entry from the CurrentUser to give to the deployment.properties component and see what happens.

Go to the CurrentUser component and drill down to a registry entry that is in the HKEY_CURRENT_USER hive. Make sure




And let’s make sure that the deployment.properties component has that key as a KeyPath.


I tested in ORCA and one of the ICE38 errors is gone! We are on the right track (I hope). Let’s make sure by testing the MSI and see if the deployment.properties file is installed.

I performed a test install on the Testing PC and the deployment.properties file was installed properly and the plug-in still works.


Now, let’s steal another HKCU entry from the CurrentUser component to give to the deployment.jssecerts component to get rid of the other ICE38 error.

I performed a test install on the Testing PC and the deployment.jssecerts file was installed properly and the plug-in still works.


I tested in ORCA and all of the ICE38 errors are gone.


We are now left with ICE33 and ICE91 Warnings. The ICE33 warnings can’t be fixed but the ICE91 warnings might actually bite us later if you install as one user and try to run it as another:


ICE91 WARNING The file 'deployment.jssecerts' will be installed to the per user directory 'security2' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.

ICE91 WARNING The file 'deployment.properties' will be installed to the per user directory 'Deployment' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.

ICE91 WARNING The file 'deployment.certs' will be installed to the per user directory 'security2' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.


So, let’s find out.

-Re-image the Testing PC

-Install the MSI package as an admin user

-Logout

-Logon as Restricted User

-Check to see if deployment.jssecerts, deployment.certs and deployment.properties files and all the folders around them got copied. In the Restricted User’s case, the Application Data folder didn’t get the stuff, just like the ICE91 warnings hinted.

Is this a real problem? All we care about is if the plug-in works or not in the end.

Let’s find out.

While still a Restricted User on the Testing PC,

-go to a web site that requires the Java plug-in and let’s see.

-As it turns out, because this is the first time the plug in is required for that user, the MSI installer is launched and it check for the existence of all the KeyPaths.

-Since there is some missing keys in the HKCU, it “heals” the components that has those KeyPaths. (You can even see the MSI Installer entries in the Application Event log)

Doing so you see the MSI installer launch to “heal” the Java Plug-in and it creates the missing files and folders.

-Testing with another Restricted User seems to work as well.


It seems we got lucky here. In the case where we wouldn’t be so lucky, we could have used Custom Actions to launch a VBS or another mini-package of sorts but the tried-and-trued method to get out of jams like this is using Active Setup. Ed Tippelt has a blurb about Active Setup here so I won’t bother explaining how works.