Attached is a modified version of the resgen task that I need some
second (third,forth,etc...) opinions on.
I re-wrote portions to handle two different issues that I encountered.
Currently the resgen task handles single files well, but breaks on
filesets. The biggest issue with the filesets, was the NeedsCompiling
routine. It only checked the single file properties, so would break if
those were null. I re-wrote that to handle the checking of filesets.
The second problem was one of needing to prepend namespaces on to the
.resx files. For instance, at our project at work, we needed to run our
Form1.resx, Form2.resx files through resgen and have them come out
"Viper.Form1.resources, Viper.Form2.resources". This was also a problem
that could be handled if you were using resgen on a file by file basis,
but not with filesets. So I added a "prepend" property. This property
will prepend anything you put in there to each outputed .resources file.
Another problem, which I have not tackled, is the culture one. Some may
want to resgen a file name form3.resx and have it come out
"Project.form3.en.resources". This case is not handled in my modified
version.
Anyway, here is my file for someone else to critique. I have not
prettied the code much (in fact haven't even bounced it against the
standards, I will do that), I also have not written any new tests for this.
It defintely works for our project (82 forms, in six different
projects), but I coded it for my use so I don't know if it fits
everybody elses issues, if i can make it better, etc...
I would appreciate any feedback. Thanks.
JT
// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Joe Jones ([EMAIL PROTECTED])
// Gerry Shaw ([EMAIL PROTECTED])
using System;
using System.IO;
using System.Text;
using SourceForge.NAnt.Attributes;
namespace SourceForge.NAnt.Tasks
{
/// <summary>Converts files from one resource format to another (wraps
Microsoft's resgen.exe).</summary>
/// <example>
/// <para>Convert a resource file from the .resx to the .resources
format</para>
/// <code>
/// <![CDATA[
/// <resgen input="translations.resx" output="translations.resources" />
/// ]]>
/// </code>
/// </example>
[TaskName("resgen")]
public class ResGenTask : ExternalProgramBase
{
string _arguments;
string _input = null;
string _output = null;
bool _compile = false;
string _prepend = null;
FileSet _resources = new FileSet();
/// <summary>Input file to process.</summary>
[TaskAttribute("input", Required=false)]
public string Input { get { return _input; } set { _input = value;} }
/// <summary>Name of the resource file to output.</summary>
[TaskAttribute("output", Required=false)]
public string Output {
get
{
if (_prepend == null || _prepend == "")
{
return _output;
}
else
{
int slash;
slash = _output.LastIndexOf(@"\");
if (slash == -1) {slash =
_output.LastIndexOf(@"/");}
if (slash != -1)
{
StringBuilder outf = new
StringBuilder();
outf.Append(_output.Substring(0,slash
+ 1));
outf.Append(_prepend);
outf.Append(_output.Substring(slash +
2, _output.Length + 1));
return outf.ToString();
}
else
{
return _prepend + _output;
}
}
}
set { _output = value; }
}
/// <summary>Any namespace information that needs to be appended to
the output.</summary>
[TaskAttribute("prepend", Required=false)]
public string Prepend { get { return _prepend; } set {_prepend = value
;} }
/// <summary>If true use the fileset to determine the list of files to convert
(<c>/compile</c> flag).</summary>
[TaskAttribute("compile")]
[BooleanValidator()]
public bool Compile { get { return _compile; } set {_compile = value;} }
/// <summary>Takes a list of .resX or .txt files to convert to .resources
files.</summary>
[FileSet("resources")]
public FileSet Resources { get { return _resources; } }
public override string ProgramFileName { get { return Name; } }
public override string ProgramArguments { get { return _arguments; } }
protected virtual void WriteOptions(TextWriter writer) {
}
protected string GetOutputPath() {
return Path.GetFullPath(Path.Combine(BaseDirectory, Output));
}
protected string GetInputPath() {
return Path.GetFullPath(Path.Combine(BaseDirectory, Input));
}
protected virtual bool NeedsCompiling() {
// return true as soon as we know we need to compile
bool needs = false;
if (!Compile)
{
FileInfo outputFileInfo = new
FileInfo(GetOutputPath());
if (!outputFileInfo.Exists)
{
needs = true;
}
FileInfo inputFileInfo = new FileInfo(GetInputPath());
if (!inputFileInfo.Exists)
{
needs = true;
}
if (outputFileInfo.LastWriteTime <
inputFileInfo.LastWriteTime)
{
needs = true;
}
}
else
{
FileInfo outputFileInfo;
FileInfo inputFileInfo;
StringBuilder outsb;
needs = false;
foreach (string fileName in Resources.FileNames)
{
outsb = new StringBuilder();
outsb = new StringBuilder();
int dirpos = fileName.LastIndexOf(@"\");
if (dirpos == -1){dirpos =
fileName.LastIndexOf(@"/");}
string newname = fileName.Substring(dirpos +
1);
outsb.Append(fileName.Substring(0,dirpos + 1));
//outsb.Append(@"/");
if (_prepend != null) {
outsb.Append(_prepend); }
int posresx = newname.IndexOf(".resx");
if (posresx == -1) {posresx =
newname.IndexOf(".txt");}
if (posresx != -1)
{
outsb.Append(newname.Substring(0,
posresx));
}
else
{
outsb.Append(newname);
}
outsb.Append(@".resources");
//System.Console.WriteLine(outsb.ToString());
outputFileInfo = new
FileInfo(outsb.ToString());
inputFileInfo = new FileInfo(fileName);
if (!outputFileInfo.Exists)
{
needs = true;
}
if (!inputFileInfo.Exists)
{
needs = true;
}
if (outputFileInfo.LastWriteTime <
inputFileInfo.LastWriteTime)
{
needs = true;
}
}
}
return needs;
}
protected override void ExecuteTask() {
if (NeedsCompiling()) {
// create temp response file to hold compiler options
StringBuilder sb = new StringBuilder ();
StringWriter writer = new StringWriter ( sb );
string quote = "\"";
try {
//Log.WriteLine(LogPrefix + "Compiling {0} to {1}",
GetInputPath(), GetOutputPath());
// specific compiler options
WriteOptions(writer);
// Microsoft common compiler options
if (!Compile) {
writer.Write(" \"{0}\"", Input );
writer.Write(" \"{0}\"", Output );
// Make sure to close the response
file otherwise contents
// will not be written to disc and
EXecuteTask() will fail.
writer.Close();
_arguments = sb.ToString ();
// display response file contents
Log.WriteLineIf(Verbose, _arguments);
// call base class to do the work
base.ExecuteTask();
} else {
StringBuilder outsb;
//bool addComma = false;
//writer.Write(" /compile" );
foreach (string fileName in
Resources.FileNames)
{
outsb = new StringBuilder();
sb = new StringBuilder ();
writer = new StringWriter ( sb
);
//outsb.Append(quote);
int dirpos =
fileName.LastIndexOf(@"\");
if (dirpos == -1){dirpos =
fileName.LastIndexOf(@"/");}
string newname =
fileName.Substring(dirpos + 1);
outsb.Append(fileName.Substring(0,dirpos + 1));
//outsb.Append(@"/");
if (_prepend != null) {
outsb.Append(_prepend); }
int posresx =
newname.IndexOf(".resx");
if (posresx == -1) {posresx =
newname.IndexOf(".txt");}
if (posresx != -1)
{
outsb.Append(newname.Substring(0, posresx));
}
else
{
outsb.Append(newname);
}
outsb.Append(@".resources");
//outsb.Append(quote);
//
System.Console.WriteLine(outsb.ToString());
writer.Write(" \"{0}\"",
fileName );
writer.Write(" \"{0}\"",
outsb.ToString() );
// Make sure to close the
response file otherwise contents
// will not be written to disc
and EXecuteTask() will fail.
writer.Close();
_arguments = sb.ToString ();
// display response file
contents
Log.WriteLineIf(Verbose,
_arguments);
System.Console.WriteLine(_arguments);
// call base class to do the
work
base.ExecuteTask();
}
}
} finally {
// make sure we delete response file even if an exception is thrown
writer.Close(); // make sure stream is closed or file cannot be
deleted
}
}
}
}
}