C# Custom Actions with DTF
I’ve been working with DTF between Installshield 12 MSI and C# for a week or so now but have been having problems as I find very little documentation for people new to MSI. I thought that I’d write up some of what I have found and how I am using it. Hopefully this will save someone out there some time. Also, if you see something wrong here or would suggest doing something differently please let me know.
First, let me talk about what I have been reading about writing custom actions in managed code. I see many many places that state that you should never write your custom action s in managed code. There are many reasons given but I think that I can put them into four groups.
1). If you have custom actions in .NET you must have the .NET Framework as a prerequisite of the install.
2.) . Managed code custom action s must be run in a separate process… so there is no two way communication between MSI and the custom action.
3.) “Weird Things” happen. I have not seen any of these things myself but have seen mention of some strange behavior.
4.) You can do most everything you could need to do in MSI commands…so there’s really no reason to have any custom actions anyway.
In our case we are developing C# applications so the requirement for the .NET framework is not an issue and being a C# house we’d like to have all code that is reasonable in C# for ease of support. So, issue 1 and 4 above are not important to us. As we are using C# for our custom actions we’d like to update the status text, progress bar, and write to the install log. This hits on problem 2. Also, after reading about the strange issues others have had I’m a little concerned about item 3 above.
What’s the fix to 2 and 3? Looks to be DTF. Deployment Tools Foundations is a new set of tools released by Microsoft with the Wix installer. Basically what it does is compiles down C# custom actions to look to MSI like a standard MSI dll.
To get started check out this site http://www.installsite.org/pages/en/msifaq/a/1044.htm it explains things much better than I can.
To download the DTF go to http://wix.sourceforge.net/downloadv3.html and get ProjectAggregator and Wix 3.0 msi. After installing you can open Visual Studio and create a “C# Custom Action Project.” In this project you will have a CustomAction.cs file. Containing something like this:
public static ActionResult CommunicationServer(Session session)
Action result seems to be the only way to return results of the custom action to the MSI. If an exception is thrown in the code and not handled the MSI install seems to stop immediately and not run a rollback! Make sure to catch all exceptions and return a ActionResult.Failure to cleanly rollback install!
Session is the connection to the MSI. With this you can send messages to MSI and can access properties. The messages that I have figured out are…
internal static void StatusMessage(Session session, string status)
Record record = new Record(3);
record = "callAddProgressInfo";
record = status;
record = "Incrementing tick  of ";
Will set the status text box. Not sure what use there is to the first and third elements of the record, but only works if second element is set to the text to be shown. This is probably very important to find the answer to…but still have not found it.
internal static void ThrowInstallError(Session session, string ErrorMessage)
Record record = new Record(1);
record = ErrorMessage;
This will prompt the user with a textbox from InstallShield. I’d like it to show the error icon but shows the info icon. Another thing to still figure out…
Still have not figured out how to work with the progress bar. I know that it uses the same message command as above but with a message type of InstallMessage.Progress. I also know that first you have to send it a Progress message to set number of ticks in the progress bar. After this you either send a progress message to state the number of ticks to advance the bar everytime that a InstallMessage.ActionData message is received or just send another InstallMessage.Progress message to state number of ticks to advance. This has not worked at all for me…so another thing to still figure out.
Last thing I’ve worked on was accessing properties. If your custom action is schedule to run immediately this is very easy. To access the INSTALLDIR property in InstallShield you just call..
String Path = session[“INSTALLDIR”]
If your custom action is defered it’s much more complicated as MSI does not allow access to properties from defered custom actions. You have to add another custom action to run before this custom action of type “New Set Property.” Schedule this custom action to run just before your C# custom action and make sure that it has the same Condition. For the Property Name set the name of the C# custom action. For the Property Value set a list of values in this format:
This will allow you in the code to access these properties using this syntax.
string Path = session.CustomActionData["InstallDir"];
So, these are some of the very basic things that I’ve figured out about DTF. Not sure if this will be helpful to anyone…but these were the things I was looking for a week ago but could not find them..so thought I’d post them here.
I wrote a few articles on my blog about DTF and I'm always looking for additional team bloggers if you'd like to continue to write on DTF and other topics.
BTW, your exception handling pattern is opposite of what Jason suggests. He says there is a built in exception handler that'll return success or failure. That's been my experience also.
for contact information
Thanks for posting these tips, they certainly helped me. I am coming in as a complete newbie to MSI's and DTF's so this helped me understand a lot of what I needed.
for contact information
More DTF clarification needed please
I have experience writing written custom actions in C++ and VBScript. I am not a C++ developer, but can modify and create functions in existing DLL's. Now, IS 2009 allows us to write managed custom actions using .Net. I am just learning C# and have a long way to go, as far as learning OOP. I have a small 2009 Basic MSI with VBScript CA's that I wish to re-do using C# for my CA's. I will figure out what I need to do in C# so that the C# functions do the same thing that the VBScript functions do. What I need help with is understanding how to use C# to be able to interface with the installer session object.
I have looked at (1) http://blog.deploymentengineering.co...i-managed.html. Using this as an example I did create my own managed custom action that instead of returning a random number, I displayed a messagebox…so I know that I can create a managed custom action. I am unclear though on the concept of getting and setting session object properties using the example provided. Is this saying that you must use the Method Signature\Return Property to be able to set properties in the object session, and if so, (since you can only return once), that you can only set one property at a time in a function (or can you use the session object)? Also, how do you get session properties, do they have to be passed as arguments to the managed custom action, or, can you retrieve them using the session object?
I have also looked at (2) http://blog.deploymentengineering.co...tf-custom.html.
Being new to .NET, and DTF, I am confused by the following statements from the two links above. From (1)..." It solves the problem of tatooing the msi process with a fixed version of the CLR”. From (2)…” If you don't mind adding the .NET framework as a dependency to your install and you want to write custom actions in managed code, DTF rocks.”
As for (2), is this saying that the only way to use the session object to get and set propertys is to use this method? This (with my lack of experience in .Net and C#), looks intimidating and appears to be a long learning curve. It appears to be saying to me that I have to learn WIX, Visual Studio, DTF, etc. etc.
These articles are dated six months ago, and more (they talk about beta). Is there more, or better, or more current documentation on these subjects, somewhere (on any of the subjects that I will need to learn), that is written for the novice rather then the experienced WIX\DTF developer? I am not asking for anyone to do my work, just point me to, and\or give me some examples. It appears (from what I can find on these forums, and my online searches), that there is a need for a forum that is specific to InstallShield and these subjects.