in src/Build/Instance/TaskRegistry.cs [1228:1424]
private bool GetTaskFactory(TargetLoggingContext targetLoggingContext, ElementLocation elementLocation, string taskProjectFile)
{
// see if we have already created the factory before, only create it once
if (_taskFactoryWrapperInstance == null)
{
AssemblyLoadInfo taskFactoryLoadInfo = TaskFactoryAssemblyLoadInfo;
ErrorUtilities.VerifyThrow(taskFactoryLoadInfo != null, "TaskFactoryLoadInfo should never be null");
ITaskFactory factory = null;
LoadedType loadedType = null;
bool isAssemblyTaskFactory = String.Equals(TaskFactoryAttributeName, AssemblyTaskFactory, StringComparison.OrdinalIgnoreCase);
bool isTaskHostFactory = String.Equals(TaskFactoryAttributeName, TaskHostFactory, StringComparison.OrdinalIgnoreCase);
if (isAssemblyTaskFactory || isTaskHostFactory)
{
bool explicitlyLaunchTaskHost =
isTaskHostFactory ||
(
s_forceTaskHostLaunch &&
!TypeLoader.IsPartialTypeNameMatch(RegisteredName, "MSBuild") &&
!TypeLoader.IsPartialTypeNameMatch(RegisteredName, "CallTarget")
);
// Create an instance of the internal assembly task factory, it has the error handling built into its methods.
AssemblyTaskFactory taskFactory = new AssemblyTaskFactory();
loadedType = taskFactory.InitializeFactory(taskFactoryLoadInfo, RegisteredName, ParameterGroupAndTaskBody.UsingTaskParameters, ParameterGroupAndTaskBody.InlineTaskXmlBody, TaskFactoryParameters, explicitlyLaunchTaskHost, targetLoggingContext, elementLocation, taskProjectFile);
factory = taskFactory;
}
else
{
// We are not one of the default factories.
TaskEngineAssemblyResolver resolver = null;
try
{
// Add a resolver to allow us to resolve types from the assembly when loading into the current appdomain.
resolver = new TaskEngineAssemblyResolver();
resolver.Initialize(taskFactoryLoadInfo.AssemblyFile);
resolver.InstallHandler();
try
{
lock (s_taskFactoryTypeLoaderLock)
{
if (s_taskFactoryTypeLoader == null)
{
s_taskFactoryTypeLoader = new TypeLoader(s_taskFactoryTypeFilter);
}
}
// Make sure we only look for task factory classes when loading based on the name
loadedType = s_taskFactoryTypeLoader.Load(TaskFactoryAttributeName, taskFactoryLoadInfo);
if (loadedType == null)
{
// We could not find the type (this is what null means from the Load method) but there is no reason given so we can only log the fact that
// we could not find the name given in the task factory attribute in the class specified in the assembly File or assemblyName fields.
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "CouldNotFindFactory", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation);
}
targetLoggingContext.LogComment(MessageImportance.Low, "InitializingTaskFactory", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation);
}
catch (TargetInvocationException e)
{
// Exception thrown by the called code itself
// Log the stack, so the task vendor can fix their code
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "TaskFactoryLoadFailure", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation, Environment.NewLine + e.InnerException.ToString());
}
catch (ReflectionTypeLoadException e)
{
// ReflectionTypeLoadException.LoaderExceptions may contain nulls
foreach (Exception exception in e.LoaderExceptions)
{
if (exception != null)
{
targetLoggingContext.LogError(new BuildEventFileInfo(taskProjectFile), "TaskFactoryLoadFailure", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation, exception.Message);
}
}
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "TaskFactoryLoadFailure", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation, e.Message);
}
catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception.
{
if (ExceptionHandling.NotExpectedReflectionException(e))
{
throw;
}
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "TaskFactoryLoadFailure", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation, e.Message);
}
try
{
// We have loaded the type, lets now try and construct it
// Any exceptions from the constructor of the task factory will be caught lower down and turned into an InvalidProjectFileExceptions
#if FEATURE_APPDOMAIN
factory = (ITaskFactory)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(loadedType.Type.GetTypeInfo().Assembly.FullName, loadedType.Type.FullName);
#else
factory = (ITaskFactory) Activator.CreateInstance(loadedType.Type);
#endif
TaskFactoryLoggingHost taskFactoryLoggingHost = new TaskFactoryLoggingHost(true /*I dont have the data at this point, the safest thing to do is make sure events are serializable*/, elementLocation, targetLoggingContext);
bool initialized = false;
try
{
ITaskFactory2 factory2 = factory as ITaskFactory2;
if (factory2 != null)
{
initialized = factory2.Initialize(RegisteredName, TaskFactoryParameters, ParameterGroupAndTaskBody.UsingTaskParameters, ParameterGroupAndTaskBody.InlineTaskXmlBody, taskFactoryLoggingHost);
}
else
{
initialized = factory.Initialize(RegisteredName, ParameterGroupAndTaskBody.UsingTaskParameters, ParameterGroupAndTaskBody.InlineTaskXmlBody, taskFactoryLoggingHost);
// TaskFactoryParameters will always be null unless specifically created to have runtime and architecture parameters.
if (TaskFactoryParameters != null)
{
targetLoggingContext.LogWarning
(
new BuildEventFileInfo(elementLocation),
null,
"TaskFactoryWillIgnoreTaskFactoryParameters",
factory.FactoryName,
XMakeAttributes.runtime,
XMakeAttributes.architecture,
RegisteredName
);
}
}
}
finally
{
#if FEATURE_APPDOMAIN
taskFactoryLoggingHost.MarkAsInactive();
#endif
}
if (!initialized)
{
_taskFactoryWrapperInstance = null;
return false;
}
}
catch (InvalidCastException e)
{
string message = String.Empty;
#if DEBUG
message += UnhandledFactoryError;
#endif
message += e.Message;
// Could get an invalid cast when Creating Instance and UnWrap due to the framework assembly not being the same.
targetLoggingContext.LogError
(
new BuildEventFileInfo(elementLocation.File, elementLocation.Line, elementLocation.Column),
"TaskFactoryInstantiationFailureErrorInvalidCast",
TaskFactoryAttributeName,
taskFactoryLoadInfo.AssemblyLocation,
message
);
return false;
}
catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception.
{
if (ExceptionHandling.IsCriticalException(e))
{
throw;
}
string message = String.Empty;
#if DEBUG
message += UnhandledFactoryError;
#endif
// message += e.ToString();
message += e.Message;
ProjectErrorUtilities.ThrowInvalidProject(elementLocation, "TaskFactoryLoadFailure", TaskFactoryAttributeName, taskFactoryLoadInfo.AssemblyLocation, message);
}
}
finally
{
if (resolver != null)
{
resolver.RemoveHandler();
resolver = null;
}
}
}
_taskFactoryWrapperInstance = new TaskFactoryWrapper(factory, loadedType, RegisteredName, TaskFactoryParameters);
}
return true;
}