In the past I had found some batch util that did text replace, but I found I was not comfortable putting this in my installer because batch files are like a black hole that get no reporting back to the log file. After the success with my previous post I felt confident that I could find something in c# that would allow this and reporting back to the log, plus it allowed me to learn a little more c#.
After searching I found a suitable sample. What this offered was to treat the xml file like a flat file because all I wanted was to replace a matched phrase with the value supplied by the user during install. This used the System.Text.RegularExpressions namespace to do the matching. What this sample does is load the file at once and do a match across the entire file. Because of this, it is only recommended for small files. Larger files will cause this to fail. With that in mind, here is my code used:
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Deployment.WindowsInstaller;
namespace TextReplaceUtil
{
public class CustomActions
{
[CustomAction]
public static ActionResult TextReplaceAll(Session session)
{
string AutoLogPrefix = "### COMPANY MESSAGE ### ";
// setup variables using properties from MSI database
// this will come from a deferred action, which will be comma delimited
// format of "What to find", "What to replace with", "absolute path + name of file"
string CustomActionData = session["CustomActionData"];
string[] MSIProperties = CustomActionData.Split(',');
string TextToReplace = MSIProperties[0];
string ReplaceWith = MSIProperties[1];
string FilePath = MSIProperties[2];
session.Log(AutoLogPrefix + "Begin TextReplaceAll action, values passed are: " + CustomActionData);
try
{
StreamReader reader = new StreamReader(FilePath);
string content = reader.ReadToEnd();
reader.Close();
content = Regex.Replace(content, TextToReplace, ReplaceWith);
StreamWriter writer = new StreamWriter(FilePath);
writer.Write(content);
writer.Close();
session.Log(AutoLogPrefix + "Successfully wrote to file " + FilePath);
}
catch(Exception e)
{
session.Log(AutoLogPrefix + "exception thrown was " + e.Message);
return ActionResult.Failure;
}
return ActionResult.Success;
}
}
}
Just like before, you use the .ca.dll after it is built. In this case you also need to create a set property action in addition to the MSI DLL action to build up the CustomActionData value that we will be using here. The comment in the code indicates the format of what is expected and the order it should arrive in. With a utility like this, you can use this for any need for text replacement in your installers.