public void ConflictWithBackVersionPrimaryWithAutoUnify() { ResolveAssemblyReference t = new ResolveAssemblyReference(); MockEngine e = new MockEngine(_output); t.BuildEngine = e; t.Assemblies = new ITaskItem[] { new TaskItem("B"), new TaskItem("A"), new TaskItem("D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa") }; t.AutoUnify = true; t.SearchPaths = new string[] { s_myLibrariesRootPath, s_myLibraries_V2Path, s_myLibraries_V1Path }; t.TargetFrameworkDirectories = new string[] { s_myVersion20Path }; bool result = Execute(t); Assert.Equal(1, e.Warnings); // @"Expected one warning." // Check that we have a message identifying conflicts with "D" string warningMessage = e.WarningEvents[0].Message; warningMessage.ShouldContain(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("ResolveAssemblyReference.FoundConflicts", "D", string.Empty)); warningMessage.ShouldContain(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ResolveAssemblyReference.ConflictFound", "D, Version=1.0.0.0, CulTUre=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa", "D, Version=2.0.0.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa")); warningMessage.ShouldContain(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ResolveAssemblyReference.FourSpaceIndent", ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ResolveAssemblyReference.ReferenceDependsOn", "D, Version=1.0.0.0, CulTUre=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa", Path.Combine(s_myLibraries_V1Path, "D.dll")))); Assert.Empty(t.SuggestedRedirects); Assert.Equal(3, t.ResolvedFiles.Length); Assert.True(ContainsItem(t.ResolvedFiles, s_myLibraries_V1_DDllPath)); // "Expected to find assembly, but didn't." }
private void VerifyImplementationArchitecture(string winmdName, string targetProcessorArchitecture, string implementationFileArch, string warnOrErrorOnTargetArchitectureMismatch) { // Create the engine. MockEngine engine = new MockEngine(); TaskItem item = new TaskItem(winmdName); ITaskItem[] assemblyFiles = new TaskItem[] { item }; ResolveAssemblyReference t = new ResolveAssemblyReference(); t.BuildEngine = engine; t.Assemblies = assemblyFiles; t.SearchPaths = new String[] { @"C:\WinMDArchVerification" }; t.TargetProcessorArchitecture = targetProcessorArchitecture; t.WarnOrErrorOnTargetArchitectureMismatch = warnOrErrorOnTargetArchitectureMismatch; bool succeeded = Execute(t); Assert.Equal(1, t.ResolvedFiles.Length); Assert.True(t.ResolvedFiles[0].ItemSpec.Equals(@"C:\WinMDArchVerification\" + winmdName + ".winmd", StringComparison.OrdinalIgnoreCase)); Assert.True(t.ResolvedFiles[0].GetMetadata(ItemMetadataNames.imageRuntime).Equals(@"WindowsRuntime 1.0", StringComparison.OrdinalIgnoreCase)); Assert.True(bool.Parse(t.ResolvedFiles[0].GetMetadata(ItemMetadataNames.winMDFile))); string fullMessage = null; if (implementationFileArch.Equals("Unknown")) { fullMessage = ResourceUtilities.FormatResourceString("ResolveAssemblyReference.UnknownProcessorArchitecture", @"C:\WinMDArchVerification\" + winmdName + ".dll", @"C:\WinMDArchVerification\" + winmdName + ".winmd", NativeMethods.IMAGE_FILE_MACHINE_R4000.ToString("X", CultureInfo.InvariantCulture)); } else { fullMessage = ResourceUtilities.FormatResourceString("ResolveAssemblyReference.MismatchBetweenTargetedAndReferencedArchOfImplementation", targetProcessorArchitecture, implementationFileArch, @"C:\WinMDArchVerification\" + winmdName + ".dll", @"C:\WinMDArchVerification\" + winmdName + ".winmd"); } if (warnOrErrorOnTargetArchitectureMismatch.Equals("None", StringComparison.OrdinalIgnoreCase)) { engine.AssertLogDoesntContain(fullMessage); } else { engine.AssertLogContains(fullMessage); } if (warnOrErrorOnTargetArchitectureMismatch.Equals("Warning", StringComparison.OrdinalIgnoreCase)) { // Should fail since PE Header is not valid and this is always an error. Assert.True(succeeded); Assert.True(t.ResolvedFiles[0].GetMetadata(ItemMetadataNames.winmdImplmentationFile).Equals(winmdName + ".dll")); Assert.Equal(0, engine.Errors); Assert.Equal(1, engine.Warnings); } else if (warnOrErrorOnTargetArchitectureMismatch.Equals("Error", StringComparison.OrdinalIgnoreCase)) { // Should fail since PE Header is not valid and this is always an error. Assert.False(succeeded); Assert.Equal(0, t.ResolvedFiles[0].GetMetadata(ItemMetadataNames.winmdImplmentationFile).Length); Assert.Equal(1, engine.Errors); Assert.Equal(0, engine.Warnings); } else if (warnOrErrorOnTargetArchitectureMismatch.Equals("None", StringComparison.OrdinalIgnoreCase)) { Assert.True(succeeded); Assert.True(t.ResolvedFiles[0].GetMetadata(ItemMetadataNames.winmdImplmentationFile).Equals(winmdName + ".dll")); Assert.Equal(0, engine.Errors); Assert.Equal(0, engine.Warnings); } }
/// <summary> /// This function will start a node and send requests to it /// </summary> private void LaunchNodeAndPostBuildRequest() { int nodeIndex = 0; // Find out what node to launch lock (nodesToLaunch) { nodeIndex = nodesToLaunch.Dequeue(); } // If the provider is shutting down - don't launch the node if (shuttingDown) { nodeData[nodeIndex].NodeState = NodeState.NotLaunched; return; } try { // Either launch node or connect to an already running node InitializeNode(nodeIndex); if (!nodeData[nodeIndex].CommunicationFailed) { // Change the state of the node to launched lock (nodeStateLock) { nodeData[nodeIndex].NodeState = NodeState.Launched; } // Send all the requests to the node. Note that the requests may end up in // mixed order with the request currently being posted. LinkedListNode <BuildRequest> current = nodeData[nodeIndex].TargetList.First; BuildRequest[] buildRequests = new BuildRequest[nodeData[nodeIndex].TargetList.Count]; int i = 0; while (current != null) { buildRequests[i] = current.Value; i++; current = current.Next; } LocalCallDescriptorForPostBuildRequests callDescriptor = new LocalCallDescriptorForPostBuildRequests(buildRequests); nodeData[nodeIndex].NodeCommandQueue.Enqueue(callDescriptor); nodeData[nodeIndex].TargetList = null; } else { // Allow the engine to decide how to proceed since the node failed to launch string message = ResourceUtilities.FormatResourceString("NodeProviderFailure"); ReportNodeCommunicationFailure(nodeIndex, new Exception(message), false); } } catch (Exception e) { // Allow the engine to deal with the exception ReportNodeCommunicationFailure(nodeIndex, e, false); } }
/// <summary> /// Finds or creates a child process which can act as a node. /// </summary> /// <returns>The pipe stream representing the node.</returns> protected NodeContext GetNode(string msbuildLocation, string commandLineArgs, int nodeId, INodePacketFactory factory, Handshake hostHandshake, NodeContextTerminateDelegate terminateNode) { #if DEBUG if (Execution.BuildManager.WaitForDebugger) { commandLineArgs += " /wfd"; } #endif if (String.IsNullOrEmpty(msbuildLocation)) { msbuildLocation = _componentHost.BuildParameters.NodeExeLocation; } if (String.IsNullOrEmpty(msbuildLocation)) { string msbuildExeName = Environment.GetEnvironmentVariable("MSBUILD_EXE_NAME"); if (!String.IsNullOrEmpty(msbuildExeName)) { // we assume that MSBUILD_EXE_NAME is, in fact, just the name. msbuildLocation = Path.Combine(msbuildExeName, ".exe"); } } #if FEATURE_NODE_REUSE // Try to connect to idle nodes if node reuse is enabled. if (_componentHost.BuildParameters.EnableNodeReuse) { (string expectedProcessName, List <Process> processes)runningNodesTuple = GetPossibleRunningNodes(msbuildLocation); CommunicationsUtilities.Trace("Attempting to connect to each existing {1} process in turn to establish node {0}...", nodeId, runningNodesTuple.expectedProcessName); foreach (Process nodeProcess in runningNodesTuple.processes) { if (nodeProcess.Id == Process.GetCurrentProcess().Id) { continue; } // Get the full context of this inspection so that we can always skip this process when we have the same taskhost context string nodeLookupKey = GetProcessesToIgnoreKey(hostHandshake, nodeProcess.Id); if (_processesToIgnore.Contains(nodeLookupKey)) { continue; } // We don't need to check this again _processesToIgnore.Add(nodeLookupKey); // Attempt to connect to each process in turn. Stream nodeStream = TryConnectToProcess(nodeProcess.Id, 0 /* poll, don't wait for connections */, hostHandshake); if (nodeStream != null) { // Connection successful, use this node. CommunicationsUtilities.Trace("Successfully connected to existed node {0} which is PID {1}", nodeId, nodeProcess.Id); return(new NodeContext(nodeId, nodeProcess, nodeStream, factory, terminateNode)); } } } #endif // None of the processes we tried to connect to allowed a connection, so create a new one. // We try this in a loop because it is possible that there is another MSBuild multiproc // host process running somewhere which is also trying to create nodes right now. It might // find our newly created node and connect to it before we get a chance. CommunicationsUtilities.Trace("Could not connect to existing process, now creating a process..."); int retries = NodeCreationRetries; while (retries-- > 0) { #if FEATURE_NET35_TASKHOST // We will also check to see if .NET 3.5 is installed in the case where we need to launch a CLR2 OOP TaskHost. // Failure to detect this has been known to stall builds when Windows pops up a related dialog. // It's also a waste of time when we attempt several times to launch multiple MSBuildTaskHost.exe (CLR2 TaskHost) // nodes because we should never be able to connect in this case. string taskHostNameForClr2TaskHost = Path.GetFileNameWithoutExtension(NodeProviderOutOfProcTaskHost.TaskHostNameForClr2TaskHost); if (Path.GetFileNameWithoutExtension(msbuildLocation).Equals(taskHostNameForClr2TaskHost, StringComparison.OrdinalIgnoreCase)) { if (FrameworkLocationHelper.GetPathToDotNetFrameworkV35(DotNetFrameworkArchitecture.Current) == null) { CommunicationsUtilities.Trace ( "Failed to launch node from {0}. The required .NET Framework v3.5 is not installed or enabled. CommandLine: {1}", msbuildLocation, commandLineArgs ); string nodeFailedToLaunchError = ResourceUtilities.GetResourceString("TaskHostNodeFailedToLaunchErrorCodeNet35NotInstalled"); throw new NodeFailedToLaunchException(null, nodeFailedToLaunchError); } } #endif // Create the node process Process msbuildProcess = LaunchNode(msbuildLocation, commandLineArgs); _processesToIgnore.Add(GetProcessesToIgnoreKey(hostHandshake, msbuildProcess.Id)); // Note, when running under IMAGEFILEEXECUTIONOPTIONS registry key to debug, the process ID // gotten back from CreateProcess is that of the debugger, which causes this to try to connect // to the debugger process. Instead, use MSBUILDDEBUGONSTART=1 // Now try to connect to it. Stream nodeStream = TryConnectToProcess(msbuildProcess.Id, TimeoutForNewNodeCreation, hostHandshake); if (nodeStream != null) { // Connection successful, use this node. CommunicationsUtilities.Trace("Successfully connected to created node {0} which is PID {1}", nodeId, msbuildProcess.Id); return(new NodeContext(nodeId, msbuildProcess, nodeStream, factory, terminateNode)); } } // We were unable to launch a node. CommunicationsUtilities.Trace("FAILED TO CONNECT TO A CHILD NODE"); return(null); }
/// <summary> /// Load a graph with root node at entryProjectFile /// Maintain a queue of projects to be processed and evaluate projects in parallel /// Returns false if loading the graph is not successful /// </summary> private bool LoadGraph( ConcurrentQueue <ConfigurationMetadata> projectsToEvaluate, ProjectCollection projectCollection, ConcurrentDictionary <ConfigurationMetadata, object> tasksInProgress, ProjectInstanceFactoryFunc projectInstanceFactory, out List <Exception> exceptions) { var exceptionsInTasks = new ConcurrentBag <Exception>(); var evaluationWaitHandle = new AutoResetEvent(false); while (projectsToEvaluate.Count != 0 || tasksInProgress.Count != 0) { ConfigurationMetadata projectToEvaluate; if (projectsToEvaluate.Count != 0) { projectToEvaluate = projectsToEvaluate.Dequeue(); var task = new Task(() => { ProjectGraphNode parsedProject = CreateNewNode(projectToEvaluate, projectCollection, projectInstanceFactory); IEnumerable <ProjectItemInstance> projectReferenceItems = parsedProject.ProjectInstance.GetItems(MSBuildConstants.ProjectReferenceItemName); foreach (var projectReferenceToParse in projectReferenceItems) { if (!string.IsNullOrEmpty(projectReferenceToParse.GetMetadataValue(ToolsVersionMetadataName))) { throw new InvalidOperationException(string.Format( CultureInfo.InvariantCulture, ResourceUtilities.GetResourceString( "ProjectGraphDoesNotSupportProjectReferenceWithToolset"), projectReferenceToParse.EvaluatedInclude, parsedProject.ProjectInstance.FullPath)); } string projectReferenceFullPath = projectReferenceToParse.GetMetadataValue(FullPathMetadataName); PropertyDictionary <ProjectPropertyInstance> projectReferenceGlobalProperties = GetProjectReferenceGlobalProperties(projectReferenceToParse, projectToEvaluate.GlobalProperties); var projectReferenceConfigurationMetadata = new ConfigurationMetadata(projectReferenceFullPath, projectReferenceGlobalProperties); if (!tasksInProgress.ContainsKey(projectReferenceConfigurationMetadata)) { if (!_allParsedProjects.ContainsKey(projectReferenceConfigurationMetadata)) { projectsToEvaluate.Enqueue(projectReferenceConfigurationMetadata); evaluationWaitHandle.Set(); } } } }); if (tasksInProgress.TryAdd(projectToEvaluate, null)) { // once the task completes, remove it from tasksInProgress using a chained task // signal the wait handle to process new projects that have been discovered by this task or exit if all projects have been evaluated task.ContinueWith(_ => { if (task.IsFaulted) { exceptionsInTasks.Add(task.Exception.InnerException); } tasksInProgress.TryRemove(projectToEvaluate, out var _); evaluationWaitHandle.Set(); }); task.Start(); } } else { // if projectsToEvaluate is empty but there are tasks in progress, there is nothing to do till a task completes and discovers new projects // wait till a task completes and sends a signal evaluationWaitHandle.WaitOne(); } } if (exceptionsInTasks.Count != 0) { exceptions = exceptionsInTasks.ToList(); return(false); } exceptions = null; return(true); }
/// <summary> /// Initializes the logger by subscribing to events of IEventSource /// </summary> public void Initialize(IEventSource eventSource) { _initialTargetOutputLogging = Environment.GetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING"); _initialLogImports = Traits.Instance.EscapeHatches.LogProjectImports; Environment.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", "true"); Environment.SetEnvironmentVariable("MSBUILDLOGIMPORTS", "1"); Traits.Instance.EscapeHatches.LogProjectImports = true; ProcessParameters(); try { string logDirectory = null; try { logDirectory = Path.GetDirectoryName(FilePath); } catch (Exception) { // Directory creation is best-effort; if finding its path fails don't create the directory // and possibly let the FileStream constructor below report the failure } if (logDirectory != null) { Directory.CreateDirectory(logDirectory); } stream = new FileStream(FilePath, FileMode.Create); if (CollectProjectImports != ProjectImportsCollectionMode.None) { projectImportsCollector = new ProjectImportsCollector(FilePath, CollectProjectImports == ProjectImportsCollectionMode.ZipFile); } if (eventSource is IEventSource3 eventSource3) { eventSource3.IncludeEvaluationMetaprojects(); } } catch (Exception e) { string errorCode; string helpKeyword; string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(out errorCode, out helpKeyword, "InvalidFileLoggerFile", FilePath, e.Message); throw new LoggerException(message, e, errorCode, helpKeyword); } stream = new GZipStream(stream, CompressionLevel.Optimal); // wrapping the GZipStream in a buffered stream significantly improves performance // and the max throughput is reached with a 32K buffer. See details here: // https://github.com/dotnet/runtime/issues/39233#issuecomment-745598847 stream = new BufferedStream(stream, bufferSize: 32768); binaryWriter = new BinaryWriter(stream); eventArgsWriter = new BuildEventArgsWriter(binaryWriter); binaryWriter.Write(FileFormatVersion); LogInitialInfo(); eventSource.AnyEventRaised += EventSource_AnyEventRaised; }
private (IReadOnlyCollection <ProjectGraphEntryPoint> NewEntryPoints, IReadOnlyDictionary <string, IReadOnlyCollection <string> > SolutionDependencies) ExpandSolutionIfPresent(IReadOnlyCollection <ProjectGraphEntryPoint> entryPoints) { if (entryPoints.Count == 0 || !entryPoints.Any(e => FileUtilities.IsSolutionFilename(e.ProjectFile))) { return(entryPoints, null); } if (entryPoints.Count != 1) { throw new ArgumentException( ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword( "StaticGraphAcceptsSingleSolutionEntryPoint", string.Join(";", entryPoints.Select(e => e.ProjectFile)))); } ErrorUtilities.VerifyThrowArgument(entryPoints.Count == 1, "StaticGraphAcceptsSingleSolutionEntryPoint"); var solutionEntryPoint = entryPoints.Single(); var solutionGlobalProperties = ImmutableDictionary.CreateRange( keyComparer: StringComparer.OrdinalIgnoreCase, valueComparer: StringComparer.OrdinalIgnoreCase, items: solutionEntryPoint.GlobalProperties ?? ImmutableDictionary <string, string> .Empty); var solution = SolutionFile.Parse(solutionEntryPoint.ProjectFile); if (solution.SolutionParserWarnings.Count != 0 || solution.SolutionParserErrorCodes.Count != 0) { throw new InvalidProjectFileException( ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword( "StaticGraphSolutionLoaderEncounteredSolutionWarningsAndErrors", solutionEntryPoint.ProjectFile, string.Join(";", solution.SolutionParserWarnings), string.Join(";", solution.SolutionParserErrorCodes))); } var projectsInSolution = GetBuildableProjects(solution); var currentSolutionConfiguration = SelectSolutionConfiguration(solution, solutionGlobalProperties); var newEntryPoints = new List <ProjectGraphEntryPoint>(projectsInSolution.Count); foreach (var project in projectsInSolution) { if (project.ProjectConfigurations.Count == 0) { continue; } var projectConfiguration = SelectProjectConfiguration(currentSolutionConfiguration, project.ProjectConfigurations); if (projectConfiguration.IncludeInBuild) { newEntryPoints.Add( new ProjectGraphEntryPoint( project.AbsolutePath, solutionGlobalProperties .SetItem("Configuration", projectConfiguration.ConfigurationName) .SetItem("Platform", projectConfiguration.PlatformName) )); } } newEntryPoints.TrimExcess(); return(newEntryPoints, GetSolutionDependencies(solution)); IReadOnlyCollection <ProjectInSolution> GetBuildableProjects(SolutionFile solutionFile) { return(solutionFile.ProjectsInOrder.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat && solutionFile.ProjectShouldBuild(p.RelativePath)).ToImmutableArray()); } SolutionConfigurationInSolution SelectSolutionConfiguration(SolutionFile solutionFile, ImmutableDictionary <string, string> globalProperties) { var solutionConfiguration = globalProperties.TryGetValue("Configuration", out string configuration) ? configuration : solutionFile.GetDefaultConfigurationName(); var solutionPlatform = globalProperties.TryGetValue("Platform", out string platform) ? platform : solutionFile.GetDefaultPlatformName(); return(new SolutionConfigurationInSolution(solutionConfiguration, solutionPlatform)); } ProjectConfigurationInSolution SelectProjectConfiguration( SolutionConfigurationInSolution solutionConfig, IReadOnlyDictionary <string, ProjectConfigurationInSolution> projectConfigs) { // implements the matching described in https://docs.microsoft.com/en-us/visualstudio/ide/understanding-build-configurations?view=vs-2019#how-visual-studio-assigns-project-configuration var solutionConfigFullName = solutionConfig.FullName; if (projectConfigs.TryGetValue(solutionConfigFullName, out ProjectConfigurationInSolution projectConfiguration)) { return(projectConfiguration); } var partiallyMarchedConfig = projectConfigs.FirstOrDefault(pc => pc.Value.ConfigurationName.Equals(solutionConfig.ConfigurationName, StringComparison.OrdinalIgnoreCase)).Value; return(partiallyMarchedConfig ?? projectConfigs.First().Value); } IReadOnlyDictionary <string, IReadOnlyCollection <string> > GetSolutionDependencies(SolutionFile solutionFile) { var solutionDependencies = new Dictionary <string, IReadOnlyCollection <string> >(); foreach (var projectWithDependencies in solutionFile.ProjectsInOrder.Where(p => p.Dependencies.Count != 0)) { solutionDependencies[projectWithDependencies.AbsolutePath] = projectWithDependencies.Dependencies.Select( dependencyGuid => { // code snippet cloned from SolutionProjectGenerator.AddPropertyGroupForSolutionConfiguration if (!solutionFile.ProjectsByGuid.TryGetValue(dependencyGuid, out var dependencyProject)) { // If it's not itself part of the solution, that's an invalid solution ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile( dependencyProject != null, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solutionFile.FullPath), "SolutionParseProjectDepNotFoundError", projectWithDependencies.ProjectGuid, dependencyGuid); } // Add it to the list of dependencies, but only if it should build in this solution configuration // (If a project is not selected for build in the solution configuration, it won't build even if it's depended on by something that IS selected for build) // .. and only if it's known to be MSBuild format, as projects can't use the information otherwise return(dependencyProject?.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat ? dependencyProject.AbsolutePath : null); }) .Where(p => p != null) .ToArray(); } return(solutionDependencies); } }
/// <summary> /// Increases the error count by 1, and logs the error message /// </summary> /// <param name="messageResourceName"></param> /// <param name="messageArgs"></param> private void LogError(string messageResourceName, params object[] messageArgs) { _errorLog.AddLast(ResourceUtilities.FormatResourceString(messageResourceName, messageArgs)); _errorCount++; }
/// <summary> /// Gets a text serialized value of a parameter for logging. /// </summary> internal static string GetParameterText(string prefix, string parameterName, IList parameterValue, bool logItemMetadata = true) { if (parameterValue == null || parameterValue.Count == 0) { return(parameterName); } using (var sb = new ReuseableStringBuilder()) { sb.Append(prefix); bool firstEntryIsTaskItemWithSomeCustomMetadata = false; var firstItem = parameterValue[0] as ITaskItem; if (firstItem != null) { if (firstItem.CloneCustomMetadata().Count > 0) { firstEntryIsTaskItemWithSomeCustomMetadata = true; } } // If it's just one entry in the list, and it's not a task item with metadata, keep it on one line like a scalar bool specialTreatmentForSingle = (parameterValue.Count == 1 && !firstEntryIsTaskItemWithSomeCustomMetadata); if (!specialTreatmentForSingle) { sb.Append("\n "); } sb.Append(parameterName); sb.Append('='); if (!specialTreatmentForSingle) { sb.Append("\n"); } bool truncateTaskInputs = Traits.Instance.EscapeHatches.TruncateTaskInputs; for (int i = 0; i < parameterValue.Count; i++) { if (parameterValue[i] == null) { continue; } if (!specialTreatmentForSingle) { sb.Append(" "); } AppendStringFromParameterValue(sb, parameterValue[i], logItemMetadata); if (!specialTreatmentForSingle && i < parameterValue.Count - 1) { sb.Append("\n"); } if (truncateTaskInputs && (sb.Length >= parameterCharacterLimit || i > parameterLimit)) { sb.Append(ResourceUtilities.GetResourceString("LogTaskInputs.Truncated")); break; } } return(sb.ToString()); } }
private void SetImageSource(Bitmap bmp) { seeImageView.imageBox2.Source = ResourceUtilities.ConvertToImageSource(bmp); }
private static Exception InvalidVersionFormat() { return(new FormatException(ResourceUtilities.GetResourceString(nameof(InvalidVersionFormat)))); }
public static string SerializeCaches(IConfigCache configCache, IResultsCache resultsCache, string outputCacheFile) { ErrorUtilities.VerifyThrowInternalNull(outputCacheFile, nameof(outputCacheFile)); try { if (string.IsNullOrWhiteSpace(outputCacheFile)) { return(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("EmptyOutputCacheFile")); } var fullPath = FileUtilities.NormalizePath(outputCacheFile); Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); using (var fileStream = File.OpenWrite(fullPath)) { var translator = BinaryTranslator.GetWriteTranslator(fileStream); ConfigCache configCacheToSerialize = null; ResultsCache resultsCacheToSerialize = null; switch (configCache) { case ConfigCache asConfigCache: configCacheToSerialize = asConfigCache; break; case ConfigCacheWithOverride configCacheWithOverride: configCacheToSerialize = configCacheWithOverride.CurrentCache; break; default: ErrorUtilities.ThrowInternalErrorUnreachable(); break; } switch (resultsCache) { case ResultsCache asResultsCache: resultsCacheToSerialize = asResultsCache; break; case ResultsCacheWithOverride resultsCacheWithOverride: resultsCacheToSerialize = resultsCacheWithOverride.CurrentCache; break; default: ErrorUtilities.ThrowInternalErrorUnreachable(); break; } translator.Translate(ref configCacheToSerialize); translator.Translate(ref resultsCacheToSerialize); } } catch (Exception e) { return(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ErrorWritingCacheFile", outputCacheFile, e.Message)); } return(null); }
public object GetResource(string resource, string language) { return(ResourceUtilities.GetResource(resource, language)); }
private void NodeLocalEngineLoop() { buildInProgress = true; // Create a logging service for this build request localEngine = new Engine(parentGlobalProperties, toolsetSearchLocations, 1 /* cpus */, true /* child node */, this.nodeId, parentStartupDirectory, null); localEngine.Router.ChildMode = true; localEngine.Router.ParentNode = this; this.outProcLoggingService = new EngineLoggingServicesOutProc(this, localEngine.FlushRequestEvent); if (nodeLoggers.Length != 0) { foreach (LoggerDescription loggerDescription in nodeLoggers) { IForwardingLogger newLogger = null; bool exitedDueToError = true; try { newLogger = loggerDescription.CreateForwardingLogger(); // Check if the class was not found in the assembly if (newLogger == null) { InternalLoggerException.Throw(null, null, "FatalErrorWhileInitializingLogger", true, loggerDescription.Name); } newLogger.Verbosity = loggerDescription.Verbosity; newLogger.Parameters = loggerDescription.LoggerSwitchParameters; newLogger.NodeId = nodeId; EventRedirector newRedirector = new EventRedirector(loggerDescription.LoggerId, outProcLoggingService); newLogger.BuildEventRedirector = newRedirector; exitedDueToError = false; } // Polite logger failure catch (LoggerException e) { ReportUnhandledError(e); } // Logger class was not found catch (InternalLoggerException e) { ReportUnhandledError(e); } catch (Exception e) { // Wrap the exception in a InternalLoggerException and send it to the parent node string errorCode; string helpKeyword; string message = ResourceUtilities.FormatResourceString(out errorCode, out helpKeyword, "FatalErrorWhileInitializingLogger", loggerDescription.Name); ReportUnhandledError(new InternalLoggerException(message, e, null, errorCode, helpKeyword, true)); } // If there was a failure registering loggers, null out the engine pointer if (exitedDueToError) { localEngine = null; return; } localEngine.RegisterLogger(newLogger); } localEngine.ExternalLoggingServices = outProcLoggingService; } // Hook up logging service to forward all events to the central engine if necessary if (centralizedLogging) { if (nodeLoggers.Length != 0) { localEngine.LoggingServices.ForwardingService = outProcLoggingService; localEngine.ExternalLoggingServices = outProcLoggingService; } else { localEngine.LoggingServices = outProcLoggingService; } } localEngine.LoggingServices.OnlyLogCriticalEvents = this.logOnlyCriticalEvents; if (!useBreadthFirstTraversal) { localEngine.PostEngineCommand(new ChangeTraversalTypeCommand(useBreadthFirstTraversal, true)); } // Post all the requests that passed in while the engine was being constructed // into the engine queue lock (buildRequests) { while (buildRequests.Count != 0) { BuildRequest buildRequest = buildRequests.Dequeue(); localEngine.PostBuildRequest(buildRequest); } } try { // If there are forwarding loggers registered - generate a custom build started if (nodeLoggers.Length > 0) { localEngine.LoggingServices.LogBuildStarted(EngineLoggingServicesInProc.CENTRAL_ENGINE_EVENTSOURCE); localEngine.LoggingServices.ProcessPostedLoggingEvents(); } // Trigger the actual build if shutdown was not called while the engine was being initialized if (!nodeShutdown) { localEngine.EngineBuildLoop(null); } } catch (Exception e) { // Unhandled exception during execution. The node has to be shutdown. ReportUnhandledError(e); } finally { if (localEngine != null) { // Flush all the messages associated before shutting down localEngine.LoggingServices.ProcessPostedLoggingEvents(); NodeManager nodeManager = localEngine.NodeManager; // If the local engine is already shutting down, the TEM will be nulled out if (nodeManager.TaskExecutionModule != null && nodeManager.TaskExecutionModule.TaskExecutionTime != 0) { TimeSpan taskTimeSpan = new TimeSpan(localEngine.NodeManager.TaskExecutionModule.TaskExecutionTime); totalTaskTime = (int)taskTimeSpan.TotalMilliseconds; } localEngine.Shutdown(); } // Flush all the events to the parent engine outProcLoggingService.ProcessPostedLoggingEvents(); // Indicate that the node logger thread should exit exitNodeEvent.Set(); } }
/// <summary> /// Gets the delta time of the physics (?) update. First it confirms the game is in a valid state. Then it calculats /// the time between physics update by comparing with Planetarium.GetUniversalTime() and GetMaxDeltaTime(). /// </summary> /// <returns>The delta time.</returns> protected double GetDeltaTimex() { if (Time.timeSinceLevelLoad < 1.0f || !FlightGlobals.ready) { //Error: Not sure what this error is for...maybe not enough time since load? Debug.Log(this.GetType().Name + "WARNING: check timeSinceLevelLoad/FlightGlobals"); Debug.Log(this.GetType().Name + "timeSinceLevelLoad = " + Time.timeSinceLevelLoad); Debug.Log(this.GetType().Name + "FlightGlobals.ready = " + !FlightGlobals.ready); return(-1); } if (Math.Abs(lastUpdateTime) < float.Epsilon) { //Error: Just started running Debug.Log(this.GetType().Name + "ERROR: check lastUpdateTime"); Debug.Log(this.GetType().Name + "lastUpdateTime = " + lastUpdateTime); lastUpdateTime = Planetarium.GetUniversalTime(); return(-1); } var deltaTime = Math.Min(Planetarium.GetUniversalTime() - lastUpdateTime, ResourceUtilities.GetMaxDeltaTime()); return(deltaTime); //why is deltaTime == 0? //return deltaTime; }
/// <summary> /// Reads a plan for the specified submission Id. /// </summary> public void ReadPlan(int submissionId, ILoggingService loggingService, BuildEventContext buildEventContext) { if (!BuildParameters.EnableBuildPlan) { return; } SchedulableRequest rootRequest = GetRootRequest(submissionId); if (rootRequest == null) { return; } string planName = GetPlanName(rootRequest); if (String.IsNullOrEmpty(planName)) { return; } if (!FileSystems.Default.FileExists(planName)) { return; } try { using (StreamReader file = new StreamReader(File.Open(planName, FileMode.Open))) { ReadTimes(file); ReadHierarchy(file); } if (_configIdToData.Count > 0) { AnalyzeData(); } } catch (IOException) { loggingService.LogCommentFromText(buildEventContext, MessageImportance.Low, ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CantReadBuildPlan", planName)); } catch (InvalidDataException) { loggingService.LogCommentFromText(buildEventContext, MessageImportance.Low, ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildPlanCorrupt", planName)); } catch (FormatException) { loggingService.LogCommentFromText(buildEventContext, MessageImportance.Low, ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildPlanCorrupt", planName)); } }
/// <summary> /// Load content of Platform.xml /// </summary> private void LoadManifestFile() { /* * Platform.xml format: * * <ApplicationPlatform name="UAP" friendlyName="Universal Application Platform" version="1.0.0.0"> * <DependentPlatform name="UAP" version="1.0.0.0" /> * <ContainedApiContracts> * <ApiContract name="UAP" version="1.0.0.0" /> * </ContainedApiContracts> * </ApplicationPlatform> */ try { string platformManifestPath = Path.Combine(_pathToManifest, "Platform.xml"); if (File.Exists(platformManifestPath)) { XmlDocument doc = new XmlDocument(); XmlReaderSettings readerSettings = new XmlReaderSettings(); readerSettings.DtdProcessing = DtdProcessing.Ignore; using (XmlReader xmlReader = XmlReader.Create(platformManifestPath, readerSettings)) { doc.Load(xmlReader); } XmlElement rootElement = null; foreach (XmlNode childNode in doc.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element && String.Equals(childNode.Name, Elements.ApplicationPlatform, StringComparison.Ordinal)) { rootElement = (XmlElement)childNode; break; } } DependentPlatforms = new List <DependentPlatform>(); ApiContracts = new List <ApiContract>(); if (rootElement != null) { Name = rootElement.GetAttribute(Attributes.Name); FriendlyName = rootElement.GetAttribute(Attributes.FriendlyName); PlatformVersion = rootElement.GetAttribute(Attributes.Version); foreach (XmlNode childNode in rootElement.ChildNodes) { XmlElement childElement = childNode as XmlElement; if (childElement == null) { continue; } if (ApiContract.IsContainedApiContractsElement(childElement.Name)) { ApiContract.ReadContractsElement(childElement, ApiContracts); } else if (ApiContract.IsVersionedContentElement(childElement.Name)) { bool versionedContent = false; bool.TryParse(childElement.InnerText, out versionedContent); this.VersionedContent = versionedContent; } else if (String.Equals(childElement.Name, Elements.DependentPlatform, StringComparison.Ordinal)) { DependentPlatforms.Add(new DependentPlatform(childElement.GetAttribute(Attributes.Name), childElement.GetAttribute(Attributes.Version))); } } } } else { this.ReadErrorMessage = ResourceUtilities.FormatResourceString("PlatformManifest.MissingPlatformXml", platformManifestPath); } } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } this.ReadErrorMessage = e.Message; } }
/// <summary> /// Writes a plan for the specified submission id. /// </summary> public void WritePlan(int submissionId, ILoggingService loggingService, BuildEventContext buildEventContext) { if (!BuildParameters.EnableBuildPlan) { return; } SchedulableRequest rootRequest = GetRootRequest(submissionId); if (rootRequest == null) { return; } string planName = GetPlanName(rootRequest); if (String.IsNullOrEmpty(planName)) { return; } try { using (StreamWriter file = new StreamWriter(File.Open(planName, FileMode.Create))) { // Write the accumulated configuration times. Dictionary <int, double> accumulatedTimeByConfiguration = new Dictionary <int, double>(); RecursiveAccumulateConfigurationTimes(rootRequest, accumulatedTimeByConfiguration); List <int> configurationsInOrder = new List <int>(accumulatedTimeByConfiguration.Keys); configurationsInOrder.Sort(); foreach (int configId in configurationsInOrder) { file.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", configId, accumulatedTimeByConfiguration[configId], _configCache[configId].ProjectFullPath)); } file.WriteLine(); // Write out the dependency information. RecursiveWriteDependencies(file, rootRequest); } } catch (IOException) { loggingService.LogCommentFromText(buildEventContext, MessageImportance.Low, ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CantWriteBuildPlan", planName)); } }
/// <summary> /// Apply a parameter /// </summary> private void ApplyFileLoggerParameter(string parameterName, string parameterValue) { if (String.Compare("LOGFILE", parameterName, StringComparison.OrdinalIgnoreCase) == 0) { if (string.IsNullOrEmpty(parameterValue)) { string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("InvalidFileLoggerFile", string.Empty, ResourceUtilities.GetResourceString("logfilePathNullOrEmpty")); throw new LoggerException(message); } // Set log file to the right half of the parameter string and then remove it as it is going to be replaced in Initialize _logFile = parameterValue; int indexOfParameter = _parameters.IndexOf(parameterName + s_fileLoggerParameterValueSplitCharacter[0] + parameterValue, 0, StringComparison.OrdinalIgnoreCase); int length = ((string)(parameterName + s_fileLoggerParameterValueSplitCharacter[0] + parameterValue)).Length; // Check to see if the next char is a ; if so remove that as well if ((indexOfParameter + length) < _parameters.Length && _parameters[indexOfParameter + length] == ';') { length++; } _parameters = _parameters.Remove(indexOfParameter, length); } }
/// <summary> /// Initialize this class if it hasn't been initialized yet. /// </summary> private void LazyInitialize() { if (_isInitialized) { return; } _isInitialized = true; // Crack the search path just one time. Match match = s_crackAssemblyFoldersFromConfigSentinel.Value.Match(this.searchPathElement); _wasMatch = false; if (match.Success) { _targetRuntimeVersion = match.Groups["TARGETRUNTIMEVERSION"].Value.Trim(); _assemblyFolderConfigFile = match.Groups["ASSEMBLYFOLDERCONFIGFILE"].Value.Trim(); if (_targetRuntimeVersion.Length != 0) { // Tolerate version keys that don't begin with "v" as these could come from user input if (!_targetRuntimeVersion.StartsWith("v", StringComparison.OrdinalIgnoreCase)) { _targetRuntimeVersion = _targetRuntimeVersion.Insert(0, "v"); } _wasMatch = true; bool useCache = Environment.GetEnvironmentVariable("MSBUILDDISABLEASSEMBLYFOLDERSEXCACHE") == null; string key = "6f7de854-47fe-4ae2-9cfe-9b33682abd91" + searchPathElement; if (useCache && _buildEngine != null) { _assemblyFoldersCache = _buildEngine.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build) as AssemblyFoldersFromConfigCache; } if (_assemblyFoldersCache == null) { // This should never happen. Microsoft.Common.CurrentVersion.targets will not specify a AssemblyFoldersFromConfig search path // if the specified (or default) file is not found. ErrorUtilities.VerifyThrow(File.Exists(_assemblyFolderConfigFile), $"The AssemblyFolders config file specified does not exist: {_assemblyFolderConfigFile}"); try { AssemblyFoldersFromConfig assemblyFolders = new AssemblyFoldersFromConfig(_assemblyFolderConfigFile, _targetRuntimeVersion, targetProcessorArchitecture); _assemblyFoldersCache = new AssemblyFoldersFromConfigCache(assemblyFolders, fileExists); if (useCache) { _buildEngine?.RegisterTaskObject(key, _assemblyFoldersCache, RegisteredTaskObjectLifetime.Build, true /* dispose early ok*/); } } catch (SerializationException e) { _taskLogger.LogError(ResourceUtilities.GetResourceString("ResolveAssemblyReference.AssemblyFoldersConfigFileMalformed"), _assemblyFolderConfigFile, e.Message); return; } } fileExists = _assemblyFoldersCache.FileExists; } } }
private void DetectCycles( IReadOnlyCollection <ProjectGraphNode> entryPointNodes, ProjectInterpretation projectInterpretation, Dictionary <ConfigurationMetadata, ParsedProject> allParsedProjects) { var nodeStates = new Dictionary <ProjectGraphNode, NodeVisitationState>(); foreach (var entryPointNode in entryPointNodes) { if (!nodeStates.TryGetValue(entryPointNode, out NodeVisitationState state)) { VisitNode(entryPointNode, nodeStates); } else { ErrorUtilities.VerifyThrow( state == NodeVisitationState.Processed, "entrypoints should get processed after a call to detect cycles"); } } return; (bool success, List <string> projectsInCycle) VisitNode( ProjectGraphNode node, IDictionary <ProjectGraphNode, NodeVisitationState> nodeState) { nodeState[node] = NodeVisitationState.InProcess; foreach (var referenceNode in node.ProjectReferences) { if (nodeState.TryGetValue(referenceNode, out var projectReferenceNodeState)) { // Because this is a depth-first search, we should only encounter new nodes or nodes whose subgraph has been completely processed. // If we encounter a node that is currently being processed(InProcess state), it must be one of the ancestors in a circular dependency. if (projectReferenceNodeState == NodeVisitationState.InProcess) { if (node.Equals(referenceNode)) { // the project being evaluated has a reference to itself var selfReferencingProjectString = FormatCircularDependencyError(new List <string> { node.ProjectInstance.FullPath, node.ProjectInstance.FullPath }); throw new CircularDependencyException( string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), selfReferencingProjectString)); } // the project being evaluated has a circular dependency involving multiple projects // add this project to the list of projects involved in cycle var projectsInCycle = new List <string> { referenceNode.ProjectInstance.FullPath }; return(false, projectsInCycle); } } else { // recursively process newly discovered references var loadReference = VisitNode(referenceNode, nodeState); if (!loadReference.success) { if (loadReference.projectsInCycle[0].Equals(node.ProjectInstance.FullPath)) { // we have reached the nth project in the cycle, form error message and throw loadReference.projectsInCycle.Add(referenceNode.ProjectInstance.FullPath); loadReference.projectsInCycle.Add(node.ProjectInstance.FullPath); var errorMessage = FormatCircularDependencyError(loadReference.projectsInCycle); throw new CircularDependencyException( string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), errorMessage)); } // this is one of the projects in the circular dependency // update the list of projects in cycle and return the list to the caller loadReference.projectsInCycle.Add(referenceNode.ProjectInstance.FullPath); return(false, loadReference.projectsInCycle); } } } nodeState[node] = NodeVisitationState.Processed; return(true, null); } }
/// <summary> /// Creates a new MSBuild process /// </summary> private int LaunchNode(string msbuildLocation, string commandLineArgs) { // Should always have been set already. ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, "msbuildLocation"); if (!File.Exists(msbuildLocation)) { throw new BuildAbortedException(ResourceUtilities.FormatResourceString("CouldNotFindMSBuildExe", msbuildLocation)); } // Repeat the executable name as the first token of the command line because the command line // parser logic expects it and will otherwise skip the first argument commandLineArgs = msbuildLocation + " " + commandLineArgs; BackendNativeMethods.STARTUP_INFO startInfo = new BackendNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf(startInfo); // Null out the process handles so that the parent process does not wait for the child process // to exit before it can exit. uint creationFlags = BackendNativeMethods.NORMALPRIORITYCLASS; startInfo.dwFlags = BackendNativeMethods.STARTFUSESTDHANDLES; if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDNODEWINDOW"))) { startInfo.hStdError = BackendNativeMethods.InvalidHandle; startInfo.hStdInput = BackendNativeMethods.InvalidHandle; startInfo.hStdOutput = BackendNativeMethods.InvalidHandle; creationFlags = creationFlags | BackendNativeMethods.CREATENOWINDOW; } else { creationFlags = creationFlags | BackendNativeMethods.CREATE_NEW_CONSOLE; } BackendNativeMethods.SECURITY_ATTRIBUTES processSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); BackendNativeMethods.SECURITY_ATTRIBUTES threadSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); processSecurityAttributes.nLength = Marshal.SizeOf(processSecurityAttributes); threadSecurityAttributes.nLength = Marshal.SizeOf(threadSecurityAttributes); BackendNativeMethods.PROCESS_INFORMATION processInfo = new BackendNativeMethods.PROCESS_INFORMATION(); string appName = msbuildLocation; CommunicationsUtilities.Trace("Launching node from {0}", msbuildLocation); bool result = BackendNativeMethods.CreateProcess ( msbuildLocation, commandLineArgs, ref processSecurityAttributes, ref threadSecurityAttributes, false, creationFlags, BackendNativeMethods.NullPtr, null, ref startInfo, out processInfo ); if (!result) { // Creating an instance of this exception calls GetLastWin32Error and also converts it to a user-friendly string. System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(); CommunicationsUtilities.Trace ( "Failed to launch node from {0}. System32 Error code {1}. Description {2}. CommandLine: {2}", msbuildLocation, e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message, commandLineArgs ); throw new NodeFailedToLaunchException(e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", processInfo.dwProcessId); return(processInfo.dwProcessId); }
/// <summary> /// Creates a new MSBuild process /// </summary> private Process LaunchNode(string msbuildLocation, string commandLineArgs) { // Should always have been set already. ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, nameof(msbuildLocation)); if (!FileSystems.Default.FileExists(msbuildLocation)) { throw new BuildAbortedException(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CouldNotFindMSBuildExe", msbuildLocation)); } // Repeat the executable name as the first token of the command line because the command line // parser logic expects it and will otherwise skip the first argument commandLineArgs = msbuildLocation + " " + commandLineArgs; BackendNativeMethods.STARTUP_INFO startInfo = new BackendNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf <BackendNativeMethods.STARTUP_INFO>(); // Null out the process handles so that the parent process does not wait for the child process // to exit before it can exit. uint creationFlags = 0; if (Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { creationFlags = BackendNativeMethods.NORMALPRIORITYCLASS; } if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDNODEWINDOW"))) { if (!Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { // Redirect the streams of worker nodes so that this MSBuild.exe's // parent doesn't wait on idle worker nodes to close streams // after the build is complete. startInfo.hStdError = BackendNativeMethods.InvalidHandle; startInfo.hStdInput = BackendNativeMethods.InvalidHandle; startInfo.hStdOutput = BackendNativeMethods.InvalidHandle; startInfo.dwFlags = BackendNativeMethods.STARTFUSESTDHANDLES; creationFlags |= BackendNativeMethods.CREATENOWINDOW; } } else { creationFlags |= BackendNativeMethods.CREATE_NEW_CONSOLE; } BackendNativeMethods.SECURITY_ATTRIBUTES processSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); BackendNativeMethods.SECURITY_ATTRIBUTES threadSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); processSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); threadSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); CommunicationsUtilities.Trace("Launching node from {0}", msbuildLocation); string exeName = msbuildLocation; #if RUNTIME_TYPE_NETCORE || MONO // Mono automagically uses the current mono, to execute a managed assembly if (!NativeMethodsShared.IsMono) { // Run the child process with the same host as the currently-running process. exeName = GetCurrentHost(); commandLineArgs = "\"" + msbuildLocation + "\" " + commandLineArgs; } #endif if (!NativeMethodsShared.IsWindows) { ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = exeName; processStartInfo.Arguments = commandLineArgs; if (!Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { // Redirect the streams of worker nodes so that this MSBuild.exe's // parent doesn't wait on idle worker nodes to close streams // after the build is complete. processStartInfo.RedirectStandardInput = true; processStartInfo.RedirectStandardOutput = true; processStartInfo.RedirectStandardError = true; processStartInfo.CreateNoWindow = (creationFlags | BackendNativeMethods.CREATENOWINDOW) == BackendNativeMethods.CREATENOWINDOW; } processStartInfo.UseShellExecute = false; Process process; try { process = Process.Start(processStartInfo); } catch (Exception ex) { CommunicationsUtilities.Trace ( "Failed to launch node from {0}. CommandLine: {1}" + Environment.NewLine + "{2}", msbuildLocation, commandLineArgs, ex.ToString() ); throw new NodeFailedToLaunchException(ex); } CommunicationsUtilities.Trace("Successfully launched {1} node with PID {0}", process.Id, exeName); return(process); } else { #if RUNTIME_TYPE_NETCORE if (NativeMethodsShared.IsWindows) { // Repeat the executable name in the args to suit CreateProcess commandLineArgs = "\"" + exeName + "\" " + commandLineArgs; } #endif BackendNativeMethods.PROCESS_INFORMATION processInfo = new BackendNativeMethods.PROCESS_INFORMATION(); bool result = BackendNativeMethods.CreateProcess ( exeName, commandLineArgs, ref processSecurityAttributes, ref threadSecurityAttributes, false, creationFlags, BackendNativeMethods.NullPtr, null, ref startInfo, out processInfo ); if (!result) { // Creating an instance of this exception calls GetLastWin32Error and also converts it to a user-friendly string. System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(); CommunicationsUtilities.Trace ( "Failed to launch node from {0}. System32 Error code {1}. Description {2}. CommandLine: {2}", msbuildLocation, e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message, commandLineArgs ); throw new NodeFailedToLaunchException(e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message); } int childProcessId = processInfo.dwProcessId; if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != NativeMethods.InvalidHandle) { NativeMethodsShared.CloseHandle(processInfo.hProcess); } if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != NativeMethods.InvalidHandle) { NativeMethodsShared.CloseHandle(processInfo.hThread); } CommunicationsUtilities.Trace("Successfully launched {1} node with PID {0}", childProcessId, exeName); return(Process.GetProcessById(childProcessId)); } }
private string GenerateCode(out string extension) { extension = null; bool haveGeneratedContent = false; CodeDomProvider provider; try { provider = CodeDomProvider.CreateProvider(Language); } catch (SystemException e) when #if FEATURE_SYSTEM_CONFIGURATION (e is ConfigurationException || e is SecurityException) #else (e.GetType().Name == "ConfigurationErrorsException") //TODO: catch specific exception type once it is public https://github.com/dotnet/corefx/issues/40456 #endif { Log.LogErrorWithCodeFromResources("WriteCodeFragment.CouldNotCreateProvider", Language, e.Message); return(null); } extension = provider.FileExtension; var unit = new CodeCompileUnit(); var globalNamespace = new CodeNamespace(); unit.Namespaces.Add(globalNamespace); // Declare authorship. Unfortunately CodeDOM puts this comment after the attributes. string comment = ResourceUtilities.GetResourceString("WriteCodeFragment.Comment"); globalNamespace.Comments.Add(new CodeCommentStatement(comment)); if (AssemblyAttributes == null) { return(String.Empty); } // For convenience, bring in the namespaces, where many assembly attributes lie globalNamespace.Imports.Add(new CodeNamespaceImport("System")); globalNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection")); foreach (ITaskItem attributeItem in AssemblyAttributes) { var attribute = new CodeAttributeDeclaration(new CodeTypeReference(attributeItem.ItemSpec)); // Some attributes only allow positional constructor arguments, or the user may just prefer them. // To set those, use metadata names like "_Parameter1", "_Parameter2" etc. // If a parameter index is skipped, it's an error. IDictionary customMetadata = attributeItem.CloneCustomMetadata(); var orderedParameters = new List <CodeAttributeArgument>(new CodeAttributeArgument[customMetadata.Count + 1] /* max possible slots needed */); var namedParameters = new List <CodeAttributeArgument>(); foreach (DictionaryEntry entry in customMetadata) { string name = (string)entry.Key; string value = (string)entry.Value; if (name.StartsWith("_Parameter", StringComparison.OrdinalIgnoreCase)) { if (!Int32.TryParse(name.Substring("_Parameter".Length), out int index)) { Log.LogErrorWithCodeFromResources("General.InvalidValue", name, "WriteCodeFragment"); return(null); } if (index > orderedParameters.Count || index < 1) { Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", index); return(null); } // "_Parameter01" and "_Parameter1" would overwrite each other orderedParameters[index - 1] = new CodeAttributeArgument(String.Empty, new CodePrimitiveExpression(value)); } else { namedParameters.Add(new CodeAttributeArgument(name, new CodePrimitiveExpression(value))); } } bool encounteredNull = false; for (int i = 0; i < orderedParameters.Count; i++) { if (orderedParameters[i] == null) { // All subsequent args should be null, else a slot was missed encounteredNull = true; continue; } if (encounteredNull) { Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", i + 1 /* back to 1 based */); return(null); } attribute.Arguments.Add(orderedParameters[i]); } foreach (CodeAttributeArgument namedParameter in namedParameters) { attribute.Arguments.Add(namedParameter); } unit.AssemblyCustomAttributes.Add(attribute); haveGeneratedContent = true; } var generatedCode = new StringBuilder(); using (var writer = new StringWriter(generatedCode, CultureInfo.CurrentCulture)) { provider.GenerateCodeFromCompileUnit(unit, writer, new CodeGeneratorOptions()); } string code = generatedCode.ToString(); // If we just generated infrastructure, don't bother returning anything // as there's no point writing the file return(haveGeneratedContent ? code : String.Empty); } }
/// <remarks> /// Traverse an evaluated graph /// Maintain the state of each node (InProcess and Processed) to detect cycles /// returns false if loading the graph is not successful /// </remarks> private (bool success, List <string> projectsInCycle) DetectCycles(ProjectGraphNode node, Dictionary <ProjectGraphNode, NodeState> nodeState, ProjectCollection projectCollection, PropertyDictionary <ProjectPropertyInstance> globalProperties) { nodeState[node] = NodeState.InProcess; IEnumerable <ProjectItemInstance> projectReferenceItems = node.ProjectInstance.GetItems(MSBuildConstants.ProjectReferenceItemName); foreach (var projectReferenceToParse in projectReferenceItems) { string projectReferenceFullPath = projectReferenceToParse.GetMetadataValue(FullPathMetadataName); PropertyDictionary <ProjectPropertyInstance> projectReferenceGlobalProperties = GetProjectReferenceGlobalProperties(projectReferenceToParse, globalProperties); var projectReferenceConfigurationMetadata = new ConfigurationMetadata(projectReferenceFullPath, projectReferenceGlobalProperties); ProjectGraphNode projectReference = _allParsedProjects[projectReferenceConfigurationMetadata]; if (nodeState.TryGetValue(projectReference, out NodeState projectReferenceNodeState)) { // Because this is a depth-first search, we should only encounter new nodes or nodes whose subgraph has been completely processed. // If we encounter a node that is currently being processed(InProcess state), it must be one of the ancestors in a circular dependency. if (projectReferenceNodeState == NodeState.InProcess) { if (node.Equals(projectReference)) { // the project being evaluated has a reference to itself var selfReferencingProjectString = FormatCircularDependencyError(new List <string> { node.ProjectInstance.FullPath, node.ProjectInstance.FullPath }); throw new CircularDependencyException(string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), selfReferencingProjectString)); } else { // the project being evaluated has a circular dependency involving multiple projects // add this project to the list of projects involved in cycle var projectsInCycle = new List <string> { projectReferenceConfigurationMetadata.ProjectFullPath }; return(false, projectsInCycle); } } } else { // recursively process newly discovered references var loadReference = DetectCycles(projectReference, nodeState, projectCollection, projectReferenceGlobalProperties); if (!loadReference.success) { if (loadReference.projectsInCycle[0].Equals(node.ProjectInstance.FullPath)) { // we have reached the nth project in the cycle, form error message and throw loadReference.projectsInCycle.Add(projectReferenceConfigurationMetadata.ProjectFullPath); loadReference.projectsInCycle.Add(node.ProjectInstance.FullPath); var errorMessage = FormatCircularDependencyError(loadReference.projectsInCycle); throw new CircularDependencyException(string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), errorMessage)); } else { // this is one of the projects in the circular dependency // update the list of projects in cycle and return the list to the caller loadReference.projectsInCycle.Add(projectReferenceConfigurationMetadata.ProjectFullPath); return(false, loadReference.projectsInCycle); } } } ProjectGraphNode parsedProjectReference = _allParsedProjects[projectReferenceConfigurationMetadata]; node.AddProjectReference(parsedProjectReference); parsedProjectReference.AddReferencingProject(node); } nodeState[node] = NodeState.Processed; return(true, null); }
/// <summary> /// Instructs the MSBuild engine to build one or more project files whose locations are specified by the /// <see cref="Projects"/> property. /// </summary> /// <returns>true if all projects build successfully; false if any project fails</returns> public override bool Execute() { // If no projects were passed in, just return success. if ((Projects == null) || (Projects.Length == 0)) { return(true); } // We have been asked to unescape all escaped characters before processing if (TargetAndPropertyListSeparators != null && TargetAndPropertyListSeparators.Length > 0) { ExpandAllTargetsAndProperties(); } // Parse the global properties into a hashtable. if (!PropertyParser.GetTableWithEscaping(Log, ResourceUtilities.GetResourceString("General.GlobalProperties"), "Properties", Properties, out Dictionary <string, string> propertiesTable)) { return(false); } // Parse out the properties to undefine, if any. string[] undefinePropertiesArray = null; if (!String.IsNullOrEmpty(RemoveProperties)) { Log.LogMessageFromResources(MessageImportance.Low, "General.UndefineProperties"); undefinePropertiesArray = RemoveProperties.Split(';'); foreach (string property in undefinePropertiesArray) { Log.LogMessageFromText($" {property}", MessageImportance.Low); } } bool isRunningMultipleNodes = BuildEngine2.IsRunningMultipleNodes; // If we are in single proc mode and stopOnFirstFailure is true, we cannot build in parallel because // building in parallel sends all of the projects to the engine at once preventing us from not sending // any more projects after the first failure. Therefore, to preserve compatibility with whidbey if we are in this situation disable buildInParallel. if (!isRunningMultipleNodes && StopOnFirstFailure && BuildInParallel) { BuildInParallel = false; Log.LogMessageFromResources(MessageImportance.Low, "MSBuild.NotBuildingInParallel"); } // When the condition below is met, provide an information message indicating stopOnFirstFailure // will have no effect. The reason there will be no effect is, when buildInParallel is true // All project files will be submitted to the engine all at once, this mean there is no stopping for failures between projects. // When RunEachTargetSeparately is false, all targets will be submitted to the engine at once, this means there is no way to stop between target failures. // therefore the first failure seen will be the only failure seen. if (isRunningMultipleNodes && BuildInParallel && StopOnFirstFailure && !RunEachTargetSeparately) { Log.LogMessageFromResources(MessageImportance.Low, "MSBuild.NoStopOnFirstFailure"); } // This is a list of string[]. That is, each element in the list is a string[]. Each // string[] represents a set of target names to build. Depending on the value // of the RunEachTargetSeparately parameter, we each just call the engine to run all // the targets together, or we call the engine separately for each target. List <string[]> targetLists = CreateTargetLists(Targets, RunEachTargetSeparately); bool success = true; List <ITaskItem> singleProject = null; bool[] skipProjects = null; if (BuildInParallel) { skipProjects = new bool[Projects.Length]; for (int i = 0; i < skipProjects.Length; i++) { skipProjects[i] = true; } } else { singleProject = new List <ITaskItem>(1) { null }; } // Read in each project file. If there are any errors opening the file or parsing the XML, // raise an event and return False. If any one of the projects fails to build, return False, // otherwise return True. If parallel build is requested we first check for file existence so // that we don't pass a non-existent file to IBuildEngine causing an exception for (int i = 0; i < Projects.Length; i++) { ITaskItem project = Projects[i]; string projectPath = FileUtilities.AttemptToShortenPath(project.ItemSpec); if (StopOnFirstFailure && !success) { // Inform the user that we skipped the remaining projects because StopOnFirstFailure=true. Log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingProjects"); // We have encountered a failure. Caller has requested that we not // continue with remaining projects. break; } if (File.Exists(projectPath) || (_skipNonexistentProjects == SkipNonexistentProjectsBehavior.Build)) { if (FileUtilities.IsVCProjFilename(projectPath)) { Log.LogErrorWithCodeFromResources("MSBuild.ProjectUpgradeNeededToVcxProj", project.ItemSpec); success = false; continue; } // If we are building in parallel we want to only make one call to // ExecuteTargets once we verified that all projects exist if (!BuildInParallel) { singleProject[0] = project; if (!ExecuteTargets ( singleProject, propertiesTable, undefinePropertiesArray, targetLists, StopOnFirstFailure, RebaseOutputs, BuildEngine3, Log, _targetOutputs, UseResultsCache, UnloadProjectsOnCompletion, ToolsVersion ) ) { success = false; } } else { skipProjects[i] = false; } } else { if (_skipNonexistentProjects == SkipNonexistentProjectsBehavior.Skip) { Log.LogMessageFromResources(MessageImportance.High, "MSBuild.ProjectFileNotFoundMessage", project.ItemSpec); } else { ErrorUtilities.VerifyThrow(_skipNonexistentProjects == SkipNonexistentProjectsBehavior.Error, "skipNonexistentProjects has unexpected value {0}", _skipNonexistentProjects); Log.LogErrorWithCodeFromResources("MSBuild.ProjectFileNotFound", project.ItemSpec); success = false; } } } // We need to build all the projects that were not skipped if (BuildInParallel) { success = BuildProjectsInParallel(propertiesTable, undefinePropertiesArray, targetLists, success, skipProjects); } return(success); }
/// <summary> /// Writes a line from a resource string to the log, using the specified indentation. /// </summary> internal void WriteLinePrettyFromResource(int indentLevel, string resourceString, params object[] args) { string formattedString = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(resourceString, args); WriteLinePretty(indentLevel, formattedString); }
/// <returns>True if the operation was successful</returns> internal static bool ExecuteTargets ( List <ITaskItem> projects, Dictionary <string, string> propertiesTable, string[] undefineProperties, List <string[]> targetLists, bool stopOnFirstFailure, bool rebaseOutputs, IBuildEngine3 buildEngine, TaskLoggingHelper log, List <ITaskItem> targetOutputs, bool useResultsCache, bool unloadProjectsOnCompletion, string toolsVersion ) { bool success = true; // We don't log a message about the project and targets we're going to // build, because it'll all be in the immediately subsequent ProjectStarted event. var projectDirectory = new string[projects.Count]; var projectNames = new string[projects.Count]; var toolsVersions = new string[projects.Count]; var projectProperties = new Dictionary <string, string> [projects.Count]; var undefinePropertiesPerProject = new IList <string> [projects.Count]; for (int i = 0; i < projectNames.Length; i++) { projectNames[i] = null; projectProperties[i] = propertiesTable; if (projects[i] != null) { // Retrieve projectDirectory only the first time. It never changes anyway. string projectPath = FileUtilities.AttemptToShortenPath(projects[i].ItemSpec); projectDirectory[i] = Path.GetDirectoryName(projectPath); projectNames[i] = projects[i].ItemSpec; toolsVersions[i] = toolsVersion; // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("Properties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceString("General.OverridingProperties", projectNames[i]), "Properties", projects[i].GetMetadata("Properties").Split(';'), out Dictionary <string, string> preProjectPropertiesTable) ) { return(false); } projectProperties[i] = preProjectPropertiesTable; } if (undefineProperties != null) { undefinePropertiesPerProject[i] = new List <string>(undefineProperties); } // If the user wanted to undefine specific global properties for this project, parse // that string and remove them now. string projectUndefineProperties = projects[i].GetMetadata("UndefineProperties"); if (!String.IsNullOrEmpty(projectUndefineProperties)) { string[] propertiesToUndefine = projectUndefineProperties.Split(';'); if (undefinePropertiesPerProject[i] == null) { undefinePropertiesPerProject[i] = new List <string>(propertiesToUndefine.Length); } if (log != null && propertiesToUndefine.Length > 0) { log.LogMessageFromResources(MessageImportance.Low, "General.ProjectUndefineProperties", projectNames[i]); foreach (string property in propertiesToUndefine) { undefinePropertiesPerProject[i].Add(property); log.LogMessageFromText($" {property}", MessageImportance.Low); } } } // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("AdditionalProperties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceString("General.AdditionalProperties", projectNames[i]), "AdditionalProperties", projects[i].GetMetadata("AdditionalProperties").Split(';'), out Dictionary <string, string> additionalProjectPropertiesTable) ) { return(false); } var combinedTable = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); // First copy in the properties from the global table that not in the additional properties table if (projectProperties[i] != null) { foreach (KeyValuePair <string, string> entry in projectProperties[i]) { if (!additionalProjectPropertiesTable.ContainsKey(entry.Key)) { combinedTable.Add(entry.Key, entry.Value); } } } // Add all the additional properties foreach (KeyValuePair <string, string> entry in additionalProjectPropertiesTable) { combinedTable.Add(entry.Key, entry.Value); } projectProperties[i] = combinedTable; } // If the user specified a different toolsVersion for this project - then override the setting if (!String.IsNullOrEmpty(projects[i].GetMetadata("ToolsVersion"))) { toolsVersions[i] = projects[i].GetMetadata("ToolsVersion"); } } } foreach (string[] targetList in targetLists) { if (stopOnFirstFailure && !success) { // Inform the user that we skipped the remaining targets StopOnFirstFailure=true. log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingTargets"); // We have encountered a failure. Caller has requested that we not // continue with remaining targets. break; } // Send the project off to the build engine. By passing in null to the // first param, we are indicating that the project to build is the same // as the *calling* project file. BuildEngineResult result = buildEngine.BuildProjectFilesInParallel(projectNames, targetList, projectProperties, undefinePropertiesPerProject, toolsVersions, true /* ask that target outputs are returned in the buildengineresult */); bool currentTargetResult = result.Result; IList <IDictionary <string, ITaskItem[]> > targetOutputsPerProject = result.TargetOutputsPerProject; success = success && currentTargetResult; // If the engine was able to satisfy the build request if (currentTargetResult) { for (int i = 0; i < projects.Count; i++) { IEnumerable <string> nonNullTargetList = targetList ?? targetOutputsPerProject[i].Keys; foreach (string targetName in nonNullTargetList) { if (targetOutputsPerProject[i].ContainsKey(targetName)) { ITaskItem[] outputItemsFromTarget = targetOutputsPerProject[i][targetName]; foreach (ITaskItem outputItemFromTarget in outputItemsFromTarget) { // No need to rebase if the calling project is the same as the callee project // (project == null). Also no point in trying to copy item metadata either, // because no items were passed into the Projects parameter! if (projects[i] != null) { // Rebase the output item paths if necessary. No need to rebase if the calling // project is the same as the callee project (project == null). if (rebaseOutputs) { try { outputItemFromTarget.ItemSpec = Path.Combine(projectDirectory[i], outputItemFromTarget.ItemSpec); } catch (ArgumentException e) { log.LogWarningWithCodeFromResources(null, projects[i].ItemSpec, 0, 0, 0, 0, "MSBuild.CannotRebaseOutputItemPath", outputItemFromTarget.ItemSpec, e.Message); } } // Copy the custom item metadata from the "Projects" items to these // output items. projects[i].CopyMetadataTo(outputItemFromTarget); // Set a metadata on the output items called "MSBuildProjectFile" which tells you which project file produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceProjectFile))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceProjectFile, projects[i].GetMetadata(FileUtilities.ItemSpecModifiers.FullPath)); } } // Set a metadata on the output items called "MSBuildTargetName" which tells you which target produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceTargetName))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceTargetName, targetName); } } targetOutputs.AddRange(outputItemsFromTarget); } } } } } return(success); }
/// <summary> /// Retrieves the list of dependencies this target needs to have built and moves the target to the next state. /// Never returns null. /// </summary> /// <returns>A collection of targets on which this target depends.</returns> internal List <TargetSpecification> GetDependencies(ProjectLoggingContext projectLoggingContext) { VerifyState(_state, TargetEntryState.Dependencies); // Resolve the target now, since from this point on we are going to be doing work with the actual instance. GetTargetInstance(); // We first make sure no batching was attempted with the target's condition. // UNDONE: (Improvement) We want to allow this actually. In order to do this we need to determine what the // batching buckets are, and if there are any which aren't empty, return our list of dependencies. // Only in the case where all bucket conditions fail do we want to skip the target entirely (and // this skip building the dependencies.) if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(_target.Condition)) { ProjectErrorUtilities.ThrowInvalidProject(_target.ConditionLocation, "TargetConditionHasInvalidMetadataReference", _target.Name, _target.Condition); } // If condition is false (based on propertyBag), set this target's state to // "Skipped" since we won't actually build it. bool condition = ConditionEvaluator.EvaluateCondition ( _target.Condition, ParserOptions.AllowPropertiesAndItemLists, _expander, ExpanderOptions.ExpandPropertiesAndItems, _requestEntry.ProjectRootDirectory, _target.ConditionLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext, FileSystems.Default); if (!condition) { _targetResult = new TargetResult(Array.Empty <TaskItem>(), new WorkUnitResult(WorkUnitResultCode.Skipped, WorkUnitActionCode.Continue, null)); _state = TargetEntryState.Completed; if (!projectLoggingContext.LoggingService.OnlyLogCriticalEvents) { // Expand the expression for the Log. Since we know the condition evaluated to false, leave unexpandable properties in the condition so as not to cause an error string expanded = _expander.ExpandIntoStringAndUnescape(_target.Condition, ExpanderOptions.ExpandPropertiesAndItems | ExpanderOptions.LeavePropertiesUnexpandedOnError, _target.ConditionLocation); // By design: Not building dependencies. This is what NAnt does too. // NOTE: In the original code, this was logged from the target logging context. However, the target // hadn't been "started" by then, so you'd get a target message outside the context of a started // target. In the Task builder (and original Task Engine), a Task Skipped message would be logged in // the context of the target, not the task. This should be the same, especially given that we // wish to allow batching on the condition of a target. var skippedTargetEventArgs = new TargetSkippedEventArgs( ResourceUtilities.GetResourceString("TargetSkippedFalseCondition"), _target.Name, _target.Condition, expanded) { BuildEventContext = projectLoggingContext.BuildEventContext, TargetName = _target.Name, TargetFile = _target.Location.File, ParentTarget = ParentEntry?.Target?.Name, BuildReason = BuildReason }; projectLoggingContext.LogBuildEvent(skippedTargetEventArgs); } return(new List <TargetSpecification>()); } var dependencies = _expander.ExpandIntoStringListLeaveEscaped(_target.DependsOnTargets, ExpanderOptions.ExpandPropertiesAndItems, _target.DependsOnTargetsLocation); List <TargetSpecification> dependencyTargets = new List <TargetSpecification>(); foreach (string escapedDependency in dependencies) { string dependencyTargetName = EscapingUtilities.UnescapeAll(escapedDependency); dependencyTargets.Add(new TargetSpecification(dependencyTargetName, _target.DependsOnTargetsLocation)); } _state = TargetEntryState.Execution; return(dependencyTargets); }
private string TranslateKudos(string textToTranslate, CultureInfo culture) { return(ResourceUtilities.GetResourceValue(_resourceManager, textToTranslate, culture)); }