PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/Dependencies/MPFProjectBase/ProjectNode.cs

https://github.com/olsonjeffery/boolangstudio
C# | 5931 lines | 5160 code | 305 blank | 466 comment | 196 complexity | 85e4ad27857ef58debbabcc2bb76d76d MD5 | raw file
Possible License(s): CC-BY-SA-3.0

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

  1. /// Copyright (c) Microsoft Corporation. All rights reserved.
  2. using System;
  3. using System.CodeDom.Compiler;
  4. using System.Collections.Generic;
  5. using System.Collections.Specialized;
  6. using System.Diagnostics;
  7. using System.Diagnostics.CodeAnalysis;
  8. using System.Globalization;
  9. using System.IO;
  10. using System.Runtime.InteropServices;
  11. using System.Windows.Forms;
  12. using System.Xml;
  13. using EnvDTE;
  14. using Microsoft.VisualStudio.OLE.Interop;
  15. using Microsoft.VisualStudio.Shell;
  16. using Microsoft.VisualStudio.Shell.Interop;
  17. using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
  18. using IServiceProvider = System.IServiceProvider;
  19. using MSBuild = Microsoft.Build.BuildEngine;
  20. using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants;
  21. using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
  22. using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
  23. namespace Microsoft.VisualStudio.Project
  24. {
  25. /// <summary>
  26. /// Manages the persistent state of the project (References, options, files, etc.) and deals with user interaction via a GUI in the form a hierarchy.
  27. /// </summary>
  28. [CLSCompliant(false)]
  29. [ComVisible(true)]
  30. public abstract partial class ProjectNode : HierarchyNode,
  31. IVsGetCfgProvider,
  32. IVsProject3,
  33. IVsAggregatableProject,
  34. IVsProjectFlavorCfgProvider,
  35. IPersistFileFormat,
  36. IVsProjectBuildSystem,
  37. IVsBuildPropertyStorage,
  38. IVsComponentUser,
  39. IVsDependencyProvider,
  40. IVsSccProject2,
  41. IBuildDependencyUpdate,
  42. IProjectEventsListener,
  43. IProjectEventsProvider,
  44. IReferenceContainerProvider,
  45. IVsProjectSpecialFiles
  46. {
  47. #region nested types
  48. public enum ImageName
  49. {
  50. OfflineWebApp = 0,
  51. WebReferencesFolder = 1,
  52. OpenReferenceFolder = 2,
  53. ReferenceFolder = 3,
  54. Reference = 4,
  55. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SDL")]
  56. SDLWebReference = 5,
  57. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DISCO")]
  58. DISCOWebReference = 6,
  59. Folder = 7,
  60. OpenFolder = 8,
  61. ExcludedFolder = 9,
  62. OpenExcludedFolder = 10,
  63. ExcludedFile = 11,
  64. DependentFile = 12,
  65. MissingFile = 13,
  66. WindowsForm = 14,
  67. WindowsUserControl = 15,
  68. WindowsComponent = 16,
  69. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  70. XMLSchema = 17,
  71. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  72. XMLFile = 18,
  73. WebForm = 19,
  74. WebService = 20,
  75. WebUserControl = 21,
  76. WebCustomUserControl = 22,
  77. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ASP")]
  78. ASPPage = 23,
  79. GlobalApplicationClass = 24,
  80. WebConfig = 25,
  81. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "HTML")]
  82. HTMLPage = 26,
  83. StyleSheet = 27,
  84. ScriptFile = 28,
  85. TextFile = 29,
  86. SettingsFile = 30,
  87. Resources = 31,
  88. Bitmap = 32,
  89. Icon = 33,
  90. Image = 34,
  91. ImageMap = 35,
  92. XWorld = 36,
  93. Audio = 37,
  94. Video = 38,
  95. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "CAB")]
  96. CAB = 39,
  97. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "JAR")]
  98. JAR = 40,
  99. DataEnvironment = 41,
  100. PreviewFile = 42,
  101. DanglingReference = 43,
  102. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XSLT")]
  103. XSLTFile = 44,
  104. Cursor = 45,
  105. AppDesignerFolder = 46,
  106. Data = 47,
  107. Application = 48,
  108. DataSet = 49,
  109. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "PFX")]
  110. PFX = 50,
  111. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SNK")]
  112. SNK = 51,
  113. ImageLast = 51
  114. }
  115. /// <summary>
  116. /// Flags for specifying which events to stop triggering.
  117. /// </summary>
  118. [Flags]
  119. internal enum EventTriggering
  120. {
  121. TriggerAll = 0,
  122. DoNotTriggerHierarchyEvents = 1,
  123. DoNotTriggerTrackerEvents = 2
  124. }
  125. #endregion
  126. #region constants
  127. /// <summary>
  128. /// The user file extension.
  129. /// </summary>
  130. internal const string PerUserFileExtension = ".user";
  131. #endregion
  132. #region fields
  133. /// <summary>
  134. /// List of output groups names and their associated target
  135. /// </summary>
  136. private static KeyValuePair<string, string>[] outputGroupNames =
  137. { // Name Target (MSBuild)
  138. new KeyValuePair<string, string>("Built", "BuiltProjectOutputGroup"),
  139. new KeyValuePair<string, string>("ContentFiles", "ContentFilesProjectOutputGroup"),
  140. new KeyValuePair<string, string>("LocalizedResourceDlls", "SatelliteDllsProjectOutputGroup"),
  141. new KeyValuePair<string, string>("Documentation", "DocumentationProjectOutputGroup"),
  142. new KeyValuePair<string, string>("Symbols", "DebugSymbolsProjectOutputGroup"),
  143. new KeyValuePair<string, string>("SourceFiles", "SourceFilesProjectOutputGroup"),
  144. new KeyValuePair<string, string>("XmlSerializer", "SGenFilesOutputGroup"),
  145. };
  146. /// <summary>A project will only try to build if it can obtain a lock on this object</summary>
  147. private volatile static object BuildLock = new object();
  148. /// <summary>Maps integer ids to project item instances</summary>
  149. private EventSinkCollection itemIdMap = new EventSinkCollection();
  150. /// <summary>A service provider call back object provided by the IDE hosting the project manager</summary>
  151. private IServiceProvider site;
  152. private TrackDocumentsHelper tracker;
  153. /// <summary>
  154. /// This property returns the time of the last change made to this project.
  155. /// It is not the time of the last change on the project file, but actually of
  156. /// the in memory project settings. In other words, it is the last time that
  157. /// SetProjectDirty was called.
  158. /// </summary>
  159. private DateTime lastModifiedTime;
  160. /// <summary>
  161. /// MSBuild engine we are going to use
  162. /// </summary>
  163. private MSBuild.Engine buildEngine;
  164. private Microsoft.Build.Utilities.Logger buildLogger;
  165. private bool useProvidedLogger;
  166. private MSBuild.Project buildProject;
  167. private MSBuild.BuildPropertyGroup currentConfig;
  168. private ConfigProvider configProvider;
  169. private TaskProvider taskProvider;
  170. private string filename;
  171. private Microsoft.VisualStudio.Shell.Url baseUri;
  172. private bool isDirty;
  173. private bool isNewProject;
  174. private bool projectOpened;
  175. private bool buildIsPrepared;
  176. private ImageHandler imageHandler;
  177. private string errorString;
  178. private string warningString;
  179. private Guid projectIdGuid;
  180. private ProjectOptions options;
  181. private bool isClosed;
  182. private EventTriggering eventTriggeringFlag = EventTriggering.TriggerAll;
  183. private bool invokeMSBuildWhenResumed;
  184. private uint suspendMSBuildCounter;
  185. private bool canFileNodesHaveChilds;
  186. private bool isProjectEventsListener = true;
  187. /// <summary>
  188. /// The build dependency list passed to IVsDependencyProvider::EnumDependencies
  189. /// </summary>
  190. private List<IVsBuildDependency> buildDependencyList = new List<IVsBuildDependency>();
  191. /// <summary>
  192. /// Defines if Project System supports Project Designer
  193. /// </summary>
  194. private bool supportsProjectDesigner;
  195. private bool showProjectInSolutionPage = true;
  196. private bool buildInProcess;
  197. /// <summary>
  198. /// Field for determining whether sourcecontrol should be disabled.
  199. /// </summary>
  200. private bool disableScc;
  201. private string sccProjectName;
  202. private string sccLocalPath;
  203. private string sccAuxPath;
  204. private string sccProvider;
  205. /// <summary>
  206. /// Flag for controling how many times we register with the Scc manager.
  207. /// </summary>
  208. private bool isRegisteredWithScc;
  209. /// <summary>
  210. /// Flag for controling query edit should communicate with the scc manager.
  211. /// </summary>
  212. private bool disableQueryEdit;
  213. /// <summary>
  214. /// Control if command with potential destructive behavior such as delete should
  215. /// be enabled for nodes of this project.
  216. /// </summary>
  217. private bool canProjectDeleteItems;
  218. /// <summary>
  219. /// Token processor used by the project sample.
  220. /// </summary>
  221. private TokenProcessor tokenProcessor;
  222. /// <summary>
  223. /// Member to store output base relative path. Used by OutputBaseRelativePath property
  224. /// </summary>
  225. private string outputBaseRelativePath = "bin";
  226. private IProjectEvents projectEventsProvider;
  227. /// <summary>
  228. /// Used for flavoring to hold the XML fragments
  229. /// </summary>
  230. private XmlDocument xmlFragments;
  231. /// <summary>
  232. /// Used to map types to CATID. This provide a generic way for us to do this
  233. /// and make it simpler for a project to provide it's CATIDs for the different type of objects
  234. /// for which it wants to support extensibility. This also enables us to have multiple
  235. /// type mapping to the same CATID if we choose to.
  236. /// </summary>
  237. private Dictionary<Type, Guid> catidMapping = new Dictionary<Type, Guid>();
  238. /// <summary>
  239. /// The globalProperty handler object in charge of maintaining global properties for this project.
  240. /// </summary>
  241. private GlobalPropertyHandler globalPropertyHandler;
  242. /// <summary>
  243. /// Flag for specifying that the project has passed security checks.
  244. /// </summary>
  245. private bool hasPassedSecurityChecks;
  246. /// <summary>
  247. /// The internal package implementation.
  248. /// </summary>
  249. private ProjectPackage package;
  250. // Has the object been disposed.
  251. private bool isDisposed;
  252. #endregion
  253. #region abstract properties
  254. /// <summary>
  255. /// This Guid must match the Guid you registered under
  256. /// HKLM\Software\Microsoft\VisualStudio\%version%\Projects.
  257. /// Among other things, the Project framework uses this
  258. /// guid to find your project and item templates.
  259. /// </summary>
  260. public abstract Guid ProjectGuid
  261. {
  262. get;
  263. }
  264. /// <summary>
  265. /// Returns a caption for VSHPROPID_TypeName.
  266. /// </summary>
  267. /// <returns></returns>
  268. public abstract string ProjectType
  269. {
  270. get;
  271. }
  272. #endregion
  273. #region virtual properties
  274. /// <summary>
  275. /// This is the project instance guid that is peristed in the project file
  276. /// </summary>
  277. [System.ComponentModel.BrowsableAttribute(false)]
  278. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")]
  279. public virtual Guid ProjectIDGuid
  280. {
  281. get
  282. {
  283. return this.projectIdGuid;
  284. }
  285. set
  286. {
  287. if(this.projectIdGuid != value)
  288. {
  289. this.projectIdGuid = value;
  290. if(this.buildProject != null)
  291. {
  292. this.SetProjectProperty("ProjectGuid", this.projectIdGuid.ToString("B"));
  293. }
  294. }
  295. }
  296. }
  297. #endregion
  298. #region properties
  299. #region overridden properties
  300. public override int MenuCommandId
  301. {
  302. get
  303. {
  304. return VsMenus.IDM_VS_CTXT_PROJNODE;
  305. }
  306. }
  307. public override string Url
  308. {
  309. get
  310. {
  311. return this.GetMkDocument();
  312. }
  313. }
  314. public override string Caption
  315. {
  316. get
  317. {
  318. // Default to file name
  319. string caption = this.buildProject.FullFileName;
  320. if(String.IsNullOrEmpty(caption))
  321. {
  322. if(this.buildProject.EvaluatedProperties[ProjectFileConstants.Name] != null)
  323. {
  324. caption = this.buildProject.EvaluatedProperties[ProjectFileConstants.Name].Value;
  325. if(caption == null || caption.Length == 0)
  326. {
  327. caption = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
  328. }
  329. }
  330. }
  331. else
  332. {
  333. caption = Path.GetFileNameWithoutExtension(caption);
  334. }
  335. return caption;
  336. }
  337. }
  338. public override Guid ItemTypeGuid
  339. {
  340. get
  341. {
  342. return this.ProjectGuid;
  343. }
  344. }
  345. public override int ImageIndex
  346. {
  347. get
  348. {
  349. return (int)ProjectNode.ImageName.Application;
  350. }
  351. }
  352. #endregion
  353. #region virtual properties
  354. public virtual string ErrorString
  355. {
  356. get
  357. {
  358. if(this.errorString == null)
  359. {
  360. this.errorString = SR.GetString(SR.Error, CultureInfo.CurrentUICulture);
  361. }
  362. return this.errorString;
  363. }
  364. }
  365. public virtual string WarningString
  366. {
  367. get
  368. {
  369. if(this.warningString == null)
  370. {
  371. this.warningString = SR.GetString(SR.Warning, CultureInfo.CurrentUICulture);
  372. }
  373. return this.warningString;
  374. }
  375. }
  376. /// <summary>
  377. /// The target name that will be used for evaluating the project file (i.e., pseudo-builds).
  378. /// This target is used to trigger a build with when the project system changes.
  379. /// Example: The language projrcts are triggering a build with the Compile target whenever
  380. /// the project system changes.
  381. /// </summary>
  382. [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ReEvaluate")]
  383. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Re")]
  384. protected internal virtual string ReEvaluateProjectFileTargetName
  385. {
  386. get
  387. {
  388. return null;
  389. }
  390. }
  391. /// <summary>
  392. /// This is the object that will be returned by EnvDTE.Project.Object for this project
  393. /// </summary>
  394. protected internal virtual object ProjectObject
  395. {
  396. get
  397. {
  398. return null;
  399. }
  400. }
  401. /// <summary>
  402. /// Override this property to specify when the project file is dirty.
  403. /// </summary>
  404. protected virtual bool IsProjectFileDirty
  405. {
  406. get
  407. {
  408. string document = this.GetMkDocument();
  409. if(String.IsNullOrEmpty(document))
  410. {
  411. return this.isDirty;
  412. }
  413. return (this.isDirty || !File.Exists(document));
  414. }
  415. }
  416. /// <summary>
  417. /// True if the project uses the Project Designer Editor instead of the property page frame to edit project properties.
  418. /// </summary>
  419. protected virtual bool SupportsProjectDesigner
  420. {
  421. get
  422. {
  423. return this.supportsProjectDesigner;
  424. }
  425. set
  426. {
  427. this.supportsProjectDesigner = value;
  428. }
  429. }
  430. protected virtual Guid ProjectDesignerEditor
  431. {
  432. get
  433. {
  434. return VSConstants.GUID_ProjectDesignerEditor;
  435. }
  436. }
  437. /// <summary>
  438. /// Defines the flag that supports the VSHPROPID.ShowProjInSolutionPage
  439. /// </summary>
  440. protected virtual bool ShowProjectInSolutionPage
  441. {
  442. get
  443. {
  444. return this.showProjectInSolutionPage;
  445. }
  446. set
  447. {
  448. this.showProjectInSolutionPage = value;
  449. }
  450. }
  451. #endregion
  452. /// <summary>
  453. /// Gets or sets the ability of a project filenode to have child nodes (sub items).
  454. /// Example would be C#/VB forms having resx and designer files.
  455. /// </summary>
  456. protected internal bool CanFileNodesHaveChilds
  457. {
  458. get
  459. {
  460. return canFileNodesHaveChilds;
  461. }
  462. set
  463. {
  464. canFileNodesHaveChilds = value;
  465. }
  466. }
  467. /// <summary>
  468. /// Get and set the Token processor.
  469. /// </summary>
  470. public TokenProcessor FileTemplateProcessor
  471. {
  472. get
  473. {
  474. if(tokenProcessor == null)
  475. tokenProcessor = new TokenProcessor();
  476. return tokenProcessor;
  477. }
  478. set
  479. {
  480. tokenProcessor = value;
  481. }
  482. }
  483. /// <summary>
  484. /// Gets a service provider object provided by the IDE hosting the project
  485. /// </summary>
  486. [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
  487. public IServiceProvider Site
  488. {
  489. get
  490. {
  491. return this.site;
  492. }
  493. }
  494. /// <summary>
  495. /// Gets an ImageHandler for the project node.
  496. /// </summary>
  497. public ImageHandler ImageHandler
  498. {
  499. get
  500. {
  501. if(null == imageHandler)
  502. {
  503. imageHandler = new ImageHandler(typeof(ProjectNode).Assembly.GetManifestResourceStream("Microsoft.VisualStudio.Project.Resources.imagelis.bmp"));
  504. }
  505. return imageHandler;
  506. }
  507. }
  508. /// <summary>
  509. /// This property returns the time of the last change made to this project.
  510. /// It is not the time of the last change on the project file, but actually of
  511. /// the in memory project settings. In other words, it is the last time that
  512. /// SetProjectDirty was called.
  513. /// </summary>
  514. public DateTime LastModifiedTime
  515. {
  516. get
  517. {
  518. return this.lastModifiedTime;
  519. }
  520. }
  521. /// <summary>
  522. /// Determines whether this project is a new project.
  523. /// </summary>
  524. public bool IsNewProject
  525. {
  526. get
  527. {
  528. return this.isNewProject;
  529. }
  530. }
  531. /// <summary>
  532. /// Gets the path to the folder containing the project.
  533. /// </summary>
  534. public string ProjectFolder
  535. {
  536. get
  537. {
  538. return Path.GetDirectoryName(this.filename);
  539. }
  540. }
  541. /// <summary>
  542. /// Gets or sets the project filename.
  543. /// </summary>
  544. public string ProjectFile
  545. {
  546. get
  547. {
  548. return Path.GetFileName(this.filename);
  549. }
  550. set
  551. {
  552. this.SetEditLabel(value);
  553. }
  554. }
  555. /// <summary>
  556. /// Gets the Base Uniform Resource Identifier (URI).
  557. /// </summary>
  558. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")]
  559. public Microsoft.VisualStudio.Shell.Url BaseURI
  560. {
  561. get
  562. {
  563. if(baseUri == null && this.buildProject != null)
  564. {
  565. string path = System.IO.Path.GetDirectoryName(this.buildProject.FullFileName);
  566. // Uri/Url behave differently when you have trailing slash and when you dont
  567. if(!path.EndsWith("\\", StringComparison.Ordinal) && !path.EndsWith("/", StringComparison.Ordinal))
  568. path += "\\";
  569. baseUri = new Url(path);
  570. }
  571. Debug.Assert(baseUri != null, "Base URL should not be null. Did you call BaseURI before loading the project?");
  572. return baseUri;
  573. }
  574. }
  575. /// <summary>
  576. /// Gets whether or not the project is closed.
  577. /// </summary>
  578. public bool IsClosed
  579. {
  580. get
  581. {
  582. return this.isClosed;
  583. }
  584. }
  585. /// <summary>
  586. /// Gets whether or not the project is being built.
  587. /// </summary>
  588. public bool BuildInProgress
  589. {
  590. get
  591. {
  592. return buildInProcess;
  593. }
  594. }
  595. /// <summary>
  596. /// Gets or set the relative path to the folder containing the project ouput.
  597. /// </summary>
  598. public virtual string OutputBaseRelativePath
  599. {
  600. get
  601. {
  602. return this.outputBaseRelativePath;
  603. }
  604. set
  605. {
  606. if(Path.IsPathRooted(value))
  607. {
  608. throw new ArgumentException("Path must not be rooted.");
  609. }
  610. this.outputBaseRelativePath = value;
  611. }
  612. }
  613. /// <summary>
  614. /// Gets or sets the flag whether query edit should communicate with the scc manager.
  615. /// </summary>
  616. protected bool DisableQueryEdit
  617. {
  618. get
  619. {
  620. return this.disableQueryEdit;
  621. }
  622. set
  623. {
  624. this.disableQueryEdit = value;
  625. }
  626. }
  627. /// <summary>
  628. /// Gets a collection of integer ids that maps to project item instances
  629. /// </summary>
  630. internal EventSinkCollection ItemIdMap
  631. {
  632. get
  633. {
  634. return this.itemIdMap;
  635. }
  636. }
  637. /// <summary>
  638. /// Get the helper object that track document changes.
  639. /// </summary>
  640. internal TrackDocumentsHelper Tracker
  641. {
  642. get
  643. {
  644. return this.tracker;
  645. }
  646. }
  647. /// <summary>
  648. /// Gets or sets the build logger.
  649. /// </summary>
  650. protected Microsoft.Build.Utilities.Logger BuildLogger
  651. {
  652. get
  653. {
  654. return this.buildLogger;
  655. }
  656. set
  657. {
  658. this.buildLogger = value;
  659. this.useProvidedLogger = true;
  660. }
  661. }
  662. /// <summary>
  663. /// Gets the taskprovider.
  664. /// </summary>
  665. protected TaskProvider TaskProvider
  666. {
  667. get
  668. {
  669. return this.taskProvider;
  670. }
  671. }
  672. /// <summary>
  673. /// Gets the project file name.
  674. /// </summary>
  675. protected string FileName
  676. {
  677. get
  678. {
  679. return this.filename;
  680. }
  681. }
  682. /// <summary>
  683. /// Gets the configuration provider.
  684. /// </summary>
  685. protected ConfigProvider ConfigProvider
  686. {
  687. get
  688. {
  689. if(this.configProvider == null)
  690. {
  691. this.configProvider = CreateConfigProvider();
  692. }
  693. return this.configProvider;
  694. }
  695. }
  696. /// <summary>
  697. /// Gets or sets whether or not source code control is disabled for this project.
  698. /// </summary>
  699. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Scc")]
  700. protected bool IsSccDisabled
  701. {
  702. get
  703. {
  704. return this.disableScc;
  705. }
  706. set
  707. {
  708. this.disableScc = value;
  709. }
  710. }
  711. /// <summary>
  712. /// Gets or set whether items can be deleted for this project.
  713. /// Enabling this feature can have the potential destructive behavior such as deleting files from disk.
  714. /// </summary>
  715. protected internal bool CanProjectDeleteItems
  716. {
  717. get
  718. {
  719. return canProjectDeleteItems;
  720. }
  721. set
  722. {
  723. canProjectDeleteItems = value;
  724. }
  725. }
  726. /// <summary>
  727. /// Determines whether the project was fully opened. This is set when the OnAfterOpenProject has triggered.
  728. /// </summary>
  729. protected internal bool HasProjectOpened
  730. {
  731. get
  732. {
  733. return this.projectOpened;
  734. }
  735. }
  736. /// <summary>
  737. /// Gets or sets event triggering flags.
  738. /// </summary>
  739. internal EventTriggering EventTriggeringFlag
  740. {
  741. get
  742. {
  743. return this.eventTriggeringFlag;
  744. }
  745. set
  746. {
  747. this.eventTriggeringFlag = value;
  748. }
  749. }
  750. /// <summary>
  751. /// Defines the build project that has loaded the project file.
  752. /// </summary>
  753. protected internal Microsoft.Build.BuildEngine.Project BuildProject
  754. {
  755. get
  756. {
  757. return this.buildProject;
  758. }
  759. set
  760. {
  761. this.buildProject = value;
  762. }
  763. }
  764. /// <summary>
  765. /// Defines the build engine that is used to build the project file.
  766. /// </summary>
  767. internal Microsoft.Build.BuildEngine.Engine BuildEngine
  768. {
  769. get
  770. {
  771. return this.buildEngine;
  772. }
  773. set
  774. {
  775. this.buildEngine = value;
  776. }
  777. }
  778. /// <summary>
  779. /// The object in charge of maintaining global properties for this project.
  780. /// </summary>
  781. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  782. internal GlobalPropertyHandler GlobalPropetyHandler
  783. {
  784. get
  785. {
  786. return this.globalPropertyHandler;
  787. }
  788. set
  789. {
  790. this.globalPropertyHandler = value;
  791. }
  792. }
  793. /// <summary>
  794. /// Has the project passed security checks?
  795. /// </summary>
  796. internal bool HasPassedSecurityChecks
  797. {
  798. get
  799. {
  800. return this.hasPassedSecurityChecks;
  801. }
  802. set
  803. {
  804. this.hasPassedSecurityChecks = value;
  805. }
  806. }
  807. /// <summary>
  808. /// The internal package implementation.
  809. /// </summary>
  810. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  811. internal ProjectPackage Package
  812. {
  813. get
  814. {
  815. return this.package;
  816. }
  817. set
  818. {
  819. this.package = value;
  820. }
  821. }
  822. #endregion
  823. #region ctor
  824. protected ProjectNode()
  825. {
  826. this.Initialize();
  827. }
  828. #endregion
  829. #region overridden methods
  830. protected override NodeProperties CreatePropertiesObject()
  831. {
  832. return new ProjectNodeProperties(this);
  833. }
  834. /// <summary>
  835. /// Sets the properties for the project node.
  836. /// </summary>
  837. /// <param name="propid">Identifier of the hierarchy property. For a list of propid values, <see cref="__VSHPROPID"/> </param>
  838. /// <param name="value">The value to set. </param>
  839. /// <returns>A success or failure value.</returns>
  840. public override int SetProperty(int propid, object value)
  841. {
  842. __VSHPROPID id = (__VSHPROPID)propid;
  843. switch(id)
  844. {
  845. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  846. this.ShowProjectInSolutionPage = (bool)value;
  847. return VSConstants.S_OK;
  848. }
  849. return base.SetProperty(propid, value);
  850. }
  851. /// <summary>
  852. /// Renames the project node.
  853. /// </summary>
  854. /// <param name="label">The new name</param>
  855. /// <returns>A success or failure value.</returns>
  856. public override int SetEditLabel(string label)
  857. {
  858. // Validate the filename.
  859. if(String.IsNullOrEmpty(label))
  860. {
  861. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  862. }
  863. else if(this.ProjectFolder.Length + label.Length + 1 > NativeMethods.MAX_PATH)
  864. {
  865. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.PathTooLong, CultureInfo.CurrentUICulture), label));
  866. }
  867. else if(Utilities.IsFileNameInvalid(label))
  868. {
  869. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  870. }
  871. string fileName = Path.GetFileNameWithoutExtension(label);
  872. // if there is no filename or it starts with a leading dot issue an error message and quit.
  873. if(String.IsNullOrEmpty(fileName) || fileName[0] == '.')
  874. {
  875. throw new InvalidOperationException(SR.GetString(SR.FileNameCannotContainALeadingPeriod, CultureInfo.CurrentUICulture));
  876. }
  877. // Nothing to do if the name is the same
  878. string oldFileName = Path.GetFileNameWithoutExtension(this.Url);
  879. if(String.Compare(oldFileName, label, StringComparison.Ordinal) == 0)
  880. {
  881. return VSConstants.S_FALSE;
  882. }
  883. // Now check whether the original file is still there. It could have been renamed.
  884. if(!File.Exists(this.Url))
  885. {
  886. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.FileOrFolderCannotBeFound, CultureInfo.CurrentUICulture), this.ProjectFile));
  887. }
  888. // Get the full file name and then rename the project file.
  889. string newFile = Path.Combine(this.ProjectFolder, label);
  890. string extension = Path.GetExtension(this.Url);
  891. // Make sure it has the correct extension
  892. if(String.Compare(Path.GetExtension(newFile), extension, StringComparison.OrdinalIgnoreCase) != 0)
  893. {
  894. newFile += extension;
  895. }
  896. this.RenameProjectFile(newFile);
  897. return VSConstants.S_OK;
  898. }
  899. /// <summary>
  900. /// Gets the automation object for the project node.
  901. /// </summary>
  902. /// <returns>An instance of an EnvDTE.Project implementation object representing the automation object for the project.</returns>
  903. public override object GetAutomationObject()
  904. {
  905. return new Automation.OAProject(this);
  906. }
  907. /// <summary>
  908. /// Closes the project node.
  909. /// </summary>
  910. /// <returns>A success or failure value.</returns>
  911. public override int Close()
  912. {
  913. int hr = VSConstants.S_OK;
  914. try
  915. {
  916. // Walk the tree and close all nodes.
  917. // This has to be done before the project closes, since we want still state available for the ProjectMgr on the nodes
  918. // when nodes are closing.
  919. try
  920. {
  921. CloseAllNodes(this);
  922. }
  923. finally
  924. {
  925. this.Dispose(true);
  926. }
  927. }
  928. catch(COMException e)
  929. {
  930. hr = e.ErrorCode;
  931. }
  932. finally
  933. {
  934. ErrorHandler.ThrowOnFailure(base.Close());
  935. }
  936. this.isClosed = true;
  937. return hr;
  938. }
  939. /// <summary>
  940. /// Sets the service provider from which to access the services.
  941. /// </summary>
  942. /// <param name="site">An instance to an Microsoft.VisualStudio.OLE.Interop object</param>
  943. /// <returns>A success or failure value.</returns>
  944. public override int SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider site)
  945. {
  946. CCITracing.TraceCall();
  947. this.site = new ServiceProvider(site);
  948. if(taskProvider != null)
  949. {
  950. taskProvider.Dispose();
  951. }
  952. taskProvider = new TaskProvider(this.site);
  953. return VSConstants.S_OK;
  954. }
  955. /// <summary>
  956. /// Gets the properties of the project node.
  957. /// </summary>
  958. /// <param name="propId">The __VSHPROPID of the property.</param>
  959. /// <returns>A property dependent value. See: <see cref="__VSHPROPID"/> for details.</returns>
  960. public override object GetProperty(int propId)
  961. {
  962. switch((__VSHPROPID)propId)
  963. {
  964. case __VSHPROPID.VSHPROPID_ConfigurationProvider:
  965. return this.ConfigProvider;
  966. case __VSHPROPID.VSHPROPID_ProjectName:
  967. return this.Caption;
  968. case __VSHPROPID.VSHPROPID_ProjectDir:
  969. return this.ProjectFolder;
  970. case __VSHPROPID.VSHPROPID_TypeName:
  971. return this.ProjectType;
  972. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  973. return this.ShowProjectInSolutionPage;
  974. case __VSHPROPID.VSHPROPID_ExpandByDefault:
  975. return true;
  976. // Use the same icon as if the folder was closed
  977. case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
  978. return GetProperty((int)__VSHPROPID.VSHPROPID_IconIndex);
  979. }
  980. switch((__VSHPROPID2)propId)
  981. {
  982. case __VSHPROPID2.VSHPROPID_SupportsProjectDesigner:
  983. return this.SupportsProjectDesigner;
  984. case __VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList:
  985. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationIndependentPropertyPages());
  986. case __VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList:
  987. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationDependentPropertyPages());
  988. case __VSHPROPID2.VSHPROPID_PriorityPropertyPagesCLSIDList:
  989. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetPriorityProjectDesignerPages());
  990. case __VSHPROPID2.VSHPROPID_Container:
  991. return true;
  992. default:
  993. break;
  994. }
  995. return base.GetProperty(propId);
  996. }
  997. /// <summary>
  998. /// Gets the GUID value of the node.
  999. /// </summary>
  1000. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  1001. /// <param name="guid">The guid to return for the property.</param>
  1002. /// <returns>A success or failure value.</returns>
  1003. public override int GetGuidProperty(int propid, out Guid guid)
  1004. {
  1005. guid = Guid.Empty;
  1006. if((__VSHPROPID)propid == __VSHPROPID.VSHPROPID_ProjectIDGuid)
  1007. {
  1008. guid = this.ProjectIDGuid;
  1009. }
  1010. else if(propid == (int)__VSHPROPID.VSHPROPID_CmdUIGuid)
  1011. {
  1012. guid = this.ProjectGuid;
  1013. }
  1014. else if((__VSHPROPID2)propid == __VSHPROPID2.VSHPROPID_ProjectDesignerEditor && this.SupportsProjectDesigner)
  1015. {
  1016. guid = this.ProjectDesignerEditor;
  1017. }
  1018. else
  1019. {
  1020. base.GetGuidProperty(propid, out guid);
  1021. }
  1022. if(guid.CompareTo(Guid.Empty) == 0)
  1023. {
  1024. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1025. }
  1026. return VSConstants.S_OK;
  1027. }
  1028. /// <summary>
  1029. /// Sets Guid properties for the project node.
  1030. /// </summary>
  1031. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  1032. /// <param name="guid">The guid value to set.</param>
  1033. /// <returns>A success or failure value.</returns>
  1034. public override int SetGuidProperty(int propid, ref Guid guid)
  1035. {
  1036. switch((__VSHPROPID)propid)
  1037. {
  1038. case __VSHPROPID.VSHPROPID_ProjectIDGuid:
  1039. this.ProjectIDGuid = guid;
  1040. return VSConstants.S_OK;
  1041. }
  1042. CCITracing.TraceCall(String.Format(CultureInfo.CurrentCulture, "Property {0} not found", propid));
  1043. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1044. }
  1045. /// <summary>
  1046. /// Removes items from the hierarchy.
  1047. /// </summary>
  1048. /// <devdoc>Project overwrites this.</devdoc>
  1049. public override void Remove(bool removeFromStorage)
  1050. {
  1051. // the project will not be deleted from disk, just removed
  1052. if(removeFromStorage)
  1053. {
  1054. return;
  1055. }
  1056. // Remove the entire project from the solution
  1057. IVsSolution solution = this.Site.GetService(typeof(SVsSolution)) as IVsSolution;
  1058. uint iOption = 1; // SLNSAVEOPT_PromptSave
  1059. ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement(iOption, this, 0));
  1060. }
  1061. /// <summary>
  1062. /// Gets the moniker for the project node. That is the full path of the project file.
  1063. /// </summary>
  1064. /// <returns>The moniker for the project file.</returns>
  1065. public override string GetMkDocument()
  1066. {
  1067. Debug.Assert(!String.IsNullOrEmpty(this.filename));
  1068. Debug.Assert(this.BaseURI != null && !String.IsNullOrEmpty(this.BaseURI.AbsoluteUrl));
  1069. return Path.Combine(this.BaseURI.AbsoluteUrl, this.filename);
  1070. }
  1071. /// <summary>
  1072. /// Disposes the project node object.
  1073. /// </summary>
  1074. /// <param name="disposing">Flag determining ehether it was deterministic or non deterministic clean up.</param>
  1075. protected override void Dispose(bool disposing)
  1076. {
  1077. if(this.isDisposed)
  1078. {
  1079. return;
  1080. }
  1081. try
  1082. {
  1083. try
  1084. {
  1085. this.UnRegisterProject();
  1086. }
  1087. finally
  1088. {
  1089. try
  1090. {
  1091. this.RegisterClipboardNotifications(false);
  1092. }
  1093. finally
  1094. {
  1095. try
  1096. {
  1097. if(this.globalPropertyHandler != null)
  1098. {
  1099. this.globalPropertyHandler.ActiveConfigurationChanged -= new EventHandler<ActiveConfigurationChangedEventArgs>(this.OnHandleConfigurationRelatedGlobalProperties);
  1100. this.globalPropertyHandler.Dispose();
  1101. }
  1102. if(this.projectEventsProvider != null)
  1103. {
  1104. this.projectEventsProvider.AfterProjectFileOpened -= this.OnAfterProjectOpen;
  1105. }
  1106. if(this.taskProvider != null)
  1107. {
  1108. taskProvider.Tasks.Clear();
  1109. this.taskProvider.Dispose();
  1110. this.taskProvider = null;
  1111. }
  1112. if(buildLogger != null)
  1113. {
  1114. buildLogger = null;
  1115. }
  1116. this.site = null;
  1117. }
  1118. finally
  1119. {
  1120. if(this.buildEngine != null)
  1121. {
  1122. this.buildEngine.UnregisterAllLoggers();
  1123. this.buildEngine = null;
  1124. }
  1125. }
  1126. }
  1127. }
  1128. if(this.buildProject != null)
  1129. {
  1130. this.buildProject.ParentEngine.UnloadProject(this.buildProject);
  1131. this.buildProject = null;
  1132. }
  1133. if(null != imageHandler)
  1134. {
  1135. imageHandler.Close();
  1136. imageHandler = null;
  1137. }
  1138. }
  1139. finally
  1140. {
  1141. base.Dispose(disposing);
  1142. this.isDisposed = true;
  1143. }
  1144. }
  1145. /// <summary>
  1146. /// Handles command status on the project node. If a command cannot be handled then the base should be called.
  1147. /// </summary>
  1148. /// <param name="cmdGroup">A unique identifier of the command group. The pguidCmdGroup parameter can be NULL to specify the standard group.</param>
  1149. /// <param name="cmd">The command to query status for.</param>
  1150. /// <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>
  1151. /// <param name="result">An out parameter specifying the QueryStatusResult of the command.</param>
  1152. /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
  1153. protected override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result)
  1154. {
  1155. if(cmdGroup == VsMenus.guidStandardCommandSet97)
  1156. {
  1157. switch((VsCommands)cmd)
  1158. {
  1159. case VsCommands.Copy:
  1160. case VsCommands.Paste:
  1161. case VsCommands.Cut:
  1162. case VsCommands.Rename:
  1163. case VsCommands.Exit:
  1164. case VsCommands.ProjectSettings:
  1165. case VsCommands.BuildSln:
  1166. case VsCommands.UnloadProject:
  1167. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1168. return VSConstants.S_OK;
  1169. case VsCommands.ViewForm:
  1170. if(this.HasDesigner)
  1171. {
  1172. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1173. return VSConstants.S_OK;
  1174. }
  1175. break;
  1176. case VsCommands.CancelBuild:
  1177. result |= QueryStatusResult.SUPPORTED;
  1178. if(this.buildInProcess)
  1179. result |= QueryStatusResult.ENABLED;
  1180. else
  1181. result |= QueryStatusResult.INVISIBLE;
  1182. return VSConstants.S_OK;
  1183. case VsCommands.NewFolder:
  1184. case VsCommands.AddNewItem:
  1185. case VsCommands.AddExistingItem:
  1186. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1187. return VSConstants.S_OK;
  1188. case VsCommands.SetStartupProject:
  1189. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1190. return VSConstants.S_OK;
  1191. }
  1192. }
  1193. else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
  1194. {
  1195. switch((VsCommands2K)cmd)
  1196. {
  1197. case VsCommands2K.ADDREFERENCE:
  1198. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1199. return VSConstants.S_OK;
  1200. case VsCommands2K.EXCLUDEFROMPROJECT:
  1201. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
  1202. return VSConstants.S_OK;
  1203. }
  1204. }
  1205. else
  1206. {
  1207. return (int)OleConstants.OLECMDERR_E_UNKNOWNGROUP;
  1208. }
  1209. return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
  1210. }
  1211. /// <summary>
  1212. /// Handles command execution.
  1213. /// </summary>
  1214. /// <param name="cmdGroup">Unique identifier of the command group</param>
  1215. /// <param name="cmd">The command to be executed.</param>
  1216. /// <param name="nCmdexecopt">Values describe how the object should execute the command.</param>
  1217. /// <param name="pvaIn">Pointer to a VARIANTARG structure containing input arguments. Can be NULL</param>
  1218. /// <param name="pvaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
  1219. /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
  1220. protected override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
  1221. {
  1222. if(cmdGroup == VsMenus.guidStandardCommandSet97)
  1223. {
  1224. switch((VsCommands)cmd)
  1225. {
  1226. case VsCommands.UnloadProject:
  1227. return this.UnloadProject();
  1228. case VsCommands.CleanSel:
  1229. case VsCommands.CleanCtx:
  1230. return this.CleanProject();
  1231. }
  1232. }
  1233. else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
  1234. {
  1235. switch((VsCommands2K)cmd)
  1236. {
  1237. case VsCommands2K.ADDREFERENCE:
  1238. return this.AddProjectReference();
  1239. case VsCommands2K.ADDWEBREFERENCE:
  1240. case VsCommands2K.ADDWEBREFERENCECTX:
  1241. return this.AddWebReference();
  1242. }
  1243. }
  1244. return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
  1245. }
  1246. /// <summary>
  1247. /// Get the boolean value for the deletion of a project item
  1248. /// </summary>
  1249. /// <param name="deleteOperation">A flag that specifies the type of delete operation (delete from storage or remove from project)</param>
  1250. /// <returns>true if item can be deleted from project</returns>
  1251. protected override bool CanDeleteItem(__VSDELETEITEMOPERATION deleteOperation)
  1252. {
  1253. if(deleteOperation == __VSDELETEITEMOPERATION.DELITEMOP_RemoveFromProject)
  1254. {
  1255. return true;
  1256. }
  1257. return false;
  1258. }
  1259. /// <summary>
  1260. /// Returns a specific Document manager to handle opening and closing of the Project(Application) Designer if projectdesigner is supported.
  1261. /// </summary>
  1262. /// <returns>Document manager object</returns>
  1263. protected internal override DocumentManager GetDocumentManager()
  1264. {
  1265. if(this.SupportsProjectDesigner)
  1266. {
  1267. return new ProjectDesignerDocumentManager(this);
  1268. }
  1269. return null;
  1270. }
  1271. #endregion
  1272. #region virtual methods
  1273. /// <summary>
  1274. /// Executes a wizard.
  1275. /// </summary>
  1276. /// <param name="parentNode">The node to which the wizard should add item(s).</param>
  1277. /// <param name="itemName">The name of the file that the user typed in.</param>
  1278. /// <param name="wizardToRun">The name of the wizard to run.</param>
  1279. /// <param name="dlgOwner">The owner of the dialog box.</param>
  1280. /// <returns>A VSADDRESULT enum value describing success or failure.</returns>
  1281. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily"), SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dlg")]
  1282. public virtual VSADDRESULT RunWizard(HierarchyNode parentNode, string itemName, string wizardToRun, IntPtr dlgOwner)
  1283. {
  1284. Debug.Assert(!String.IsNullOrEmpty(itemName), "The Add item dialog was passing in a null or empty item to be added to the hierrachy.");
  1285. Debug.Assert(!String.IsNullOrEmpty(this.ProjectFolder), "The Project Folder is not specified for this project.");
  1286. // We just validate for length, since we assume other validation has been performed by the dlgOwner.
  1287. if(this.ProjectFolder.Length + itemName.Length + 1 > NativeMethods.MAX_PATH)
  1288. {
  1289. string errorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.PathTooLong, CultureInfo.CurrentUICulture), itemName);
  1290. if(!Utilities.IsInAutomationFunction(this.Site))
  1291. {
  1292. string title = null;
  1293. OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL;
  1294. OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK;
  1295. OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST;
  1296. VsShellUtilities.ShowMessageBox(this.Site, title, errorMessage, icon, buttons, defaultButton);
  1297. return VSADDRESULT.ADDRESULT_Failure;
  1298. }
  1299. else
  1300. {
  1301. throw new InvalidOperationException(errorMessage);
  1302. }
  1303. }
  1304. // Build up the ContextParams safearray
  1305. // [0] = Wizard type guid (bstr)
  1306. // [1] = Project name (bstr)
  1307. // [2] = ProjectItems collection (bstr)
  1308. // [3] = Local Directory (bstr)
  1309. // [4] = Filename the user typed (bstr)
  1310. // [5] = Product install Directory (bstr)
  1311. // [6] = Run silent (bool)
  1312. object[] contextParams = new object[7];
  1313. contextParams[0] = EnvDTE.Constants.vsWizardAddItem;
  1314. contextParams[1] = this.Caption;
  1315. object automationObject = parentNode.GetAutomationObject();
  1316. if(automationObject is EnvDTE.Project)
  1317. {
  1318. EnvDTE.Project project = (EnvDTE.Project)automationObject;
  1319. contextParams[2] = project.ProjectItems;
  1320. }
  1321. else
  1322. {
  1323. // This would normally be a folder unless it is an item with subitems
  1324. ProjectItem item = (ProjectItem)automationObject;
  1325. contextParams[2] = item.ProjectItems;
  1326. }
  1327. contextParams[3] = this.ProjectFolder;
  1328. contextParams[4] = itemName;
  1329. object objInstallationDir = null;
  1330. IVsShell shell = (IVsShell)this.GetService(typeof(IVsShell));
  1331. ErrorHandler.ThrowOnFailure(shell.GetProperty((int)__VSSPROPID.VSSPROPID_InstallDirectory, out objInstallationDir));
  1332. string installDir = (string)objInstallationDir;
  1333. // append a '\' to the install dir to mimic what the shell does (though it doesn't add one to destination dir)
  1334. if(!installDir.EndsWith("\\", StringComparison.Ordinal))
  1335. {
  1336. installDir += "\\";
  1337. }
  1338. contextParams[5] = installDir;
  1339. contextParams[6] = true;
  1340. IVsExtensibility3 ivsExtensibility = this.GetService(typeof(IVsExtensibility)) as IVsExtensibility3;
  1341. Debug.Assert(ivsExtensibility != null, "Failed to get IVsExtensibility3 service");
  1342. if(ivsExtensibility == null)
  1343. {
  1344. return VSADDRESULT.ADDRESULT_Failure;
  1345. }
  1346. // Determine if we have the trust to run this wizard.
  1347. IVsDetermineWizardTrust wizardTrust = this.GetService(typeof(SVsDetermineWizardTrust)) as IVsDetermineWizardTrust;
  1348. if(wizardTrust != null)
  1349. {
  1350. Guid guidProjectAdding = Guid.Empty;
  1351. ErrorHandler.ThrowOnFailure(wizardTrust.OnWizardInitiated(wizardToRun, ref guidProjectAdding));
  1352. }
  1353. int wizResultAsInt;
  1354. try
  1355. {
  1356. Array contextParamsAsArray = contextParams;
  1357. int result = ivsExtensibility.RunWizardFile(wizardToRun, (int)dlgOwner, ref contextParamsAsArray, out wizResultAsInt);
  1358. if(!ErrorHandler.Succeeded(result) && result != VSConstants.OLE_E_PROMPTSAVECANCELLED)
  1359. {
  1360. ErrorHandler.ThrowOnFailure(result);
  1361. }
  1362. }
  1363. finally
  1364. {
  1365. if(wizardTrust != null)
  1366. {
  1367. ErrorHandler.ThrowOnFailure(wizardTrust.OnWizardCompleted());
  1368. }
  1369. }
  1370. EnvDTE.wizardResult wizardResult = (EnvDTE.wizardResult)wizResultAsInt;
  1371. switch(wizardResult)
  1372. {
  1373. default:
  1374. return VSADDRESULT.ADDRESULT_Cancel;
  1375. case wizardResult.wizardResultSuccess:
  1376. return VSADDRESULT.ADDRESULT_Success;
  1377. case wizardResult.wizardResultFailure:
  1378. return VSADDRESULT.ADDRESULT_Failure;
  1379. }
  1380. }
  1381. /// <summary>
  1382. /// Override this method if you want to modify the behavior of the Add Reference dialog
  1383. /// By example you could change which pages are visible and which is visible by default.
  1384. /// </summary>
  1385. /// <returns></returns>
  1386. public virtual int AddProjectReference()
  1387. {
  1388. CCITracing.TraceCall();
  1389. IVsComponentSelectorDlg componentDialog;
  1390. Guid guidEmpty = Guid.Empty;
  1391. VSCOMPONENTSELECTORTABINIT[] tabInit = new VSCOMPONENTSELECTORTABINIT[2];
  1392. string strBrowseLocations = Path.GetDirectoryName(this.BaseURI.Uri.LocalPath);
  1393. tabInit[0].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
  1394. // Tell the Add Reference dialog to call hierarchies GetProperty with the following
  1395. // propID to enablefiltering out ourself from the Project to Project reference
  1396. tabInit[0].varTabInitInfo = (int)__VSHPROPID.VSHPROPID_ShowProjInSolutionPage;
  1397. tabInit[0].guidTab = VSConstants.GUID_SolutionPage;
  1398. // Add the Browse for file page
  1399. tabInit[1].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
  1400. tabInit[1].guidTab = VSConstants.GUID_BrowseFilePage;
  1401. tabInit[1].varTabInitInfo = 0;
  1402. componentDialog = this.GetService(typeof(IVsComponentSelectorDlg)) as IVsComponentSelectorDlg;
  1403. try
  1404. {
  1405. // call the container to open the add reference dialog.
  1406. if(componentDialog != null)
  1407. {
  1408. // Let the project know not to show itself in the Add Project Reference Dialog page
  1409. this.ShowProjectInSolutionPage = false;
  1410. // call the container to open the add reference dialog.
  1411. string browseFilters = "Component files (*.dll)" + "\0*.dll\0";
  1412. ErrorHandler.ThrowOnFailure(componentDialog.ComponentSelectorDlg(
  1413. (System.UInt32)(__VSCOMPSELFLAGS.VSCOMSEL_MultiSelectMode | __VSCOMPSELFLAGS.VSCOMSEL_IgnoreMachineName),
  1414. (IVsComponentUser)this,
  1415. SR.GetString(SR.AddReferenceDialogTitle, CultureInfo.CurrentUICulture), // Title
  1416. "VS.AddReference", // Help topic
  1417. ref guidEmpty,
  1418. ref guidEmpty,
  1419. String.Empty, // Machine Name
  1420. (uint)tabInit.Length,
  1421. tabInit,
  1422. browseFilters,
  1423. ref strBrowseLocations));
  1424. }
  1425. }
  1426. catch(COMException e)
  1427. {
  1428. Trace.WriteLine("Exception : " + e.Message);
  1429. return e.ErrorCode;
  1430. }
  1431. finally
  1432. {
  1433. // Let the project know it can show itself in the Add Project Reference Dialog page
  1434. this.ShowProjectInSolutionPage = true;
  1435. }
  1436. return VSConstants.S_OK;
  1437. }
  1438. /// <summary>
  1439. /// Returns the Compiler associated to the project
  1440. /// </summary>
  1441. /// <returns>Null</returns>
  1442. public virtual ICodeCompiler GetCompiler()
  1443. {
  1444. return null;
  1445. }
  1446. /// <summary>
  1447. /// Override this method if you have your own project specific
  1448. /// subclass of ProjectOptions
  1449. /// </summary>
  1450. /// <returns>This method returns a new instance of the ProjectOptions base class.</returns>
  1451. public virtual ProjectOptions CreateProjectOptions()
  1452. {
  1453. return new ProjectOptions();
  1454. }
  1455. /// <summary>
  1456. /// Loads a project file. Called from the factory CreateProject to load the project.
  1457. /// </summary>
  1458. /// <param name="fileName">File name of the project that will be created. </param>
  1459. /// <param name="location">Location where the project will be created.</param>
  1460. /// <param name="name">If applicable, the name of the template to use when cloning a new project.</param>
  1461. /// <param name="flags">Set of flag values taken from the VSCREATEPROJFLAGS enumeration.</param>
  1462. /// <param name="iidProject">Identifier of the interface that the caller wants returned. </param>
  1463. /// <param name="canceled">An out parameter specifying if the project creation was canceled</param>
  1464. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "iid")]
  1465. public virtual void Load(string fileName, string location, string name, uint flags, ref Guid iidProject, out int canceled)
  1466. {
  1467. try
  1468. {
  1469. this.disableQueryEdit = true;
  1470. // set up internal members and icons
  1471. canceled = 0;
  1472. this.ProjectMgr = this;
  1473. this.isNewProject = false;
  1474. // We need to set the project guid before we check the project for security.
  1475. if((flags & (uint)__VSCREATEPROJFLAGS.CPF_CLONEFILE) == (uint)__VSCREATEPROJFLAGS.CPF_CLONEFILE)
  1476. {
  1477. // we need to generate a new guid for the project
  1478. this.projectIdGuid = Guid.NewGuid();
  1479. }
  1480. else
  1481. {
  1482. this.SetProjectGuidFromProjectFile();
  1483. }
  1484. ProjectLoadOption loadOption = this.IsProjectSecure();
  1485. if(loadOption == ProjectLoadOption.DonNotLoad)
  1486. {
  1487. canceled = 1;
  1488. return;
  1489. }
  1490. else if(loadOption == ProjectLoadOption.LoadNormally)
  1491. {
  1492. this.hasPassedSecurityChecks = true;
  1493. }
  1494. // This is almost a No op if the engine has already been instantiated in the factory.
  1495. this.buildEngine = Utilities.InitializeMsBuildEngine(this.buildEngine, this.Site);
  1496. Debug.Assert(this.globalPropertyHandler != null, "The global property handler should have been initialized at this point");
  1497. // Now register with the configuration change event.
  1498. this.globalPropertyHandler.ActiveConfigurationChanged += new EventHandler<ActiveConfigurationChangedEventArgs>(this.OnHandleConfigurationRelatedGlobalProperties);
  1499. // based on the passed in flags, this either reloads/loads a project, or tries to create a new one
  1500. // now we create a new project... we do that by loading the template and then saving und…

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