PageRenderTime 57ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 1ms

/source2/VSIP/MPF/10.0_original/Src/CSharp/ProjectNode.cs

https://bitbucket.org/mvptracker/cosmos
C# | 6517 lines | 5727 code | 314 blank | 476 comment | 221 complexity | 39e8ced0a98a2f0a74571103d48de716 MD5 | raw file
Possible License(s): BSD-2-Clause

Large files files are truncated, but you can click here to view the full file

  1. /***************************************************************************
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. This code is licensed under the Visual Studio SDK license terms.
  4. THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  5. ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  6. IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  7. PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  8. ***************************************************************************/
  9. using System;
  10. using System.CodeDom.Compiler;
  11. using System.Collections.Generic;
  12. using System.Collections.Specialized;
  13. using System.Diagnostics;
  14. using System.Diagnostics.CodeAnalysis;
  15. using System.Globalization;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Runtime.InteropServices;
  19. using System.Runtime.Versioning;
  20. using System.Text;
  21. using System.Xml;
  22. using EnvDTE;
  23. using Microsoft.Build.BackEnd;
  24. using Microsoft.Build.Evaluation;
  25. using Microsoft.Build.Execution;
  26. using Microsoft.VisualStudio.OLE.Interop;
  27. using Microsoft.VisualStudio.Shell;
  28. using Microsoft.VisualStudio.Shell.Interop;
  29. using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
  30. using IServiceProvider = System.IServiceProvider;
  31. using MSBuild = Microsoft.Build.Evaluation;
  32. using MSBuildConstruction = Microsoft.Build.Construction;
  33. using MSBuildExecution = Microsoft.Build.Execution;
  34. using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants;
  35. using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
  36. using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
  37. namespace Microsoft.VisualStudio.Project
  38. {
  39. /// <summary>
  40. /// Manages the persistent state of the project (References, options, files, etc.) and deals with user interaction via a GUI in the form a hierarchy.
  41. /// </summary>
  42. [CLSCompliant(false)]
  43. [ComVisible(true)]
  44. public abstract partial class ProjectNode : HierarchyNode,
  45. IVsGetCfgProvider,
  46. IVsProject3,
  47. IVsAggregatableProject,
  48. IVsProjectFlavorCfgProvider,
  49. IPersistFileFormat,
  50. IVsProjectBuildSystem,
  51. IVsBuildPropertyStorage,
  52. IVsComponentUser,
  53. IVsDependencyProvider,
  54. IVsSccProject2,
  55. IBuildDependencyUpdate,
  56. IProjectEventsListener,
  57. IProjectEventsProvider,
  58. IReferenceContainerProvider,
  59. IVsProjectSpecialFiles,
  60. IVsProjectUpgrade,
  61. IVsDesignTimeAssemblyResolution,
  62. IVsSetTargetFrameworkWorkerCallback
  63. {
  64. #region nested types
  65. public enum ImageName
  66. {
  67. OfflineWebApp = 0,
  68. WebReferencesFolder = 1,
  69. OpenReferenceFolder = 2,
  70. ReferenceFolder = 3,
  71. Reference = 4,
  72. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SDL")]
  73. SDLWebReference = 5,
  74. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DISCO")]
  75. DISCOWebReference = 6,
  76. Folder = 7,
  77. OpenFolder = 8,
  78. ExcludedFolder = 9,
  79. OpenExcludedFolder = 10,
  80. ExcludedFile = 11,
  81. DependentFile = 12,
  82. MissingFile = 13,
  83. WindowsForm = 14,
  84. WindowsUserControl = 15,
  85. WindowsComponent = 16,
  86. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  87. XMLSchema = 17,
  88. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  89. XMLFile = 18,
  90. WebForm = 19,
  91. WebService = 20,
  92. WebUserControl = 21,
  93. WebCustomUserControl = 22,
  94. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ASP")]
  95. ASPPage = 23,
  96. GlobalApplicationClass = 24,
  97. WebConfig = 25,
  98. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "HTML")]
  99. HTMLPage = 26,
  100. StyleSheet = 27,
  101. ScriptFile = 28,
  102. TextFile = 29,
  103. SettingsFile = 30,
  104. Resources = 31,
  105. Bitmap = 32,
  106. Icon = 33,
  107. Image = 34,
  108. ImageMap = 35,
  109. XWorld = 36,
  110. Audio = 37,
  111. Video = 38,
  112. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "CAB")]
  113. CAB = 39,
  114. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "JAR")]
  115. JAR = 40,
  116. DataEnvironment = 41,
  117. PreviewFile = 42,
  118. DanglingReference = 43,
  119. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XSLT")]
  120. XSLTFile = 44,
  121. Cursor = 45,
  122. AppDesignerFolder = 46,
  123. Data = 47,
  124. Application = 48,
  125. DataSet = 49,
  126. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "PFX")]
  127. PFX = 50,
  128. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SNK")]
  129. SNK = 51,
  130. ImageLast = 51
  131. }
  132. /// <summary>
  133. /// Flags for specifying which events to stop triggering.
  134. /// </summary>
  135. [Flags]
  136. internal enum EventTriggering
  137. {
  138. TriggerAll = 0,
  139. DoNotTriggerHierarchyEvents = 1,
  140. DoNotTriggerTrackerEvents = 2
  141. }
  142. #endregion
  143. #region constants
  144. /// <summary>
  145. /// The user file extension.
  146. /// </summary>
  147. internal const string PerUserFileExtension = ".user";
  148. private Guid GUID_MruPage = new Guid("{19B97F03-9594-4c1c-BE28-25FF030113B3}");
  149. /// <summary>
  150. /// The VS command that allows projects to open Windows Explorer to the project directory.
  151. /// </summary>
  152. private const VsCommands2K ExploreFolderInWindowsCommand = (VsCommands2K)1635;
  153. #endregion
  154. #region fields
  155. private static readonly FrameworkName DefaultTargetFrameworkMoniker = new FrameworkName(".NETFramework", new Version(4, 0));
  156. private static Guid addComponentLastActiveTab = VSConstants.GUID_SolutionPage;
  157. private static uint addComponentDialogSizeX = 0;
  158. private static uint addComponentDialogSizeY = 0;
  159. /// <summary>
  160. /// List of output groups names and their associated target
  161. /// </summary>
  162. private static KeyValuePair<string, string>[] outputGroupNames =
  163. { // Name Target (MSBuild)
  164. new KeyValuePair<string, string>("Built", "BuiltProjectOutputGroup"),
  165. new KeyValuePair<string, string>("ContentFiles", "ContentFilesProjectOutputGroup"),
  166. new KeyValuePair<string, string>("LocalizedResourceDlls", "SatelliteDllsProjectOutputGroup"),
  167. new KeyValuePair<string, string>("Documentation", "DocumentationProjectOutputGroup"),
  168. new KeyValuePair<string, string>("Symbols", "DebugSymbolsProjectOutputGroup"),
  169. new KeyValuePair<string, string>("SourceFiles", "SourceFilesProjectOutputGroup"),
  170. new KeyValuePair<string, string>("XmlSerializer", "SGenFilesOutputGroup"),
  171. };
  172. /// <summary>A project will only try to build if it can obtain a lock on this object</summary>
  173. private volatile static object BuildLock = new object();
  174. /// <summary>Maps integer ids to project item instances</summary>
  175. private EventSinkCollection itemIdMap = new EventSinkCollection();
  176. /// <summary>A service provider call back object provided by the IDE hosting the project manager</summary>
  177. private ServiceProvider site;
  178. public static ServiceProvider ServiceProvider { get; set; }
  179. private TrackDocumentsHelper tracker;
  180. /// <summary>
  181. /// A cached copy of project options.
  182. /// </summary>
  183. private ProjectOptions options;
  184. /// <summary>
  185. /// This property returns the time of the last change made to this project.
  186. /// It is not the time of the last change on the project file, but actually of
  187. /// the in memory project settings. In other words, it is the last time that
  188. /// SetProjectDirty was called.
  189. /// </summary>
  190. private DateTime lastModifiedTime;
  191. /// <summary>
  192. /// MSBuild engine we are going to use
  193. /// </summary>
  194. private MSBuild.ProjectCollection buildEngine;
  195. private Microsoft.Build.Utilities.Logger buildLogger;
  196. private bool useProvidedLogger;
  197. private MSBuild.Project buildProject;
  198. private MSBuildExecution.ProjectInstance currentConfig;
  199. private DesignTimeAssemblyResolution designTimeAssemblyResolution;
  200. private ConfigProvider configProvider;
  201. private TaskProvider taskProvider;
  202. private string filename;
  203. private Microsoft.VisualStudio.Shell.Url baseUri;
  204. private bool isDirty;
  205. private bool isNewProject;
  206. private bool projectOpened;
  207. private bool buildIsPrepared;
  208. private ImageHandler imageHandler;
  209. private string errorString;
  210. private string warningString;
  211. private Guid projectIdGuid;
  212. private bool isClosed;
  213. private EventTriggering eventTriggeringFlag = EventTriggering.TriggerAll;
  214. private bool invokeMSBuildWhenResumed;
  215. private uint suspendMSBuildCounter;
  216. private bool canFileNodesHaveChilds;
  217. private bool isProjectEventsListener = true;
  218. /// <summary>
  219. /// The build dependency list passed to IVsDependencyProvider::EnumDependencies
  220. /// </summary>
  221. private List<IVsBuildDependency> buildDependencyList = new List<IVsBuildDependency>();
  222. /// <summary>
  223. /// Defines if Project System supports Project Designer
  224. /// </summary>
  225. private bool supportsProjectDesigner;
  226. private bool showProjectInSolutionPage = true;
  227. private bool buildInProcess;
  228. /// <summary>
  229. /// Field for determining whether sourcecontrol should be disabled.
  230. /// </summary>
  231. private bool disableScc;
  232. private string sccProjectName;
  233. private string sccLocalPath;
  234. private string sccAuxPath;
  235. private string sccProvider;
  236. /// <summary>
  237. /// Flag for controling how many times we register with the Scc manager.
  238. /// </summary>
  239. private bool isRegisteredWithScc;
  240. /// <summary>
  241. /// Flag for controling query edit should communicate with the scc manager.
  242. /// </summary>
  243. private bool disableQueryEdit;
  244. /// <summary>
  245. /// Control if command with potential destructive behavior such as delete should
  246. /// be enabled for nodes of this project.
  247. /// </summary>
  248. private bool canProjectDeleteItems;
  249. /// <summary>
  250. /// Token processor used by the project sample.
  251. /// </summary>
  252. private TokenProcessor tokenProcessor;
  253. /// <summary>
  254. /// Member to store output base relative path. Used by OutputBaseRelativePath property
  255. /// </summary>
  256. private string outputBaseRelativePath = "bin";
  257. private IProjectEvents projectEventsProvider;
  258. /// <summary>
  259. /// Used for flavoring to hold the XML fragments
  260. /// </summary>
  261. private XmlDocument xmlFragments;
  262. /// <summary>
  263. /// Used to map types to CATID. This provide a generic way for us to do this
  264. /// and make it simpler for a project to provide it's CATIDs for the different type of objects
  265. /// for which it wants to support extensibility. This also enables us to have multiple
  266. /// type mapping to the same CATID if we choose to.
  267. /// </summary>
  268. private Dictionary<Type, Guid> catidMapping = new Dictionary<Type, Guid>();
  269. /// <summary>
  270. /// The internal package implementation.
  271. /// </summary>
  272. private ProjectPackage package;
  273. // Has the object been disposed.
  274. private bool isDisposed;
  275. #endregion
  276. #region abstract properties
  277. /// <summary>
  278. /// This Guid must match the Guid you registered under
  279. /// HKLM\Software\Microsoft\VisualStudio\%version%\Projects.
  280. /// Among other things, the Project framework uses this
  281. /// guid to find your project and item templates.
  282. /// </summary>
  283. public abstract Guid ProjectGuid
  284. {
  285. get;
  286. }
  287. /// <summary>
  288. /// Returns a caption for VSHPROPID_TypeName.
  289. /// </summary>
  290. /// <returns></returns>
  291. public abstract string ProjectType
  292. {
  293. get;
  294. }
  295. #endregion
  296. #region virtual properties
  297. /// <summary>
  298. /// This is the project instance guid that is peristed in the project file
  299. /// </summary>
  300. [System.ComponentModel.BrowsableAttribute(false)]
  301. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")]
  302. public virtual Guid ProjectIDGuid
  303. {
  304. get
  305. {
  306. return this.projectIdGuid;
  307. }
  308. set
  309. {
  310. if (this.projectIdGuid != value)
  311. {
  312. this.projectIdGuid = value;
  313. if (this.buildProject != null)
  314. {
  315. this.SetProjectProperty("ProjectGuid", this.projectIdGuid.ToString("B"));
  316. }
  317. }
  318. }
  319. }
  320. #endregion
  321. #region properties
  322. #region overridden properties
  323. public override int MenuCommandId
  324. {
  325. get
  326. {
  327. return VsMenus.IDM_VS_CTXT_PROJNODE;
  328. }
  329. }
  330. public override string Url
  331. {
  332. get
  333. {
  334. return this.GetMkDocument();
  335. }
  336. }
  337. public override string Caption
  338. {
  339. get
  340. {
  341. // Default to file name
  342. string caption = this.buildProject.FullPath;
  343. if (String.IsNullOrEmpty(caption))
  344. {
  345. if (this.buildProject.GetProperty(ProjectFileConstants.Name) != null)
  346. {
  347. caption = this.buildProject.GetProperty(ProjectFileConstants.Name).EvaluatedValue;
  348. if (caption == null || caption.Length == 0)
  349. {
  350. caption = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
  351. }
  352. }
  353. }
  354. else
  355. {
  356. caption = Path.GetFileNameWithoutExtension(caption);
  357. }
  358. return caption;
  359. }
  360. }
  361. public override Guid ItemTypeGuid
  362. {
  363. get
  364. {
  365. return this.ProjectGuid;
  366. }
  367. }
  368. public override int ImageIndex
  369. {
  370. get
  371. {
  372. return (int)ProjectNode.ImageName.Application;
  373. }
  374. }
  375. #endregion
  376. #region virtual properties
  377. public virtual string ErrorString
  378. {
  379. get
  380. {
  381. if (this.errorString == null)
  382. {
  383. this.errorString = SR.GetString(SR.Error, CultureInfo.CurrentUICulture);
  384. }
  385. return this.errorString;
  386. }
  387. }
  388. public virtual string WarningString
  389. {
  390. get
  391. {
  392. if (this.warningString == null)
  393. {
  394. this.warningString = SR.GetString(SR.Warning, CultureInfo.CurrentUICulture);
  395. }
  396. return this.warningString;
  397. }
  398. }
  399. /// <summary>
  400. /// The target name that will be used for evaluating the project file (i.e., pseudo-builds).
  401. /// This target is used to trigger a build with when the project system changes.
  402. /// Example: The language projrcts are triggering a build with the Compile target whenever
  403. /// the project system changes.
  404. /// </summary>
  405. [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ReEvaluate")]
  406. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Re")]
  407. protected internal virtual string ReEvaluateProjectFileTargetName
  408. {
  409. get
  410. {
  411. return null;
  412. }
  413. }
  414. /// <summary>
  415. /// This is the object that will be returned by EnvDTE.Project.Object for this project
  416. /// </summary>
  417. protected internal virtual object ProjectObject
  418. {
  419. get
  420. {
  421. return null;
  422. }
  423. }
  424. /// <summary>
  425. /// Override this property to specify when the project file is dirty.
  426. /// </summary>
  427. protected virtual bool IsProjectFileDirty
  428. {
  429. get
  430. {
  431. string document = this.GetMkDocument();
  432. if (String.IsNullOrEmpty(document))
  433. {
  434. return this.isDirty;
  435. }
  436. return (this.isDirty || !File.Exists(document));
  437. }
  438. }
  439. /// <summary>
  440. /// True if the project uses the Project Designer Editor instead of the property page frame to edit project properties.
  441. /// </summary>
  442. protected virtual bool SupportsProjectDesigner
  443. {
  444. get
  445. {
  446. return this.supportsProjectDesigner;
  447. }
  448. set
  449. {
  450. this.supportsProjectDesigner = value;
  451. }
  452. }
  453. protected virtual Guid ProjectDesignerEditor
  454. {
  455. get
  456. {
  457. return VSConstants.GUID_ProjectDesignerEditor;
  458. }
  459. }
  460. /// <summary>
  461. /// Defines the flag that supports the VSHPROPID.ShowProjInSolutionPage
  462. /// </summary>
  463. protected virtual bool ShowProjectInSolutionPage
  464. {
  465. get
  466. {
  467. return this.showProjectInSolutionPage;
  468. }
  469. set
  470. {
  471. this.showProjectInSolutionPage = value;
  472. }
  473. }
  474. #endregion
  475. /// <summary>
  476. /// Gets or sets the ability of a project filenode to have child nodes (sub items).
  477. /// Example would be C#/VB forms having resx and designer files.
  478. /// </summary>
  479. protected internal bool CanFileNodesHaveChilds
  480. {
  481. get
  482. {
  483. return canFileNodesHaveChilds;
  484. }
  485. set
  486. {
  487. canFileNodesHaveChilds = value;
  488. }
  489. }
  490. /// <summary>
  491. /// Get and set the Token processor.
  492. /// </summary>
  493. public TokenProcessor FileTemplateProcessor
  494. {
  495. get
  496. {
  497. if (tokenProcessor == null)
  498. tokenProcessor = new TokenProcessor();
  499. return tokenProcessor;
  500. }
  501. set
  502. {
  503. tokenProcessor = value;
  504. }
  505. }
  506. /// <summary>
  507. /// Gets a service provider object provided by the IDE hosting the project
  508. /// </summary>
  509. [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
  510. public IServiceProvider Site
  511. {
  512. get
  513. {
  514. return this.site;
  515. }
  516. }
  517. /// <summary>
  518. /// Gets an ImageHandler for the project node.
  519. /// </summary>
  520. public ImageHandler ImageHandler
  521. {
  522. get
  523. {
  524. if (null == imageHandler)
  525. {
  526. imageHandler = new ImageHandler(typeof(ProjectNode).Assembly.GetManifestResourceStream("Microsoft.VisualStudio.Project.Resources.imagelis.bmp"));
  527. }
  528. return imageHandler;
  529. }
  530. }
  531. /// <summary>
  532. /// This property returns the time of the last change made to this project.
  533. /// It is not the time of the last change on the project file, but actually of
  534. /// the in memory project settings. In other words, it is the last time that
  535. /// SetProjectDirty was called.
  536. /// </summary>
  537. public DateTime LastModifiedTime
  538. {
  539. get
  540. {
  541. return this.lastModifiedTime;
  542. }
  543. }
  544. /// <summary>
  545. /// Determines whether this project is a new project.
  546. /// </summary>
  547. public bool IsNewProject
  548. {
  549. get
  550. {
  551. return this.isNewProject;
  552. }
  553. }
  554. /// <summary>
  555. /// Gets the path to the folder containing the project.
  556. /// </summary>
  557. public string ProjectFolder
  558. {
  559. get
  560. {
  561. return Path.GetDirectoryName(this.filename);
  562. }
  563. }
  564. /// <summary>
  565. /// Gets or sets the project filename.
  566. /// </summary>
  567. public string ProjectFile
  568. {
  569. get
  570. {
  571. return Path.GetFileName(this.filename);
  572. }
  573. set
  574. {
  575. this.SetEditLabel(value);
  576. }
  577. }
  578. /// <summary>
  579. /// Gets the Base Uniform Resource Identifier (URI).
  580. /// </summary>
  581. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")]
  582. public Microsoft.VisualStudio.Shell.Url BaseURI
  583. {
  584. get
  585. {
  586. if (baseUri == null && this.buildProject != null)
  587. {
  588. string path = System.IO.Path.GetDirectoryName(this.buildProject.FullPath);
  589. // Uri/Url behave differently when you have trailing slash and when you dont
  590. if (!path.EndsWith("\\", StringComparison.Ordinal) && !path.EndsWith("/", StringComparison.Ordinal))
  591. path += "\\";
  592. baseUri = new Url(path);
  593. }
  594. Debug.Assert(baseUri != null, "Base URL should not be null. Did you call BaseURI before loading the project?");
  595. return baseUri;
  596. }
  597. }
  598. /// <summary>
  599. /// Gets whether or not the project is closed.
  600. /// </summary>
  601. public bool IsClosed
  602. {
  603. get
  604. {
  605. return this.isClosed;
  606. }
  607. }
  608. /// <summary>
  609. /// Gets whether or not the project is being built.
  610. /// </summary>
  611. public bool BuildInProgress
  612. {
  613. get
  614. {
  615. return buildInProcess;
  616. }
  617. }
  618. /// <summary>
  619. /// Gets or set the relative path to the folder containing the project ouput.
  620. /// </summary>
  621. public virtual string OutputBaseRelativePath
  622. {
  623. get
  624. {
  625. return this.outputBaseRelativePath;
  626. }
  627. set
  628. {
  629. if (Path.IsPathRooted(value))
  630. {
  631. throw new ArgumentException("Path must not be rooted.");
  632. }
  633. this.outputBaseRelativePath = value;
  634. }
  635. }
  636. public FrameworkName TargetFrameworkMoniker
  637. {
  638. get
  639. {
  640. if (this.options == null)
  641. {
  642. GetProjectOptions();
  643. }
  644. if (this.options != null)
  645. {
  646. return this.options.TargetFrameworkMoniker ?? DefaultTargetFrameworkMoniker;
  647. }
  648. else
  649. {
  650. return DefaultTargetFrameworkMoniker;
  651. }
  652. }
  653. set
  654. {
  655. if (this.options == null)
  656. {
  657. GetProjectOptions();
  658. }
  659. if (value == null)
  660. {
  661. value = DefaultTargetFrameworkMoniker;
  662. }
  663. if (this.options.TargetFrameworkMoniker != value)
  664. {
  665. this.OnTargetFrameworkMonikerChanged(this.options, this.options.TargetFrameworkMoniker, value);
  666. }
  667. }
  668. }
  669. /// <summary>
  670. /// Gets or sets the flag whether query edit should communicate with the scc manager.
  671. /// </summary>
  672. protected bool DisableQueryEdit
  673. {
  674. get
  675. {
  676. return this.disableQueryEdit;
  677. }
  678. set
  679. {
  680. this.disableQueryEdit = value;
  681. }
  682. }
  683. /// <summary>
  684. /// Gets a collection of integer ids that maps to project item instances
  685. /// </summary>
  686. internal EventSinkCollection ItemIdMap
  687. {
  688. get
  689. {
  690. return this.itemIdMap;
  691. }
  692. }
  693. /// <summary>
  694. /// Get the helper object that track document changes.
  695. /// </summary>
  696. internal TrackDocumentsHelper Tracker
  697. {
  698. get
  699. {
  700. return this.tracker;
  701. }
  702. }
  703. /// <summary>
  704. /// Gets or sets the build logger.
  705. /// </summary>
  706. protected Microsoft.Build.Utilities.Logger BuildLogger
  707. {
  708. get
  709. {
  710. return this.buildLogger;
  711. }
  712. set
  713. {
  714. this.buildLogger = value;
  715. this.useProvidedLogger = true;
  716. }
  717. }
  718. /// <summary>
  719. /// Gets the taskprovider.
  720. /// </summary>
  721. protected TaskProvider TaskProvider
  722. {
  723. get
  724. {
  725. return this.taskProvider;
  726. }
  727. }
  728. /// <summary>
  729. /// Gets the project file name.
  730. /// </summary>
  731. protected string FileName
  732. {
  733. get
  734. {
  735. return this.filename;
  736. }
  737. }
  738. protected bool IsIdeInCommandLineMode
  739. {
  740. get
  741. {
  742. bool cmdline = false;
  743. var shell = this.site.GetService(typeof(SVsShell)) as IVsShell;
  744. if (shell != null)
  745. {
  746. object obj;
  747. Marshal.ThrowExceptionForHR(shell.GetProperty((int)__VSSPROPID.VSSPROPID_IsInCommandLineMode, out obj));
  748. cmdline = (bool)obj;
  749. }
  750. return cmdline;
  751. }
  752. }
  753. /// <summary>
  754. /// Gets the configuration provider.
  755. /// </summary>
  756. protected ConfigProvider ConfigProvider
  757. {
  758. get
  759. {
  760. if (this.configProvider == null)
  761. {
  762. this.configProvider = CreateConfigProvider();
  763. }
  764. return this.configProvider;
  765. }
  766. }
  767. /// <summary>
  768. /// Gets or sets whether or not source code control is disabled for this project.
  769. /// </summary>
  770. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Scc")]
  771. protected bool IsSccDisabled
  772. {
  773. get
  774. {
  775. return this.disableScc;
  776. }
  777. set
  778. {
  779. this.disableScc = value;
  780. }
  781. }
  782. /// <summary>
  783. /// Gets or set whether items can be deleted for this project.
  784. /// Enabling this feature can have the potential destructive behavior such as deleting files from disk.
  785. /// </summary>
  786. protected internal bool CanProjectDeleteItems
  787. {
  788. get
  789. {
  790. return canProjectDeleteItems;
  791. }
  792. set
  793. {
  794. canProjectDeleteItems = value;
  795. }
  796. }
  797. /// <summary>
  798. /// Determines whether the project was fully opened. This is set when the OnAfterOpenProject has triggered.
  799. /// </summary>
  800. protected internal bool HasProjectOpened
  801. {
  802. get
  803. {
  804. return this.projectOpened;
  805. }
  806. }
  807. /// <summary>
  808. /// Gets or sets event triggering flags.
  809. /// </summary>
  810. internal EventTriggering EventTriggeringFlag
  811. {
  812. get
  813. {
  814. return this.eventTriggeringFlag;
  815. }
  816. set
  817. {
  818. this.eventTriggeringFlag = value;
  819. }
  820. }
  821. /// <summary>
  822. /// Defines the build project that has loaded the project file.
  823. /// </summary>
  824. protected internal MSBuild.Project BuildProject
  825. {
  826. get
  827. {
  828. return this.buildProject;
  829. }
  830. set
  831. {
  832. SetBuildProject(value);
  833. }
  834. }
  835. /// <summary>
  836. /// Gets the current config.
  837. /// </summary>
  838. /// <value>The current config.</value>
  839. protected internal Microsoft.Build.Execution.ProjectInstance CurrentConfig
  840. {
  841. get { return this.currentConfig; }
  842. }
  843. /// <summary>
  844. /// Defines the build engine that is used to build the project file.
  845. /// </summary>
  846. internal MSBuild.ProjectCollection BuildEngine
  847. {
  848. get
  849. {
  850. return this.buildEngine;
  851. }
  852. set
  853. {
  854. this.buildEngine = value;
  855. }
  856. }
  857. /// <summary>
  858. /// The internal package implementation.
  859. /// </summary>
  860. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  861. internal ProjectPackage Package
  862. {
  863. get
  864. {
  865. return this.package;
  866. }
  867. set
  868. {
  869. this.package = value;
  870. }
  871. }
  872. #endregion
  873. #region ctor
  874. protected ProjectNode()
  875. {
  876. this.Initialize();
  877. }
  878. #endregion
  879. #region overridden methods
  880. protected override NodeProperties CreatePropertiesObject()
  881. {
  882. return new ProjectNodeProperties(this);
  883. }
  884. /// <summary>
  885. /// Sets the properties for the project node.
  886. /// </summary>
  887. /// <param name="propid">Identifier of the hierarchy property. For a list of propid values, <see cref="__VSHPROPID"/> </param>
  888. /// <param name="value">The value to set. </param>
  889. /// <returns>A success or failure value.</returns>
  890. public override int SetProperty(int propid, object value)
  891. {
  892. __VSHPROPID id = (__VSHPROPID)propid;
  893. switch (id)
  894. {
  895. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  896. this.ShowProjectInSolutionPage = (bool)value;
  897. return VSConstants.S_OK;
  898. }
  899. return base.SetProperty(propid, value);
  900. }
  901. /// <summary>
  902. /// Renames the project node.
  903. /// </summary>
  904. /// <param name="label">The new name</param>
  905. /// <returns>A success or failure value.</returns>
  906. public override int SetEditLabel(string label)
  907. {
  908. // Validate the filename.
  909. if (String.IsNullOrEmpty(label))
  910. {
  911. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  912. }
  913. else if (this.ProjectFolder.Length + label.Length + 1 > NativeMethods.MAX_PATH)
  914. {
  915. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.PathTooLong, CultureInfo.CurrentUICulture), label));
  916. }
  917. else if (Utilities.IsFileNameInvalid(label))
  918. {
  919. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  920. }
  921. string fileName = Path.GetFileNameWithoutExtension(label);
  922. // if there is no filename or it starts with a leading dot issue an error message and quit.
  923. if (String.IsNullOrEmpty(fileName) || fileName[0] == '.')
  924. {
  925. throw new InvalidOperationException(SR.GetString(SR.FileNameCannotContainALeadingPeriod, CultureInfo.CurrentUICulture));
  926. }
  927. // Nothing to do if the name is the same
  928. string oldFileName = Path.GetFileNameWithoutExtension(this.Url);
  929. if (String.Compare(oldFileName, label, StringComparison.Ordinal) == 0)
  930. {
  931. return VSConstants.S_FALSE;
  932. }
  933. // Now check whether the original file is still there. It could have been renamed.
  934. if (!File.Exists(this.Url))
  935. {
  936. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.FileOrFolderCannotBeFound, CultureInfo.CurrentUICulture), this.ProjectFile));
  937. }
  938. // Get the full file name and then rename the project file.
  939. string newFile = Path.Combine(this.ProjectFolder, label);
  940. string extension = Path.GetExtension(this.Url);
  941. // Make sure it has the correct extension
  942. if (String.Compare(Path.GetExtension(newFile), extension, StringComparison.OrdinalIgnoreCase) != 0)
  943. {
  944. newFile += extension;
  945. }
  946. this.RenameProjectFile(newFile);
  947. return VSConstants.S_OK;
  948. }
  949. /// <summary>
  950. /// Gets the automation object for the project node.
  951. /// </summary>
  952. /// <returns>An instance of an EnvDTE.Project implementation object representing the automation object for the project.</returns>
  953. public override object GetAutomationObject()
  954. {
  955. return new Automation.OAProject(this);
  956. }
  957. /// <summary>
  958. /// Closes the project node.
  959. /// </summary>
  960. /// <returns>A success or failure value.</returns>
  961. public override int Close()
  962. {
  963. int hr = VSConstants.S_OK;
  964. try
  965. {
  966. // Walk the tree and close all nodes.
  967. // This has to be done before the project closes, since we want still state available for the ProjectMgr on the nodes
  968. // when nodes are closing.
  969. try
  970. {
  971. CloseAllNodes(this);
  972. }
  973. finally
  974. {
  975. this.Dispose(true);
  976. }
  977. }
  978. catch (COMException e)
  979. {
  980. hr = e.ErrorCode;
  981. }
  982. finally
  983. {
  984. ErrorHandler.ThrowOnFailure(base.Close());
  985. }
  986. this.isClosed = true;
  987. return hr;
  988. }
  989. /// <summary>
  990. /// Sets the service provider from which to access the services.
  991. /// </summary>
  992. /// <param name="site">An instance to an Microsoft.VisualStudio.OLE.Interop object</param>
  993. /// <returns>A success or failure value.</returns>
  994. public override int SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider site)
  995. {
  996. CCITracing.TraceCall();
  997. this.site = new ServiceProvider(site);
  998. ServiceProvider = this.site;
  999. if (taskProvider != null)
  1000. {
  1001. taskProvider.Dispose();
  1002. }
  1003. taskProvider = new TaskProvider(this.site);
  1004. return VSConstants.S_OK;
  1005. }
  1006. /// <summary>
  1007. /// Gets the properties of the project node.
  1008. /// </summary>
  1009. /// <param name="propId">The __VSHPROPID of the property.</param>
  1010. /// <returns>A property dependent value. See: <see cref="__VSHPROPID"/> for details.</returns>
  1011. public override object GetProperty(int propId)
  1012. {
  1013. switch ((__VSHPROPID)propId)
  1014. {
  1015. case __VSHPROPID.VSHPROPID_ConfigurationProvider:
  1016. return this.ConfigProvider;
  1017. case __VSHPROPID.VSHPROPID_ProjectName:
  1018. return this.Caption;
  1019. case __VSHPROPID.VSHPROPID_ProjectDir:
  1020. return this.ProjectFolder;
  1021. case __VSHPROPID.VSHPROPID_TypeName:
  1022. return this.ProjectType;
  1023. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  1024. return this.ShowProjectInSolutionPage;
  1025. case __VSHPROPID.VSHPROPID_ExpandByDefault:
  1026. return true;
  1027. // Use the same icon as if the folder was closed
  1028. case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
  1029. return GetProperty((int)__VSHPROPID.VSHPROPID_IconIndex);
  1030. }
  1031. switch ((__VSHPROPID2)propId)
  1032. {
  1033. case __VSHPROPID2.VSHPROPID_SupportsProjectDesigner:
  1034. return this.SupportsProjectDesigner;
  1035. case __VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList:
  1036. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationIndependentPropertyPages());
  1037. case __VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList:
  1038. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationDependentPropertyPages());
  1039. case __VSHPROPID2.VSHPROPID_PriorityPropertyPagesCLSIDList:
  1040. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetPriorityProjectDesignerPages());
  1041. case __VSHPROPID2.VSHPROPID_Container:
  1042. return true;
  1043. default:
  1044. break;
  1045. }
  1046. return base.GetProperty(propId);
  1047. }
  1048. /// <summary>
  1049. /// Gets the GUID value of the node.
  1050. /// </summary>
  1051. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  1052. /// <param name="guid">The guid to return for the property.</param>
  1053. /// <returns>A success or failure value.</returns>
  1054. public override int GetGuidProperty(int propid, out Guid guid)
  1055. {
  1056. guid = Guid.Empty;
  1057. if ((__VSHPROPID)propid == __VSHPROPID.VSHPROPID_ProjectIDGuid)
  1058. {
  1059. guid = this.ProjectIDGuid;
  1060. }
  1061. else if (propid == (int)__VSHPROPID.VSHPROPID_CmdUIGuid)
  1062. {
  1063. guid = this.ProjectGuid;
  1064. }
  1065. else if ((__VSHPROPID2)propid == __VSHPROPID2.VSHPROPID_ProjectDesignerEditor && this.SupportsProjectDesigner)
  1066. {
  1067. guid = this.ProjectDesignerEditor;
  1068. }
  1069. else
  1070. {
  1071. base.GetGuidProperty(propid, out guid);
  1072. }
  1073. if (guid.CompareTo(Guid.Empty) == 0)
  1074. {
  1075. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1076. }
  1077. return VSConstants.S_OK;
  1078. }
  1079. /// <summary>
  1080. /// Sets Guid properties for the project node.
  1081. /// </summary>
  1082. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  1083. /// <param name="guid">The guid value to set.</param>
  1084. /// <returns>A success or failure value.</returns>
  1085. public override int SetGuidProperty(int propid, ref Guid guid)
  1086. {
  1087. switch ((__VSHPROPID)propid)
  1088. {
  1089. case __VSHPROPID.VSHPROPID_ProjectIDGuid:
  1090. this.ProjectIDGuid = guid;
  1091. return VSConstants.S_OK;
  1092. }
  1093. CCITracing.TraceCall(String.Format(CultureInfo.CurrentCulture, "Property {0} not found", propid));
  1094. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1095. }
  1096. /// <summary>
  1097. /// Removes items from the hierarchy.
  1098. /// </summary>
  1099. /// <devdoc>Project overwrites this.</devdoc>
  1100. public override void Remove(bool removeFromStorage)
  1101. {
  1102. // the project will not be deleted from disk, just removed
  1103. if (removeFromStorage)
  1104. {
  1105. return;
  1106. }
  1107. // Remove the entire project from the solution
  1108. IVsSolution solution = this.Site.GetService(typeof(SVsSolution)) as IVsSolution;
  1109. uint iOption = 1; // SLNSAVEOPT_PromptSave
  1110. ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement(iOption, this, 0));
  1111. }
  1112. /// <summary>
  1113. /// Gets the moniker for the project node. That is the full path of the project file.
  1114. /// </summary>
  1115. /// <returns>The moniker for the project file.</returns>
  1116. public override string GetMkDocument()
  1117. {
  1118. Debug.Assert(!String.IsNullOrEmpty(this.filename));
  1119. Debug.Assert(this.BaseURI != null && !String.IsNullOrEmpty(this.BaseURI.AbsoluteUrl));
  1120. return Path.Combine(this.BaseURI.AbsoluteUrl, this.filename);
  1121. }
  1122. /// <summary>
  1123. /// Disposes the project node object.
  1124. /// </summary>
  1125. /// <param name="disposing">Flag determining ehether it was deterministic or non deterministic clean up.</param>
  1126. protected override void Dispose(bool disposing)
  1127. {
  1128. if (this.isDisposed)
  1129. {
  1130. return;
  1131. }
  1132. try
  1133. {
  1134. try
  1135. {
  1136. this.UnRegisterProject();
  1137. }
  1138. finally
  1139. {
  1140. try
  1141. {
  1142. this.RegisterClipboardNotifications(false);
  1143. }
  1144. finally
  1145. {
  1146. try
  1147. {
  1148. if (this.projectEventsProvider != null)
  1149. {
  1150. this.projectEventsProvider.AfterProjectFileOpened -= this.OnAfterProjectOpen;
  1151. }
  1152. if (this.taskProvider != null)
  1153. {
  1154. taskProvider.Tasks.Clear();
  1155. this.taskProvider.Dispose();
  1156. this.taskProvider = null;
  1157. }
  1158. if (this.buildLogger != null)
  1159. {
  1160. this.buildLogger.Shutdown();
  1161. buildLogger = null;
  1162. }
  1163. if (this.site != null)
  1164. {
  1165. this.site.Dispose();
  1166. }
  1167. }
  1168. finally
  1169. {
  1170. this.buildEngine = null;
  1171. }
  1172. }
  1173. }
  1174. if (this.buildProject != null)
  1175. {
  1176. this.buildProject.ProjectCollection.UnloadProject(this.buildProject);
  1177. this.buildProject.ProjectCollection.UnloadProject(this.buildProject.Xml);
  1178. this.buildProject = null;
  1179. }
  1180. if (null != imageHandler)
  1181. {
  1182. imageHandler.Close();
  1183. imageHandler = null;
  1184. }
  1185. }
  1186. finally
  1187. {
  1188. base.Dispose(disposing);
  1189. this.isDisposed = true;
  1190. }
  1191. }
  1192. /// <summary>
  1193. /// Handles command status on the project node. If a command cannot be handled then the base should be called.
  1194. /// </summary>
  1195. /// <param name="cmdGroup">A unique identifier of the command group. The pguidCmdGroup parameter can be NULL to specify the standard group.</param>
  1196. /// <param name="cmd">The command to query status for.</param>
  1197. /// <param name="pCmdText">Pointer to an OLECMDTEXT structure in which to return the name and/or status information of a single command. Can be NULL to indicate that the caller does not require this information.</param>
  1198. /// <param name="result">An out parameter specifying the QueryStatusResult of the command.</param>
  1199. /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
  1200. protected override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result)
  1201. {
  1202. if (cmdGroup == VsMenus.guidStandardCommandSet97)
  1203. {
  1204. switch ((VsCommands)cmd)
  1205. {
  1206. case VsCommands.Copy:
  1207. case VsCommands.Paste:
  1208. case VsCommands.Cut:
  1209. case VsCommands.Rename:
  1210. case VsCommands.Exit:
  1211. case VsCommands.ProjectSettings:
  1212. case VsCommands.BuildSln:
  1213. case VsCommands.UnloadProject:
  1214. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1215. return VSConstants.S_OK;
  1216. case VsCommands.ViewForm:
  1217. if (this.HasDesigner)
  1218. {
  1219. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1220. return VSConstants.S_OK;
  1221. }
  1222. break;
  1223. case VsCommands.CancelBuild:
  1224. result |= QueryStatusResult.SUPPORTED;
  1225. if (this.buildInProcess)
  1226. result |= QueryStatusResult.ENABLED;
  1227. else
  1228. result |= QueryStatusResult.INVISIBLE;
  1229. return VSConstants.S_OK;
  1230. case VsCommands.NewFolder:
  1231. case VsCommands.AddNewItem:
  1232. case VsCommands.AddExistingItem:
  1233. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1234. return VSConstants.S_OK;
  1235. case VsCommands.SetStartupProject:
  1236. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1237. return VSConstants.S_OK;
  1238. }
  1239. }
  1240. else if (cmdGroup == VsMenus.guidStandardCommandSet2K)
  1241. {
  1242. switch ((VsCommands2K)cmd)
  1243. {
  1244. case VsCommands2K.ADDREFERENCE:
  1245. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1246. return VSConstants.S_OK;
  1247. case VsCommands2K.EXCLUDEFROMPROJECT:
  1248. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
  1249. return VSConstants.S_OK;
  1250. case ExploreFolderInWindowsCommand:
  1251. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1252. return VSConstants.S_OK;
  1253. }
  1254. }
  1255. else
  1256. {
  1257. return (int)OleConstants.OLECMDERR_E_UNKNOWNGROUP;
  1258. }
  1259. return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
  1260. }
  1261. /// <summary>
  1262. /// Handles command execution.
  1263. /// </summary>
  1264. /// <param name="cmdGroup">Unique identifier of the command group</param>
  1265. /// <param name="cmd">The command to be executed.</param>
  1266. /// <param name="nCmdexecopt">Values describe how the object should execute the command.</param>
  1267. /// <param name="pvaIn">Pointer to a VARIANTARG structure containing input arguments. Can be NULL</param>
  1268. /// <param name="pvaOut">VARIANTARG structure to receive command output. Can b…

Large files files are truncated, but you can click here to view the full file