in src/Utilities/ToolTask.cs [1460:1715]
public override bool Execute()
{
// Let the tool validate its parameters. ToolTask is responsible for logging
// useful information about what was wrong with the parameters.
if (!ValidateParameters())
{
return false;
}
if (EnvironmentVariables != null)
{
_environmentVariablePairs = new List<KeyValuePair<object, object>>(EnvironmentVariables.Length);
foreach (string entry in EnvironmentVariables)
{
string[] nameValuePair = entry.Split(s_equalsSplitter, 2);
if (nameValuePair.Length == 1 || (nameValuePair.Length == 2 && nameValuePair[0].Length == 0))
{
LogPrivate.LogErrorWithCodeFromResources("ToolTask.InvalidEnvironmentParameter", nameValuePair[0]);
return false;
}
_environmentVariablePairs.Add(new KeyValuePair<object, object>((object)nameValuePair[0], (object)nameValuePair[1]));
}
}
// Assign standard stream logging importances
if (!AssignStandardStreamLoggingImportance())
{
return false;
}
try
{
if (SkipTaskExecution())
{
// the task has said there's no command-line that we need to run, so
// return true to indicate this task completed successfully (without
// doing any actual work).
return true;
}
string commandLineCommands = GenerateCommandLineCommands();
// If there are response file commands, then we need a response file later.
string batchFileContents = commandLineCommands;
string responseFileCommands = GenerateResponseFileCommands();
bool runningOnWindows = NativeMethodsShared.IsWindows;
if (UseCommandProcessor)
{
if (runningOnWindows) // we are Windows
{
ToolExe = "cmd.exe";
// Generate the temporary batch file
// May throw IO-related exceptions
_temporaryBatchFile = FileUtilities.GetTemporaryFile(".cmd");
}
else
{
ToolExe = "/bin/sh";
// Generate the temporary batch file
// May throw IO-related exceptions
_temporaryBatchFile = FileUtilities.GetTemporaryFile(".sh");
}
if (!runningOnWindows)
{
// Use sh rather than bash, as not all 'nix systems necessarily have Bash installed
File.AppendAllText(_temporaryBatchFile, "#!/bin/sh\n"); // first line for UNIX is ANSI
// This is a hack..!
File.AppendAllText(_temporaryBatchFile, commandLineCommands.Replace('\\', Path.DirectorySeparatorChar), EncodingUtilities.CurrentSystemOemEncoding);
}
else
{
File.AppendAllText(_temporaryBatchFile, commandLineCommands, EncodingUtilities.CurrentSystemOemEncoding);
string batchFileForCommandLine = _temporaryBatchFile;
// If for some crazy reason the path has a & character and a space in it
// then get the short path of the temp path, which should not have spaces in it
// and then escape the &
if (batchFileForCommandLine.Contains("&") && !batchFileForCommandLine.Contains("^&"))
{
batchFileForCommandLine = NativeMethodsShared.GetShortFilePath(batchFileForCommandLine);
batchFileForCommandLine = batchFileForCommandLine.Replace("&", "^&");
}
commandLineCommands = "/C \"" + batchFileForCommandLine + "\"";
if (EchoOff)
{
commandLineCommands = "/Q " + commandLineCommands;
}
}
}
// ensure the command line arguments string is not null
if ((commandLineCommands == null) || (commandLineCommands.Length == 0))
{
commandLineCommands = String.Empty;
}
// add a leading space to the command line arguments (if any) to
// separate them from the tool path
else
{
commandLineCommands = " " + commandLineCommands;
}
// Initialize the host object. At this point, the task may elect
// to not proceed. Compiler tasks do this for purposes of up-to-date
// checking in the IDE.
HostObjectInitializationStatus nextAction = InitializeHostObject();
if (nextAction == HostObjectInitializationStatus.NoActionReturnSuccess)
{
return true;
}
else if (nextAction == HostObjectInitializationStatus.NoActionReturnFailure)
{
_exitCode = 1;
return HandleTaskExecutionErrors();
}
string pathToTool = ComputePathToTool();
if (pathToTool == null)
{
// An appropriate error should have been logged already.
return false;
}
// Log the environment. We do this up here,
// rather than later where the environment is set,
// so that it appears before the command line is logged.
bool alreadyLoggedEnvironmentHeader = false;
// Old style environment overrides
#pragma warning disable 0618 // obsolete
Dictionary<string, string> envOverrides = EnvironmentOverride;
if (null != envOverrides)
{
foreach (KeyValuePair<string, string> entry in envOverrides)
{
alreadyLoggedEnvironmentHeader = LogEnvironmentVariable(alreadyLoggedEnvironmentHeader, entry.Key, entry.Value);
}
#pragma warning restore 0618
}
// New style environment overrides
if (_environmentVariablePairs != null)
{
foreach (KeyValuePair<object, object> variable in _environmentVariablePairs)
{
alreadyLoggedEnvironmentHeader = LogEnvironmentVariable(alreadyLoggedEnvironmentHeader, (string)variable.Key, (string)variable.Value);
}
}
if (!runningOnWindows)
{
commandLineCommands = commandLineCommands.Replace('\\', Path.DirectorySeparatorChar);
responseFileCommands = responseFileCommands.Replace('\\', Path.DirectorySeparatorChar);
}
if (UseCommandProcessor)
{
// Log that we are about to invoke the specified command.
LogToolCommand(pathToTool + commandLineCommands);
LogToolCommand(batchFileContents);
}
else
{
// Log that we are about to invoke the specified command.
LogToolCommand(pathToTool + commandLineCommands + " " + responseFileCommands);
}
_exitCode = 0;
if (nextAction == HostObjectInitializationStatus.UseHostObjectToExecute)
{
// The hosting IDE passed in a host object to this task. Give the task
// a chance to call this host object to do the actual work.
try
{
if (!CallHostObjectToExecute())
{
_exitCode = 1;
}
}
catch (Exception e)
{
LogPrivate.LogErrorFromException(e);
return false;
}
}
else
{
ErrorUtilities.VerifyThrow(nextAction == HostObjectInitializationStatus.UseAlternateToolToExecute,
"Invalid return status");
// No host object was provided, or at least not one that supports all of the
// switches/parameters we need. So shell out to the command-line tool.
_exitCode = ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
// Raise a comment event to notify that the process completed
if (_terminatedTool)
{
return false;
}
else if (_exitCode != 0)
{
return HandleTaskExecutionErrors();
}
else
{
return true;
}
}
catch (ArgumentException e)
{
if (!_terminatedTool)
{
LogPrivate.LogErrorWithCodeFromResources("General.InvalidToolSwitch", ToolExe, GetErrorMessageWithDiagnosticsCheck(e));
}
return false;
}
catch (Win32Exception e)
{
if (!_terminatedTool)
{
LogPrivate.LogErrorWithCodeFromResources("ToolTask.CouldNotStartToolExecutable", ToolExe, GetErrorMessageWithDiagnosticsCheck(e));
}
return false;
}
catch (IOException e)
{
if (!_terminatedTool)
{
LogPrivate.LogErrorWithCodeFromResources("ToolTask.CouldNotStartToolExecutable", ToolExe, GetErrorMessageWithDiagnosticsCheck(e));
}
return false;
}
catch (UnauthorizedAccessException e)
{
if (!_terminatedTool)
{
LogPrivate.LogErrorWithCodeFromResources("ToolTask.CouldNotStartToolExecutable", ToolExe, GetErrorMessageWithDiagnosticsCheck(e));
}
return false;
}
finally
{
// Clean up after ourselves.
if (_temporaryBatchFile != null && File.Exists(_temporaryBatchFile))
{
DeleteTempFile(_temporaryBatchFile);
}
}
} // Execute()