Wednesday, July 15, 2009

Using XPath to modify app.config on setup

Sample code to modify the app.config when executing a setup package:

This assumes it is in the "Committed" event of a projectinstaller class. This sample only modifies a connectionString, but can easily be used for anything:

string assemblypath = Context.Parameters["assemblypath"];
string appConfigPath = assemblyPath + ".config";
XmlDocument doc = new XmlDocument();
doc.Load(appConfigPath);
XmlNode aConnection = doc.SelectSingleNode("/configuration/connectionStrings/add[@name=\"aConnectionIdentifier\"]");
aConnection.Attributes["connectionString"].Value = "Data Source=.;Initial Catalog=MyDatabase;User Id=MyUser;Password=MyPassword;";
doc.Save(appConfigPath);


Wednesday, July 8, 2009

Embedding your DLLs into your EXE

Good info at http://dotnetzip.codeplex.com/Wiki/View.aspx?title=Embed%20DotNetZip&referringTitle=Home for embedding your DLLs into your EXE, instead of having them separate. Not sure why you might want to do this, other than to obfusicate your code a bit, but you never know.

Great .NET Zip library

http://dotnetzip.codeplex.com is a super library for zip functionality in .NET. I had problems viewing the compiled help file that you can download, but there are so many examples on the website, it really isn't necessary. It offers functionality equivalent to what you can get with WinZip 9.0 (AES encryption, too).

Wednesday, July 1, 2009

ClickOnce and Team Build

Okay, I've figured it all out. First off, there are too many "Version" terms. There's the AssemblyVersion, the version the user sees on the landing page, the BuildNumber, which is commonly part of the "Version", and finally, the one thing my brain was not wrapping itself around, the "PublishVersion". This publish version is not visible to the end-user, but it's stored in the manifest and is key to letting the ClickOnce application know that an update is available. I was wanting to override it, but I wasn't fully grasping that it was really its own thing--separate from AssemblyVersion.

What I wanted was a PublishVersion that came from the Publish version on the properties page of the project, but used the ChangeSet in place of the Revision number. I didn't care if the Revision was updated in Source Control since it would always be ignored anyhow and overridden on each build.

Everything I found went through all sorts of hoops to basically accomplish this. Apparently MSBuild doesn't offer a simple way to pass this as a property on the task, so for awhile it appeared the only solution was to use MAGE somehow--but I wanted to avoid that because ther seemed to be such an overly-complicated set of configuration for it--it would also have to be used to generate the manifest

Then it occurred to me--the light bulb upstairs finally came on--why not just update the csproj file using a XMLModify to replace the Revision for the Publish version with the changeset. I could do this just like I modify the app.config file--in the AfterGet target override. It would be so simple and elegant--just one simple task to add to what I already had!

Well, for some reason I couldn't get Xml.ModifyFile to work on the csproj file, so I just switched over to File.Regex.

I also did find I had to make a minor tweak of the Regex that extracted the version. My Regex only worked if the Major, Minor, and build numbers were single digits. I just had to add a "+" after each bracket ("]") for it to work.

Finally, I had modified the Copy tasks that deployed the files to their deployment site so that only the necessary files would be copied, instead of every file (which originally included all DLLs and EXEs--I only needed the .DEPLOY and related files).

The template for this Team Build project can be found at http://docs.google.com/View?id=ddzhk5g7_2dgt2sxdj

I've uploaded the C# source code for the custom RegexCapture task to http://docs.google.com/View?id=ddzhk5g7_3gqtnz9fs