Having TFS generate a CAB file during the build of a Smart Device solution is a pain since CABWIZ is a particularly unfriendly tool. Below is a custom build task that greatly simplifies the process:
namespace OpenNETCF.Build.Utilities
{
using System;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Win32;
using System.Diagnostics;
/// <summary>
/// Uses CabWiz to create a Smart Device CAB installer.
/// </summary>
/// <example>
/// <code><![CDATA[
/// <CabWiz
/// InfPath="MyApp.inf"
/// ErrorLog="Error.log"
/// WorkingFolder="..\Build"
/// Cpu="x86"
/// Compress="true"
/// NoUninstall="false"
/// OutputPath="..\Release"
/// Platform="wm"
/// PreXml="Pre.xml"
/// PostXml="Post.xml"
/// />
/// ]]></code>
/// </example>
public sealed class CabWiz : ToolTask
{
[Required]
public string InfPath { get; set; }
public bool Compress { get; set; }
public string Cpu { get; set; }
public string ErrorLog { get; set; }
public bool NoUninstall { get; set; }
public string OutputPath { get; set; }
public string Platform { get; set; }
public string PostXml { get; set; }
public string PreXml { get; set; }
private static string CabWizSubPath
{
get { return @"SmartDevices\SDK\SDKTools"; }
}
protected override string ToolName
{
get { return "cabwiz.exe"; }
}
public override bool Execute()
{
bool ret = base.Execute();
if (!ret)
{
string path = Path.GetDirectoryName(InfPath);
path = Path.Combine(path, ErrorLog);
if (File.Exists(path))
{
Log.LogMessageFromText(string.Format("!!! BEGIN CABWIZ ERROR FILE DUMP !!!", path), MessageImportance.High);
Log.LogMessagesFromFile(path, MessageImportance.High);
Log.LogMessageFromText(string.Format("!!! END CABWIZ ERROR FILE DUMP !!!", path), MessageImportance.High);
}
else
{
Log.LogMessageFromText(string.Format("CABWIZ: Couldn't find error log at '{0}'", path), MessageImportance.High);
}
}
return ret;
}
protected override string GenerateFullPathToTool()
{
if (String.IsNullOrEmpty(ToolPath))
{
string path = string.Empty;
using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VS", false))
{
if (regKey != null)
{
path = (string)regKey.GetValue("ProductDir");
}
}
ToolPath = Path.Combine(path, CabWizSubPath);
}
return Path.Combine(ToolPath, ToolName);
}
protected override string GenerateCommandLineCommands()
{
GenerateFullPathToTool();
StringBuilder cabWizArgs = new StringBuilder();
cabWizArgs.AppendFormat("\"{0}\" ", InfPath);
if (!string.IsNullOrEmpty(OutputPath))
{
cabWizArgs.AppendFormat("/dest \"{0}\" ", OutputPath);
}
if (!string.IsNullOrEmpty(ErrorLog))
{
cabWizArgs.AppendFormat("/err \"{0}\" ", ErrorLog);
}
if (!string.IsNullOrEmpty(PreXml))
{
cabWizArgs.AppendFormat("/prexml \"{0}\" ", PreXml);
}
if (!string.IsNullOrEmpty(PostXml))
{
cabWizArgs.AppendFormat("/postxml \"{0}\" ", PostXml);
}
if (!string.IsNullOrEmpty(Cpu))
{
cabWizArgs.AppendFormat("/cpu {0} ", Cpu);
}
if (!string.IsNullOrEmpty(Platform))
{
cabWizArgs.AppendFormat("/platform {0} ", Platform);
}
if (Compress)
{
cabWizArgs.Append("/compress ");
}
if (NoUninstall)
{
cabWizArgs.Append("/nouninstall");
}
Log.LogMessage(MessageImportance.High, cabWizArgs.ToString());
return cabWizArgs.ToString();
}
}
}
Usage looks like this:
<CabWiz
InfPath="$(CABFolder)\MyINF.INF"
ErrorLog="Error.log"
OutputPath="$(CABFolder)" />