public async Task CreateInMemoryImport() { if (_unloadCancellationToken.IsCancellationRequested) { return; } using (var access = await _projectLockService.WriteLockAsync(_unloadCancellationToken)) { // A bit odd but we have to "check it out" prior to creating it to avoid some of the validations in chk CPS await access.CheckoutAsync(_inMemoryImportFullPath); // Now either open or create the in-memory file. Normally Create will happen, but in // a scenario where your project had previously failed to load for some reason, need to TryOpen // to avoid a new reason for a project load failure _inMemoryImport = ProjectRootElement.TryOpen(_inMemoryImportFullPath, access.ProjectCollection); if (_inMemoryImport != null) { // The file already exists. Scrape it out so we don’t add duplicate items. _inMemoryImport.RemoveAllChildren(); } else { // The project didn’t already exist, so create it, and then mark the evaluated project dirty // so that MSBuild will notice. This step isn’t necessary if the project was already in memory. _inMemoryImport = CreateEmptyMsBuildProject(_inMemoryImportFullPath, access.ProjectCollection); // Note that we actually need to mark every project evaluation dirty that is already loaded. await ReevaluateLoadedConfiguredProjects(_unloadCancellationToken, access); } _filesItemGroup = _inMemoryImport.AddItemGroup(); _directoriesItemGroup = _inMemoryImport.AddItemGroup(); _temporaryAddedItemGroup = _inMemoryImport.AddItemGroup(); } }
public async Task SubscribeProjectXmlChangedEventAsync(UnconfiguredProject unconfiguredProject, EventHandler <ProjectXmlChangedEventArgs> handler) { var configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync().ConfigureAwait(false); using (var access = await _projectLockService.WriteLockAsync()) { var xmlProject = await access.GetProjectAsync(configuredProject).ConfigureAwait(true); xmlProject.ProjectCollection.ProjectXmlChanged += handler; } }
public async Task EnterWriteLockAsync(Func <ProjectCollection, CancellationToken, Task> action, CancellationToken cancellationToken = default) { Requires.NotNull(action, nameof(action)); await _projectLockService.WriteLockAsync(async access => { // 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(); }, cancellationToken); }
/// <summary> /// Called when a project.lock.json file changes. /// </summary> public int FilesChanged(uint cChanges, string[] rgpszFile, uint[] rggrfChange) { // Kick off the operation to notify the project change in a different thread irregardless of // the kind of change since we are interested in all changes. _projectServices.ThreadingService.Fork(async() => { try { await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() => { using (var access = await _projectLockService.WriteLockAsync()) { // notify all the loaded configured projects var currentProjects = _projectServices.Project.LoadedConfiguredProjects; foreach (var configuredProject in currentProjects) { // Inside a write lock, we should get back to the same thread. var project = await access.GetProjectAsync(configuredProject).ConfigureAwait(true); project.MarkDirty(); configuredProject.NotifyProjectChange(); } } }); } catch (OperationCanceledException) { // Project is already unloaded } }, unconfiguredProject: _projectServices.Project); return(VSConstants.S_OK); }
public async Task OpenProjectXmlForWriteAsync(UnconfiguredProject project, Action <ProjectRootElement> action, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(project, nameof(project)); Requires.NotNull(project, nameof(action)); using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync(cancellationToken)) { await access.CheckoutAsync(project.FullPath) .ConfigureAwait(true); ProjectRootElement rootElement = await access.GetProjectXmlAsync(project.FullPath, cancellationToken) .ConfigureAwait(true); // Deliberately not async to reduce the type of // code you can run while holding the lock. action(rootElement); } }
public static async Task InstallTargets(EnvDTE.Project envDteProject, IProjectLockService projectLockService, UnconfiguredProject unconfiguredProject, string toolsPath) { var logger = new TraceLogger(); try { if (projectLockService == null) { throw new ArgumentNullException("projectLockService"); } if (unconfiguredProject == null) { throw new ArgumentNullException("unconfiguredProject"); } using (var access = await projectLockService.WriteLockAsync()) { var configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync(); Project project = await access.GetProjectAsync(configuredProject); // If you're going to change the project in any way, // check it out from SCC first: await access.CheckoutAsync(configuredProject.UnconfiguredProject.FullPath); // install targets var installer = new InstallTargetsHelper(logger); installer.Install(project, toolsPath); // configureCallback(project); IProjectTreeService projectTreeService = configuredProject.Services.ExportProvider.GetExportedValue <IProjectTreeService>(); await projectTreeService.PublishLatestTreeAsync(); // envDteProject.Save(envDteProject.FullName); // save changes. //project.Save(project.FullPath); } } catch (AggregateException ex) { logger.LogError(ex.Message); foreach (var e in ex.InnerExceptions) { logger.LogError(e.Message); } throw; } catch (Exception e) { logger.LogError(e.Message); } }
public async Task ExecuteInWriteLock(Action <ProjectRootElement> action) { using (var access = await _projectLockService.WriteLockAsync()) { await access.CheckoutAsync(_unconfiguredProject.FullPath).ConfigureAwait(true); var msbuildProject = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath).ConfigureAwait(false); action.Invoke(msbuildProject); } }
public async Task SaveProjectXmlAsync(string toSave) { using (var access = await _projectLockService.WriteLockAsync()) { await access.CheckoutAsync(_unconfiguredProject.FullPath).ConfigureAwait(true); var encoding = await _unconfiguredProject.GetFileEncodingAsync().ConfigureAwait(false); _fileSystem.WriteAllText(_unconfiguredProject.FullPath, toSave, encoding); } }
public async Task SaveProjectXmlAsync(string toSave) { using (var access = await _projectLockService.WriteLockAsync()) { await access.CheckoutAsync(_unconfiguredProject.FullPath).ConfigureAwait(true); // We must clear the project dirty flag first. If it's dirty in memory, the ProjectReloadManager will detect that // the project is dirty and fail the reload, and discard the changes. var projectRoot = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath).ConfigureAwait(true); var stringWriter = new StringWriter(); // Calling save on the ProjectRootElement clears the dirty flag. However, we don't care about the result, to just // throw it into a stringwriter and discard. projectRoot.Save(stringWriter); var encoding = await _unconfiguredProject.GetFileEncodingAsync().ConfigureAwait(false); _fileSystem.WriteAllText(_unconfiguredProject.FullPath, toSave, encoding); } }
public void Add(string bstrImport) { if (!_importsList.IsPresent(bstrImport)) { _threadingService.ExecuteSynchronously(async() => { using (var access = await _lockService.WriteLockAsync()) { var project = await access.GetProjectAsync(ConfiguredProject).ConfigureAwait(true); await access.CheckoutAsync(project.Xml.ContainingProject.FullPath).ConfigureAwait(true); project.AddItem(importItemTypeName, bstrImport); } }); OnImportAdded(bstrImport); } else { throw new ArgumentException(string.Format("{0} - Namespace is already imported", bstrImport), nameof(bstrImport)); } }
public override async Task <string> OnSetPropertyValueAsync( string unevaluatedPropertyValue, IProjectProperties defaultProperties, IReadOnlyDictionary <string, string> dimensionalConditions = null) { await _projectLockService.WriteLockAsync(async access => { ProjectRootElement projectXml = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath); await _helper.SetPropertyAsync(unevaluatedPropertyValue, defaultProperties, projectXml); }); return(null); }
public override async Task <string> OnSetPropertyValueAsync( string unevaluatedPropertyValue, IProjectProperties defaultProperties, IReadOnlyDictionary <string, string> dimensionalConditions = null) { using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync()) { Microsoft.Build.Construction.ProjectRootElement projectXml = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath); await _helper.SetPropertyAsync(unevaluatedPropertyValue, defaultProperties, projectXml); } return(null); }
public override async Task <string> OnSetPropertyValueAsync( string unevaluatedPropertyValue, IProjectProperties defaultProperties, IReadOnlyDictionary <string, string> dimensionalConditions = null) { using (var access = await _projectLockService.WriteLockAsync()) { var projectXml = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath).ConfigureAwait(true); await _helper.SetPropertyAsync(unevaluatedPropertyValue, defaultProperties, projectXml).ConfigureAwait(true); } return(null); }
public async Task SaveProjectSettings() { await threadHandler.AsyncPump.RunAsync(async() => { using (var writeLock = await projectLockService.WriteLockAsync()) { await writeLock.CheckoutAsync(project.FullPath); var msBuildProject = await writeLock.GetProjectAsync(await project.GetSuggestedConfiguredProjectAsync()); msBuildProject.SetProperty(nameof(GitHub) + nameof(Branch), Branch); msBuildProject.SetProperty(nameof(VersionNamePattern), VersionNamePattern); msBuildProject.SetProperty(nameof(RepositoryName), RepositoryName); msBuildProject.Save(); } }); }
/// <summary> /// Called when a project.lock.json file changes. /// </summary> public int FilesChanged(uint cChanges, string[] rgpszFile, uint[] rggrfChange) { // Kick off the operation to notify the project change in a different thread irregardless of // the kind of change since we are interested in all changes. _projectServices.ThreadingService.Fork(async() => { using (var access = await _projectLockService.WriteLockAsync()) { // Inside a write lock, we should get back to the same thread. var project = await access.GetProjectAsync(_projectServices.ActiveConfiguredProject).ConfigureAwait(true); project.MarkDirty(); _projectServices.ActiveConfiguredProject.NotifyProjectChange(); } }, configuredProject: _projectServices.ActiveConfiguredProject); return(VSConstants.S_OK); }
public async Task RunLockedAsync(bool writeLock, Func <Task> task) { if (writeLock) { using (await _projectLockService.WriteLockAsync()) { await task().ConfigureAwait(true); } } else { using (await _projectLockService.ReadLockAsync()) { await task().ConfigureAwait(true); } } }
internal async Task Save() { await threadHandling.AsyncPump.RunAsync(async() => { using (var writeLock = await lockService.WriteLockAsync()) { await writeLock.CheckoutAsync(project.FullPath); var msBuildProject = await writeLock.GetProjectAsync(await project.GetSuggestedConfiguredProjectAsync()); msBuildProject.SetProperty("SelectedDeployTarget", SelectedTarget?.Name ?? ""); msBuildProject.Save(); } }); if (SelectedTarget != null) { await SelectedTarget.DeployTarget.SaveProjectSettings(); } }
private async Task ProjectRenamedOnWriter(object sender, ProjectRenamedEventArgs args) { var oldImportName = FileSystemMirroringProjectUtilities.GetInMemoryTargetsFileName(args.OldFullPath); var newImportName = FileSystemMirroringProjectUtilities.GetInMemoryTargetsFileName(args.NewFullPath); using (var access = await _projectLockService.WriteLockAsync()) { await access.CheckoutAsync(_unconfiguredProject.FullPath); var xml = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath); var import = xml.Imports.FirstOrDefault(i => i.Project.EqualsIgnoreCase(oldImportName)); if (import != null) { import.Project = newImportName; import.Condition = $"Exists('{newImportName}')"; await Project.UpdateFullPathAsync(access); } } }
public async Task <bool> ApplyAsync() { using (var projectWriteLock = await mProjectLockService.WriteLockAsync()) { var configuredProject = await mUnconfiguredProject.GetSuggestedConfiguredProjectAsync(); var project = await projectWriteLock.GetProjectAsync(configuredProject); await projectWriteLock.CheckoutAsync(mUnconfiguredProject.FullPath); foreach (var property in mBuildProperties.GetProperties()) { project.SetProperty(property.Key, property.Value); } project.Save(); } return(true); }
public async Task ApplyChangesAsync() { var xConfiguredProject = await mUnconfiguredProject.GetSuggestedConfiguredProjectAsync(); using (var xAccess = await mProjectLockService.WriteLockAsync()) { var xProject = await xAccess.GetProjectAsync(xConfiguredProject); await xAccess.CheckoutAsync(xConfiguredProject.UnconfiguredProject.FullPath); foreach (var xProperty in Properties) { if (PropertyChanged(xProperty)) { xProject.SetProperty(xProperty.Key, xProperty.Value); } } xProject.Save(); } }
private static async ATask SetVCProjectsConfigurationProperties12(DTEProject project, string configurationName, string platformName) { // Inspired from Nuget: https://github.com/Haacked/NuGet/blob/master/src/VisualStudio12/ProjectHelper.cs IVsBrowseObjectContext context = project.Object as IVsBrowseObjectContext; UnconfiguredProject unconfiguredProject = context.UnconfiguredProject; IProjectLockService service = unconfiguredProject.ProjectService.Services.ProjectLockService; using (ProjectWriteLockReleaser releaser = await service.WriteLockAsync()) { ProjectCollection collection = releaser.ProjectCollection; ConfigureCollection(collection, configurationName, platformName); _VCProjectCollectionLoaded = true; // The following was present in the NuGet code: it seesms unecessary, // as the lock it's release anyway after the using block (check // service.IsAnyLockHeld). Also it seemed to cause a deadlock sometimes // when switching solution configuration //await releaser.ReleaseAsync(); } }