Using Linq to XML to Clean up ISString Tables

I was recently doing some cleanup work on an install that was getting a little long in the tooth and I noticed that it had a lot of pesky orphaned InstallShield String Table entries. Now if you are like me you always want to clean these up but first you need to be able to answer the question: Is this entry being used?

Fortunately with the help of .NET 3.5, C# and LINQ to XML it’s a piece of cake to find out. I was recently able to whip up this small little utility in less time then it’ll take me to blog about it.

Basically it’s a simple layout of all entries, used entries and orphaned entries. Let’s look at how easy .NET makes it to figure out which is which:

   1:  private void Process( string documentPath )
   2:  {
   3:    var document = XDocument.Load(documentPath);
   4:    var entries = from row in document.Descendants("row")
   5:                  where row.Parent.Attribute("name").Value == "ISString"
   6:                  select row.Elements().First().Value;
   7:   
   8:    List<string> stringEntries = entries.ToList();
   9:    document.Descendants("table").Where(w => w.Attribute("name").Value == "ISString").Remove();
  10:    string documentText = document.ToString();
  11:   
  12:    foreach (var entry in stringEntries)
  13:    {
  14:      listBoxAll.Items.Add( entry );
  15:      if( documentText.Contains( entry ))
  16:        listBoxUsed.Items.Add( entry );
  17:      else
  18:        listBoxOrphaned.Items.Add(entry);
  19:    }
  20:  }

The process is fairly straight forward. Load the ISM into the DOM; Query a list of ISString entry names; remove the ISString table from the DOM and then finally iterate through the list of names to see if the document contains a reference. It wouldn’t take but a few additional lines of code to let you select the entries to remove and automate the rest.

It takes a little time getting used to LINQ to XML but it really rocks once you get the hang of it.

Note: The above example doesn’t take into consideration entries that might be used by InstallScript as I don’t use InstallScript anymore.