// 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 } }