// NAnt - A .NET build tool
// Copyright (C) 2003 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
//
// Gerry Shaw (gerry_shaw@yahoo.com)
using System;
using System.Globalization;
using System.IO;
using System.Xml;
using NAnt.Core.Attributes;
using NAnt.Core.Types;
using NAnt.Core.Util;
namespace NAnt.Core.Tasks {
///
/// Executes a system command.
///
///
/// Ping "nant.sourceforge.net".
///
///
///
///
/// ]]>
///
///
///
///
/// Execute a java application using IKVM.NET that requires the
/// Apache FOP jars, and a set of custom jars.
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
/// Assuming the base directory of the build file is "c:\ikvm-test" and
/// the value of the "fop.dist.dir" property is "c:\fop", then the value
/// of the -cp argument that is passed toikvm.exe is
/// "c:\ikvm-test\conf;c:\fop\build\fop.jar;conf;c:\fop\lib\xercesImpl-2.2.1.jar;c:\fop\lib\avalon-framework-cvs-20020806.jar;c:\fop\lib\batik.jar;c:\ikvm-test\lib\mylib.jar;c:\ikvm-test\lib\otherlib.zip"
/// on a DOS-based system.
///
///
[TaskName("exec")]
public class ExecTask : ExternalProgramBase {
#region Private Instance Fields
private string _program;
private string _commandline;
private DirectoryInfo _baseDirectory;
private DirectoryInfo _workingDirectory;
private FileInfo _output;
private bool _outputAppend;
private EnvironmentSet _environmentSet = new EnvironmentSet();
private bool _useRuntimeEngine;
private string _resultProperty;
#endregion Private Instance Fields
#region Public Instance Properties
///
/// The program to execute without command arguments.
///
///
/// The path will not be evaluated to a full path using the project
/// base directory.
///
[TaskAttribute("program", Required=true)]
[StringValidator(AllowEmpty=false)]
public string FileName {
get { return _program; }
set { _program = StringUtils.ConvertEmptyToNull(value); }
}
///
/// The command-line arguments for the program.
///
[TaskAttribute("commandline")]
public string CommandLineArguments {
get { return _commandline; }
set { _commandline = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Environment variables to pass to the program.
///
[BuildElement("environment")]
public EnvironmentSet EnvironmentSet {
get { return _environmentSet; }
}
///
/// The directory in which the command will be executed.
///
///
/// The directory in which the command will be executed. The default
/// is the project's base directory.
///
///
///
/// The working directory will be evaluated relative to the project's
/// base directory if it is relative.
///
///
[TaskAttribute("workingdir")]
public DirectoryInfo WorkingDirectory {
get {
if (_workingDirectory == null) {
return base.BaseDirectory;
}
return _workingDirectory;
}
set { _workingDirectory = value; }
}
///
///
/// The name of a property in which the exit code of the program should
/// be stored. Only of interest if is
/// .
///
///
/// If the exit code of the program is "-1000" then the program could
/// not be started, or did not exit (in time).
///
///
[TaskAttribute("resultproperty")]
[StringValidator(AllowEmpty=false)]
public string ResultProperty {
get { return _resultProperty; }
set { _resultProperty = value; }
}
#endregion Public Instance Properties
#region Override implementation of ExternalProgramBase
///
/// Specifies whether the external program should be executed using a
/// runtime engine, if configured. The default is .
///
///
/// if the external program should be executed
/// using a runtime engine; otherwise, .
///
[TaskAttribute("useruntimeengine")]
[FrameworkConfigurable("useruntimeengine")]
public override bool UseRuntimeEngine {
get { return _useRuntimeEngine; }
set { _useRuntimeEngine = value; }
}
///
/// Gets the filename of the external program to start.
///
///
/// The filename of the external program.
///
public override string ProgramFileName {
get {
if (Path.IsPathRooted(FileName)) {
return FileName;
} else if (_baseDirectory == null) {
// resolve program to full path relative to project directory
string fullPath = Project.GetFullPath(FileName);
// check if the program exists in that location
if (File.Exists(fullPath)) {
// return full path to program (which we know exists)
return fullPath;
}
return FileName;
} else {
return Path.GetFullPath(Path.Combine(BaseDirectory.FullName,
FileName));
}
}
}
///
/// Performs additional checks after the task has been initialized.
///
/// The used to initialize the task.
/// does not hold a valid file name.
protected override void InitializeTask(XmlNode taskNode) {
try {
// just check if program file to execute is a valid file name
if (Path.IsPathRooted(FileName)) {
// do nothing
}
} catch (Exception ex) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1117"),
FileName, Name), Location, ex);
}
base.InitializeTask(taskNode);
}
///
/// Gets the command-line arguments for the external program.
///
///
/// The command-line arguments for the external program.
///
public override string ProgramArguments {
get { return _commandline; }
}
///
/// The directory the program is in.
///
///
///
/// The directory the program is in. The default is the project's base
/// directory.
///
///
/// The basedir will be evaluated relative to the project's base
/// directory if it is relative.
///
///
[TaskAttribute("basedir")]
public override DirectoryInfo BaseDirectory {
get {
if (_baseDirectory == null) {
return base.BaseDirectory;
}
return _baseDirectory;
}
set { _baseDirectory = value; }
}
///
/// The file to which the standard output will be redirected.
///
///
/// By default, the standard output is redirected to the console.
///
[TaskAttribute("output", Required=false)]
public override FileInfo Output {
get { return _output; }
set { _output = value; }
}
///
/// Gets or sets a value indicating whether output should be appended
/// to the output file. The default is .
///
///
/// if output should be appended to the ;
/// otherwise, .
///
[TaskAttribute("append", Required=false)]
public override bool OutputAppend {
get { return _outputAppend; }
set { _outputAppend = value; }
}
///
/// Executes the external program.
///
protected override void ExecuteTask() {
base.ExecuteTask();
if (ResultProperty != null) {
Properties[ResultProperty] = base.ExitCode.ToString(
CultureInfo.InvariantCulture);
}
}
protected override void PrepareProcess(System.Diagnostics.Process process) {
base.PrepareProcess(process);
// set working directory specified by user
process.StartInfo.WorkingDirectory = WorkingDirectory.FullName;
// set environment variables
foreach (Option option in EnvironmentSet.Options) {
if (option.IfDefined && !option.UnlessDefined) {
if (option.Value == null) {
process.StartInfo.EnvironmentVariables[option.OptionName] = "";
} else {
process.StartInfo.EnvironmentVariables[option.OptionName] = option.Value;
}
}
}
foreach (EnvironmentVariable variable in EnvironmentSet.EnvironmentVariables) {
if (variable.IfDefined && !variable.UnlessDefined) {
if (variable.Value == null) {
process.StartInfo.EnvironmentVariables[variable.VariableName] = "";
} else {
process.StartInfo.EnvironmentVariables[variable.VariableName] = variable.Value;
}
}
}
}
#endregion Override implementation of ExternalProgramBase
}
}