private static async Task DoWorkInWriterLock(IVsProject project, Action <MsBuildProject> action) { UnconfiguredProject unconfiguredProject = GetUnconfiguredProject(project); if (unconfiguredProject != null) { var service = unconfiguredProject.ProjectService.Services.ProjectLockService; if (service != null) { using (ProjectWriteLockReleaser x = await service.WriteLockAsync()) { await x.CheckoutAsync(unconfiguredProject.FullPath); ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync(); MsBuildProject buildProject = await x.GetProjectAsync(configuredProject); if (buildProject != null) { action(buildProject); } await x.ReleaseAsync(); } await unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread(); } } }
public static async Task DoWorkInWriterLockAsync(Project project, IVsHierarchy hierarchy, Action <MsBuildProject> action) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var vsProject = (IVsProject)hierarchy; UnconfiguredProject unconfiguredProject = GetUnconfiguredProject(vsProject); if (unconfiguredProject != null) { var service = unconfiguredProject.ProjectService.Services.ProjectLockService; if (service != null) { using (ProjectWriteLockReleaser x = await service.WriteLockAsync()) { await x.CheckoutAsync(unconfiguredProject.FullPath); ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync(); MsBuildProject buildProject = await x.GetProjectAsync(configuredProject); if (buildProject != null) { action(buildProject); } await x.ReleaseAsync(); } await unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread(); project.Save(); } } }
public async Task EnterWriteLockAsync(Func <ProjectCollection, CancellationToken, Task> action, CancellationToken cancellationToken = default) { Requires.NotNull(action, nameof(action)); using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync(cancellationToken)) { // Only async to let the caller call one of the other project accessor methods await action(access.ProjectCollection, cancellationToken); // Avoid blocking thread on Dispose await access.ReleaseAsync(); } }
public async Task OpenProjectXmlForWriteAsync(UnconfiguredProject project, Action <ProjectRootElement> action, CancellationToken cancellationToken = default) { Requires.NotNull(project, nameof(project)); Requires.NotNull(project, nameof(action)); using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync(cancellationToken)) { await access.CheckoutAsync(project.FullPath); ProjectRootElement rootElement = await access.GetProjectXmlAsync(project.FullPath, cancellationToken); // Deliberately not async to reduce the type of // code you can run while holding the lock. action(rootElement); // Avoid blocking thread on Dispose await access.ReleaseAsync(); } }
private static async Task DoWorkInWriterLockInternal(Project project, IVsHierarchy hierarchy, Action <MsBuildProject> action) { UnconfiguredProject unconfiguredProject = GetUnconfiguredProject((IVsProject)hierarchy); if (unconfiguredProject != null) { var service = unconfiguredProject.ProjectService.Services.ProjectLockService; if (service != null) { // WriteLockAsync will move us to a background thread. using (ProjectWriteLockReleaser x = await service.WriteLockAsync()) { await x.CheckoutAsync(unconfiguredProject.FullPath); ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync(); MsBuildProject buildProject = await x.GetProjectAsync(configuredProject); if (buildProject != null) { action(buildProject); } await x.ReleaseAsync(); } // perform the save synchronously await Task.Run(() => { // move to the UI thread for the rest of this method unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread(); var fileSystem = new PhysicalFileSystem(@"c:\"); fileSystem.MakeFileWritable(project.FullName); project.Save(); } ); } } }
async Task <bool> BuildProjectAsync(ProjectWriteLockReleaser writeAccess) { var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject); var solutionPath = QtProjectTracker.SolutionPath; var configProps = new Dictionary <string, string>( ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary()) { { "SolutionPath", solutionPath }, { "SolutionFileName", Path.GetFileName(solutionPath) }, { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) }, { "SolutionExt", Path.GetExtension(solutionPath) }, { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' } }; foreach (var property in Properties) { configProps[property.Key] = property.Value; } var projectInstance = new ProjectInstance(msBuildProject.Xml, configProps, null, new ProjectCollection()); var loggerVerbosity = LoggerVerbosity; if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity; } var buildParams = new BuildParameters() { Loggers = (loggerVerbosity != LoggerVerbosity.Quiet) ? new[] { new QtProjectLogger() { Verbosity = loggerVerbosity } } : null }; var buildRequest = new BuildRequestData(projectInstance, Targets.ToArray(), hostServices: null, flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild); if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, ConfiguredProject.ProjectConfiguration.Name, UnconfiguredProject.FullPath)); Messages.Print("=== Targets"); foreach (var target in buildRequest.TargetNames) { Messages.Print(string.Format(" {0}", target)); } Messages.Print("=== Properties"); foreach (var property in Properties) { Messages.Print(string.Format(" {0}={1}", property.Key, property.Value)); } } BuildResult result = null; while (result == null) { try { result = BuildManager.DefaultBuildManager.Build( buildParams, buildRequest); } catch (InvalidOperationException) { if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] " + "Warning: Another build is in progress; waiting...", DateTime.Now, Thread.CurrentThread.ManagedThreadId, ConfiguredProject.ProjectConfiguration.Name)); } await Task.Delay(3000); } } if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { string resMsg; StringBuilder resInfo = new StringBuilder(); if (result?.OverallResult == BuildResultCode.Success) { resMsg = "Build ok"; } else { resMsg = "Build FAIL"; if (result == null) { resInfo.AppendLine("####### Build returned 'null'"); } else { resInfo.AppendLine("####### Build returned 'Failure' code"); if (result.ResultsByTarget != null) { foreach (var tr in result.ResultsByTarget) { var res = tr.Value; if (res.ResultCode != TargetResultCode.Failure) { continue; } resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key); if (res.Items != null && res.Items.Length > 0) { resInfo.AppendFormat( "Items: {0}\r\n", string.Join(", ", res.Items .Select(it => it.ItemSpec))); } var e = tr.Value?.Exception; if (e != null) { resInfo.AppendFormat( "Exception: {0}\r\nStacktrace:\r\n{1}\r\n", e.Message, e.StackTrace); } } } } } Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, ConfiguredProject.ProjectConfiguration.Name, resMsg, resInfo.ToString())); } bool ok = false; if (result == null || result.ResultsByTarget == null || result.OverallResult != BuildResultCode.Success) { Messages.Print(string.Format("{0}: background build FAILED!", Path.GetFileName(UnconfiguredProject.FullPath))); } else { var checkResults = result.ResultsByTarget .Where(x => Targets.Contains(x.Key)) .Select(x => x.Value); ok = checkResults.Any() && checkResults.All(x => x.ResultCode == TargetResultCode.Success); if (ok) { msBuildProject.MarkDirty(); } } await writeAccess.ReleaseAsync(); return(ok); }