/// <summary> /// Constructor for IVSOutput2 implementation /// </summary> /// <param name="projectManager">Project that produce this output</param> /// <param name="outputAssembly">MSBuild generated item corresponding to the output assembly (by default, these would be of type MainAssembly</param> public Output(ProjectNode projectManager, ProjectElement outputAssembly) { if(projectManager == null) throw new ArgumentNullException("projectManager"); if(outputAssembly == null) throw new ArgumentNullException("outputAssembly"); project = projectManager; output = outputAssembly; }
/// <summary> /// This will clone a template project file and add it as a /// subproject to our hierarchy. /// If you want to create a project for which there exist a /// vstemplate, consider using RunVsTemplateWizard instead. /// </summary> protected internal virtual NestedProjectNode AddNestedProjectFromTemplate(ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { throw new ArgumentNullException("element"); } string destination = elementToUse.GetFullPathForElement(); string template = this.GetProjectTemplatePath(elementToUse); return this.AddNestedProjectFromTemplate(template, Path.GetDirectoryName(destination), Path.GetFileName(destination), elementToUse, creationFlags); }
protected internal void RunVsTemplateWizard(ProjectElement element, bool silent) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { throw new ArgumentNullException("element"); } this.nestedProjectElement = elementToUse; Automation.OAProject oaProject = GetAutomationObject() as Automation.OAProject; if(oaProject == null || oaProject.ProjectItems == null) throw new System.InvalidOperationException(SR.GetString(SR.InvalidAutomationObject, CultureInfo.CurrentUICulture)); Debug.Assert(oaProject.Object != null, "The project automation object should have set the Object to the SolutionFolder"); Automation.OASolutionFolder<ProjectContainerNode> folder = oaProject.Object as Automation.OASolutionFolder<ProjectContainerNode>; // Prepare the parameters to pass to RunWizardFile string destination = elementToUse.GetFullPathForElement(); string template = this.GetProjectTemplatePath(elementToUse); object[] wizParams = new object[7]; wizParams[0] = EnvDTE.Constants.vsWizardAddSubProject; wizParams[1] = Path.GetFileNameWithoutExtension(destination); wizParams[2] = oaProject.ProjectItems; wizParams[3] = Path.GetDirectoryName(destination); wizParams[4] = Path.GetFileNameWithoutExtension(destination); wizParams[5] = Path.GetDirectoryName(folder.DTE.FullName); //VS install dir wizParams[6] = silent; IVsDetermineWizardTrust wizardTrust = this.GetService(typeof(SVsDetermineWizardTrust)) as IVsDetermineWizardTrust; if(wizardTrust != null) { Guid guidProjectAdding = Guid.Empty; // In case of a project template an empty guid should be added as the guid parameter. See env\msenv\core\newtree.h IsTrustedTemplate method definition. ErrorHandler.ThrowOnFailure(wizardTrust.OnWizardInitiated(template, ref guidProjectAdding)); } try { // Make the call to execute the wizard. This should cause AddNestedProjectFromTemplate to be // called back with the correct set of parameters. EnvDTE.IVsExtensibility extensibilityService = (EnvDTE.IVsExtensibility)GetService(typeof(EnvDTE.IVsExtensibility)); EnvDTE.wizardResult result = extensibilityService.RunWizardFile(template, 0, ref wizParams); if(result == EnvDTE.wizardResult.wizardResultFailure) throw new COMException(); } finally { if(wizardTrust != null) { ErrorHandler.ThrowOnFailure(wizardTrust.OnWizardCompleted()); } } }
/// <summary> /// Add an existing project as a nested node of our hierarchy. /// This is used while loading the project and can also be used /// to add an existing project to our hierarchy. /// </summary> protected internal virtual NestedProjectNode AddExistingNestedProject(ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { throw new ArgumentNullException("element"); } string filename = elementToUse.GetFullPathForElement(); // Delegate to AddNestedProjectFromTemplate. Because we pass flags that specify open project rather then clone, this will works. Debug.Assert((creationFlags & __VSCREATEPROJFLAGS.CPF_OPENFILE) == __VSCREATEPROJFLAGS.CPF_OPENFILE, "__VSCREATEPROJFLAGS.CPF_OPENFILE should have been specified, did you mean to call AddNestedProjectFromTemplate?"); return AddNestedProjectFromTemplate(filename, Path.GetDirectoryName(filename), Path.GetFileName(filename), elementToUse, creationFlags); }
protected virtual ReferenceNode CreateReferenceNode(string referenceType, ProjectElement element) { ReferenceNode node = null; if(referenceType == ProjectFileConstants.COMReference) { node = this.CreateComReferenceNode(element); } else if(referenceType == ProjectFileConstants.Reference) { node = this.CreateAssemblyReferenceNode(element); } else if(referenceType == ProjectFileConstants.ProjectReference) { node = this.CreateProjectReferenceNode(element); } return node; }
protected virtual FolderNode VerifySubFolderExists(string path, HierarchyNode parent) { FolderNode folderNode = null; uint uiItemId; Url url = new Url(this.BaseURI, path); string strFullPath = url.AbsoluteUrl; // Folders end in our storage with a backslash, so add one... ErrorHandler.ThrowOnFailure(this.ParseCanonicalName(strFullPath, out uiItemId)); if(uiItemId != 0) { Debug.Assert(this.NodeFromItemId(uiItemId) is FolderNode, "Not a FolderNode"); folderNode = (FolderNode)this.NodeFromItemId(uiItemId); } if(folderNode == null) { // folder does not exist yet... // We could be in the process of loading so see if msbuild knows about it MSBuild.BuildItemGroup folders = buildProject.GetEvaluatedItemsByName(ProjectFileConstants.Folder); ProjectElement item = null; foreach(MSBuild.BuildItem folder in folders) { if(String.Compare(folder.FinalItemSpec.TrimEnd('\\'), path.TrimEnd('\\'), StringComparison.OrdinalIgnoreCase) == 0) { item = new ProjectElement(this, folder, false); break; } } // If MSBuild did not know about it, create a new one if(item == null) item = this.AddFolderToMsBuild(path); folderNode = this.CreateFolderNode(path, item); parent.AddChild(folderNode); } return folderNode; }
/// <summary> /// Create a file node based on an msbuild item. /// </summary> /// <param name="item">msbuild item</param> /// <returns>FileNode added</returns> public virtual FileNode CreateFileNode(ProjectElement item) { return new FileNode(this, item); }
/// <summary> /// Based on the Template and TypeGuid properties of the /// element, generate the full template path. /// /// TypeGuid should be the Guid of a registered project factory. /// Template can be a full path, a project template (for projects /// that support VsTemplates) or a relative path (for other projects). /// </summary> protected virtual string GetProjectTemplatePath(ProjectElement element) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { throw new ArgumentNullException("element"); } string templateFile = elementToUse.GetMetadata(ProjectFileConstants.Template); Debug.Assert(!String.IsNullOrEmpty(templateFile), "No template file has been specified in the template attribute in the project file"); string fullPath = templateFile; if(!Path.IsPathRooted(templateFile)) { RegisteredProjectType registeredProjectType = this.GetRegisteredProject(elementToUse); // This is not a full path Debug.Assert(registeredProjectType != null && (!String.IsNullOrEmpty(registeredProjectType.DefaultProjectExtensionValue) || !String.IsNullOrEmpty(registeredProjectType.WizardTemplatesDirValue)), " Registered wizard directory value not set in the registry."); // See if this specify a VsTemplate file fullPath = registeredProjectType.GetVsTemplateFile(templateFile); if(String.IsNullOrEmpty(fullPath)) { // Default to using the WizardTemplateDir to calculate the absolute path fullPath = Path.Combine(registeredProjectType.WizardTemplatesDirValue, templateFile); } } return fullPath; }
/// <summary> /// Constructor for the FileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> public FileNode(ProjectNode root, ProjectElement element) : base(root, element) { if(this.ProjectMgr.NodeHasDesigner(this.ItemNode.GetMetadata(ProjectFileConstants.Include))) { this.HasDesigner = true; } }
public ProjectReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.referencedProjectRelativePath = this.ItemNode.GetMetadata(ProjectFileConstants.Include); Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectRelativePath), "Could not retrive referenced project path form project file"); string guidString = this.ItemNode.GetMetadata(ProjectFileConstants.Project); // Continue even if project setttings cannot be read. try { this.referencedProjectGuid = new Guid(guidString); this.buildDependency = new BuildDependency(this.ProjectMgr, this.referencedProjectGuid); this.ProjectMgr.AddBuildDependency(this.buildDependency); } finally { Debug.Assert(this.referencedProjectGuid != Guid.Empty, "Could not retrive referenced project guidproject file"); this.referencedProjectName = this.ItemNode.GetMetadata(ProjectFileConstants.Name); Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectName), "Could not retrive referenced project name form project file"); } Uri uri = new Uri(this.ProjectMgr.BaseURI.Uri, this.referencedProjectRelativePath); if(uri != null) { this.referencedProjectFullPath = Microsoft.VisualStudio.Shell.Url.Unescape(uri.LocalPath, true); } }
/// <summary> /// Constructor for the ReferenceNode /// </summary> public AssemblyReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.GetPathNameFromProjectFile(); this.InitializeFileChangeEvents(); string include = this.ItemNode.GetMetadata(ProjectFileConstants.Include); this.CreateFromAssemblyName(new System.Reflection.AssemblyName(include)); }
/// <summary> /// Creates a com reference node from the project element. /// </summary> protected virtual ComReferenceNode CreateComReferenceNode(ProjectElement reference) { return new ComReferenceNode(this.ProjectMgr, reference); }
/// <summary> /// Creates an assembly refernce node from a project element. /// </summary> protected virtual AssemblyReferenceNode CreateAssemblyReferenceNode(ProjectElement element) { AssemblyReferenceNode node = null; try { node = new AssemblyReferenceNode(this.ProjectMgr, element); } catch(ArgumentNullException e) { Trace.WriteLine("Exception : " + e.Message); } catch(FileNotFoundException e) { Trace.WriteLine("Exception : " + e.Message); } catch(BadImageFormatException e) { Trace.WriteLine("Exception : " + e.Message); } catch(FileLoadException e) { Trace.WriteLine("Exception : " + e.Message); } catch(System.Security.SecurityException e) { Trace.WriteLine("Exception : " + e.Message); } return node; }
/// <summary> /// Creates a project reference node given an existing project element. /// </summary> protected virtual ProjectReferenceNode CreateProjectReferenceNode(ProjectElement element) { return new ProjectReferenceNode(this.ProjectMgr, element); }
/// <summary> /// This can be called directly or through RunVsTemplateWizard. /// This will clone a template project file and add it as a /// subproject to our hierarchy. /// If you want to create a project for which there exist a /// vstemplate, consider using RunVsTemplateWizard instead. /// </summary> protected internal virtual NestedProjectNode AddNestedProjectFromTemplate(string fileName, string destination, string projectName, ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { // If this is project creation and the template specified a subproject in its project file, this.nestedProjectElement will be used ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { // If this is null, this means MSBuild does not know anything about our subproject so add an MSBuild item for it elementToUse = new ProjectElement(this, fileName, ProjectFileConstants.SubProject); } NestedProjectNode node = CreateNestedProjectNode(elementToUse); node.Init(fileName, destination, projectName, creationFlags); // In case that with did not have an existing element, or the nestedProjectelement was null // and since Init computes the final path, set the MSBuild item to that path if(this.nestedProjectElement == null) { string relativePath = node.Url; if(Path.IsPathRooted(relativePath)) { relativePath = this.ProjectFolder; if(!relativePath.EndsWith("/\\", StringComparison.Ordinal)) { relativePath += Path.DirectorySeparatorChar; } relativePath = new Url(relativePath).MakeRelative(new Url(node.Url)); } elementToUse.Rename(relativePath); } this.AddChild(node); return node; }
/// <summary> /// constructor for the ReferenceNode /// </summary> protected ReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.ExcludeNodeFromScc = true; }
/// <summary> /// Override this method if you want to provide your own type of nodes. /// This would be the case if you derive a class from NestedProjectNode /// </summary> protected virtual NestedProjectNode CreateNestedProjectNode(ProjectElement element) { return new NestedProjectNode(this, element); }
/// <summary> /// Constructor for the DependentFileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> public DependentFileNode(ProjectNode root, ProjectElement element) : base(root, element) { this.HasParentNodeNameRelation = false; }
/// <summary> /// Get information from the registry based for the project /// factory corresponding to the TypeGuid of the element /// </summary> private RegisteredProjectType GetRegisteredProject(ProjectElement element) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if(elementToUse == null) { throw new ArgumentNullException("element"); } // Get the project type guid from project elementToUse string typeGuidString = elementToUse.GetMetadataAndThrow(ProjectFileConstants.TypeGuid, new Exception()); Guid projectFactoryGuid = new Guid(typeGuidString); EnvDTE.DTE dte = this.ProjectMgr.Site.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; Debug.Assert(dte != null, "Could not get the automation object from the services exposed by this project"); if(dte == null) throw new InvalidOperationException(); RegisteredProjectType registeredProjectType = RegisteredProjectType.CreateRegisteredProjectType(projectFactoryGuid); Debug.Assert(registeredProjectType != null, "Could not read the registry setting associated to this project."); if(registeredProjectType == null) { throw new InvalidOperationException(); } return registeredProjectType; }
public NestedProjectNode(ProjectNode root, ProjectElement element) : base(root, element) { this.IsExpanded = true; }
/// <summary> /// Create dependent file node based on an msbuild item /// </summary> /// <param name="item">msbuild item</param> /// <returns>dependent file node</returns> public virtual DependentFileNode CreateDependentFileNode(ProjectElement item) { return new DependentFileNode(this, item); }
/// <summary> /// This is used when loading the project to loop through all the items /// and for each SubProject it finds, it create the project and a node /// in our Hierarchy to hold the project. /// </summary> internal protected void CreateNestedProjectNodes() { // 1. Create a ProjectElement with the found item and then Instantiate a new Nested project with this ProjectElement. // 2. Link into the hierarchy. // Read subprojects from from msbuildmodel __VSCREATEPROJFLAGS creationFlags = __VSCREATEPROJFLAGS.CPF_NOTINSLNEXPLR | __VSCREATEPROJFLAGS.CPF_SILENT; if(this.IsNewProject) { creationFlags |= __VSCREATEPROJFLAGS.CPF_CLONEFILE; } else { creationFlags |= __VSCREATEPROJFLAGS.CPF_OPENFILE; } foreach(MSBuild.BuildItem item in this.BuildProject.EvaluatedItems) { if(String.Compare(item.Name, ProjectFileConstants.SubProject, StringComparison.OrdinalIgnoreCase) == 0) { this.nestedProjectElement = new ProjectElement(this, item, false); if(!this.IsNewProject) { AddExistingNestedProject(null, creationFlags); } else { // If we are creating the subproject from a vstemplate/vsz file bool isVsTemplate = Utilities.IsTemplateFile(GetProjectTemplatePath(null)); if(isVsTemplate) { RunVsTemplateWizard(null, true); } else { // We are cloning the specified project file AddNestedProjectFromTemplate(null, creationFlags); } } } } this.nestedProjectElement = null; }
/// <summary> /// To support virtual folders, override this method to return your own folder nodes /// </summary> /// <param name="path">Path to store for this folder</param> /// <param name="element">Element corresponding to the folder</param> /// <returns>A FolderNode that can then be added to the hierarchy</returns> protected internal virtual FolderNode CreateFolderNode(string path, ProjectElement element) { FolderNode folderNode = new FolderNode(this, path, element); return folderNode; }
/// <summary> /// Adds references to this container from a MSBuild project. /// </summary> public void LoadReferencesFromBuildProject(MSBuild.Project buildProject) { foreach(string referenceType in SupportedReferenceTypes) { MSBuild.BuildItemGroup refererncesGroup = buildProject.GetEvaluatedItemsByName(referenceType); bool isAssemblyReference = referenceType == ProjectFileConstants.Reference; // If the project was loaded for browsing we should still create the nodes but as not resolved. if(this.ProjectMgr.HasPassedSecurityChecks && isAssemblyReference && this.ProjectMgr.Build(MsBuildTarget.ResolveAssemblyReferences) != MSBuildResult.Successful) { continue; } foreach(MSBuild.BuildItem item in refererncesGroup) { ProjectElement element = new ProjectElement(this.ProjectMgr, item, false); ReferenceNode node = CreateReferenceNode(referenceType, element); if(node != null) { // Make sure that we do not want to add the item twice to the ui hierarchy // We are using here the UI representation of the Node namely the Caption to find that out, in order to // avoid different representation problems. // Example :<Reference Include="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> // <Reference Include="EnvDTE80" /> bool found = false; for(HierarchyNode n = this.FirstChild; n != null && !found; n = n.NextSibling) { if(String.Compare(n.Caption, node.Caption, StringComparison.OrdinalIgnoreCase) == 0) { found = true; } } if(!found) { this.AddChild(node); } } } } }