| Index: experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectConfig.cs
|
| diff --git a/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectConfig.cs b/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectConfig.cs
|
| deleted file mode 100644
|
| index 96237a1ac3a821285c3029003fc502ddb697dd47..0000000000000000000000000000000000000000
|
| --- a/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectConfig.cs
|
| +++ /dev/null
|
| @@ -1,950 +0,0 @@
|
| -/// Copyright (c) Microsoft Corporation. All rights reserved.
|
| -
|
| -using System;
|
| -using System.Collections.Generic;
|
| -using System.Diagnostics;
|
| -using System.Diagnostics.CodeAnalysis;
|
| -using System.Globalization;
|
| -using System.IO;
|
| -using System.Runtime.InteropServices;
|
| -using Microsoft.VisualStudio;
|
| -using Microsoft.VisualStudio.OLE.Interop;
|
| -using Microsoft.VisualStudio.Shell;
|
| -//#define ConfigTrace
|
| -using Microsoft.VisualStudio.Shell.Interop;
|
| -using MSBuild = Microsoft.Build.BuildEngine;
|
| -
|
| -namespace Microsoft.VisualStudio.Project
|
| -{
|
| - [CLSCompliant(false), ComVisible(true)]
|
| - public class ProjectConfig :
|
| - IVsCfg,
|
| - IVsProjectCfg,
|
| - IVsProjectCfg2,
|
| - IVsProjectFlavorCfg,
|
| - IVsDebuggableProjectCfg,
|
| - ISpecifyPropertyPages,
|
| - IVsSpecifyProjectDesignerPages,
|
| - IVsCfgBrowseObject
|
| - {
|
| - #region constants
|
| - internal const string Debug = "Debug";
|
| - internal const string Release = "Release";
|
| - internal const string AnyCPU = "AnyCPU";
|
| - #endregion
|
| -
|
| - #region fields
|
| - private ProjectNode project;
|
| - private string configName;
|
| - private MSBuild.BuildPropertyGroup currentConfig;
|
| - private List<OutputGroup> outputGroups;
|
| - private IProjectConfigProperties configurationProperties;
|
| - private IVsProjectFlavorCfg flavoredCfg;
|
| - private BuildableProjectConfig buildableCfg;
|
| - #endregion
|
| -
|
| - #region properties
|
| - public ProjectNode ProjectMgr
|
| - {
|
| - get
|
| - {
|
| - return this.project;
|
| - }
|
| - }
|
| -
|
| - public string ConfigName
|
| - {
|
| - get
|
| - {
|
| - return this.configName;
|
| - }
|
| - set
|
| - {
|
| - this.configName = value;
|
| - }
|
| - }
|
| -
|
| - public virtual object ConfigurationProperties
|
| - {
|
| - get
|
| - {
|
| - if (this.configurationProperties == null)
|
| - {
|
| - this.configurationProperties = new ProjectConfigProperties(this);
|
| - }
|
| - return this.configurationProperties;
|
| - }
|
| - }
|
| -
|
| - protected IList<OutputGroup> OutputGroups
|
| - {
|
| - get
|
| - {
|
| - if (null == this.outputGroups)
|
| - {
|
| - // Initialize output groups
|
| - this.outputGroups = new List<OutputGroup>();
|
| -
|
| - // Get the list of group names from the project.
|
| - // The main reason we get it from the project is to make it easier for someone to modify
|
| - // it by simply overriding that method and providing the correct MSBuild target(s).
|
| - IList<KeyValuePair<string, string>> groupNames = project.GetOutputGroupNames();
|
| -
|
| - if (groupNames != null)
|
| - {
|
| - // Populate the output array
|
| - foreach (KeyValuePair<string, string> group in groupNames)
|
| - {
|
| - OutputGroup outputGroup = CreateOutputGroup(project, group);
|
| - this.outputGroups.Add(outputGroup);
|
| - }
|
| - }
|
| -
|
| - }
|
| - return this.outputGroups;
|
| - }
|
| - }
|
| - #endregion
|
| -
|
| - #region ctors
|
| - public ProjectConfig(ProjectNode project, string configuration)
|
| - {
|
| - this.project = project;
|
| - this.configName = configuration;
|
| -
|
| -
|
| - // Because the project can be aggregated by a flavor, we need to make sure
|
| - // we get the outer most implementation of that interface (hence: project --> IUnknown --> Interface)
|
| - IntPtr projectUnknown = Marshal.GetIUnknownForObject(this.ProjectMgr);
|
| - try
|
| - {
|
| - IVsProjectFlavorCfgProvider flavorCfgProvider = (IVsProjectFlavorCfgProvider)Marshal.GetTypedObjectForIUnknown(projectUnknown, typeof(IVsProjectFlavorCfgProvider));
|
| - ErrorHandler.ThrowOnFailure(flavorCfgProvider.CreateProjectFlavorCfg(this, out flavoredCfg));
|
| - if (flavoredCfg == null)
|
| - throw new COMException();
|
| - }
|
| - finally
|
| - {
|
| - if (projectUnknown != IntPtr.Zero)
|
| - Marshal.Release(projectUnknown);
|
| - }
|
| - // if the flavored object support XML fragment, initialize it
|
| - IPersistXMLFragment persistXML = flavoredCfg as IPersistXMLFragment;
|
| - if (null != persistXML)
|
| - {
|
| - this.project.LoadXmlFragment(persistXML, this.DisplayName);
|
| - }
|
| - }
|
| - #endregion
|
| -
|
| - #region methods
|
| - protected virtual OutputGroup CreateOutputGroup(ProjectNode project, KeyValuePair<string, string> group)
|
| - {
|
| - OutputGroup outputGroup = new OutputGroup(group.Key, group.Value, project, this);
|
| - return outputGroup;
|
| - }
|
| -
|
| - public void PrepareBuild(bool clean)
|
| - {
|
| - project.PrepareBuild(this.configName, clean);
|
| - }
|
| -
|
| - public virtual string GetConfigurationProperty(string propertyName, bool resetCache)
|
| - {
|
| - MSBuild.BuildProperty property = GetMsBuildProperty(propertyName, resetCache);
|
| - if (property == null)
|
| - return null;
|
| -
|
| - return property.FinalValue;
|
| - }
|
| -
|
| - public virtual void SetConfigurationProperty(string propertyName, string propertyValue)
|
| - {
|
| - if (!this.project.QueryEditProjectFile(false))
|
| - {
|
| - throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
|
| - }
|
| -
|
| - string condition = String.Format(CultureInfo.InvariantCulture, ConfigProvider.configString, this.ConfigName);
|
| - this.project.BuildProject.SetProperty(propertyName, propertyValue, condition);
|
| -
|
| - // property cache will need to be updated
|
| - this.currentConfig = null;
|
| - // Signal the output groups that something is changed
|
| - foreach (OutputGroup group in this.OutputGroups)
|
| - {
|
| - group.InvalidateGroup();
|
| - }
|
| - this.project.SetProjectFileDirty(true);
|
| -
|
| - return;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// If flavored, and if the flavor config can be dirty, ask it if it is dirty
|
| - /// </summary>
|
| - /// <param name="storageType">Project file or user file</param>
|
| - /// <returns>0 = not dirty</returns>
|
| - internal int IsFlavorDirty(_PersistStorageType storageType)
|
| - {
|
| - int isDirty = 0;
|
| - if (this.flavoredCfg != null && this.flavoredCfg is IPersistXMLFragment)
|
| - {
|
| - ErrorHandler.ThrowOnFailure(((IPersistXMLFragment)this.flavoredCfg).IsFragmentDirty((uint)storageType, out isDirty));
|
| - }
|
| - return isDirty;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// If flavored, ask the flavor if it wants to provide an XML fragment
|
| - /// </summary>
|
| - /// <param name="flavor">Guid of the flavor</param>
|
| - /// <param name="storageType">Project file or user file</param>
|
| - /// <param name="fragment">Fragment that the flavor wants to save</param>
|
| - /// <returns>HRESULT</returns>
|
| - internal int GetXmlFragment(Guid flavor, _PersistStorageType storageType, out string fragment)
|
| - {
|
| - fragment = null;
|
| - int hr = VSConstants.S_OK;
|
| - if (this.flavoredCfg != null && this.flavoredCfg is IPersistXMLFragment)
|
| - {
|
| - Guid flavorGuid = flavor;
|
| - hr = ((IPersistXMLFragment)this.flavoredCfg).Save(ref flavorGuid, (uint)storageType, out fragment, 1);
|
| - }
|
| - return hr;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsSpecifyPropertyPages
|
| - public void GetPages(CAUUID[] pages)
|
| - {
|
| - this.GetCfgPropertyPages(pages);
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsSpecifyProjectDesignerPages
|
| - /// <summary>
|
| - /// Implementation of the IVsSpecifyProjectDesignerPages. It will retun the pages that are configuration dependent.
|
| - /// </summary>
|
| - /// <param name="pages">The pages to return.</param>
|
| - /// <returns>VSConstants.S_OK</returns>
|
| - public virtual int GetProjectDesignerPages(CAUUID[] pages)
|
| - {
|
| - this.GetCfgPropertyPages(pages);
|
| - return VSConstants.S_OK;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsCfg methods
|
| - /// <summary>
|
| - /// The display name is a two part item
|
| - /// first part is the config name, 2nd part is the platform name
|
| - /// </summary>
|
| - public virtual int get_DisplayName(out string name)
|
| - {
|
| - name = DisplayName;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - private string DisplayName
|
| - {
|
| - get
|
| - {
|
| - string name;
|
| - string[] platform = new string[1];
|
| - uint[] actual = new uint[1];
|
| - name = this.configName;
|
| - // currently, we only support one platform, so just add it..
|
| - IVsCfgProvider provider;
|
| - ErrorHandler.ThrowOnFailure(project.GetCfgProvider(out provider));
|
| - ErrorHandler.ThrowOnFailure(((IVsCfgProvider2)provider).GetPlatformNames(1, platform, actual));
|
| - if (!string.IsNullOrEmpty(platform[0]))
|
| - {
|
| - name += "|" + platform[0];
|
| - }
|
| - return name;
|
| - }
|
| - }
|
| - public virtual int get_IsDebugOnly(out int fDebug)
|
| - {
|
| - fDebug = 0;
|
| - if (this.configName == "Debug")
|
| - {
|
| - fDebug = 1;
|
| - }
|
| - return VSConstants.S_OK;
|
| - }
|
| - public virtual int get_IsReleaseOnly(out int fRelease)
|
| - {
|
| - CCITracing.TraceCall();
|
| - fRelease = 0;
|
| - if (this.configName == "Release")
|
| - {
|
| - fRelease = 1;
|
| - }
|
| - return VSConstants.S_OK;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsProjectCfg methods
|
| - public virtual int EnumOutputs(out IVsEnumOutputs eo)
|
| - {
|
| - CCITracing.TraceCall();
|
| - eo = null;
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - public virtual int get_BuildableProjectCfg(out IVsBuildableProjectCfg pb)
|
| - {
|
| - CCITracing.TraceCall();
|
| - if (buildableCfg == null)
|
| - buildableCfg = new BuildableProjectConfig(this);
|
| - pb = buildableCfg;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_CanonicalName(out string name)
|
| - {
|
| - return ((IVsCfg)this).get_DisplayName(out name);
|
| - }
|
| -
|
| - public virtual int get_IsPackaged(out int pkgd)
|
| - {
|
| - CCITracing.TraceCall();
|
| - pkgd = 0;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_IsSpecifyingOutputSupported(out int f)
|
| - {
|
| - CCITracing.TraceCall();
|
| - f = 1;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_Platform(out Guid platform)
|
| - {
|
| - CCITracing.TraceCall();
|
| - platform = Guid.Empty;
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - public virtual int get_ProjectCfgProvider(out IVsProjectCfgProvider p)
|
| - {
|
| - CCITracing.TraceCall();
|
| - p = null;
|
| - IVsCfgProvider cfgProvider = null;
|
| - this.project.GetCfgProvider(out cfgProvider);
|
| - if (cfgProvider != null)
|
| - {
|
| - p = cfgProvider as IVsProjectCfgProvider;
|
| - }
|
| -
|
| - return (null == p) ? VSConstants.E_NOTIMPL : VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_RootURL(out string root)
|
| - {
|
| - CCITracing.TraceCall();
|
| - root = null;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_TargetCodePage(out uint target)
|
| - {
|
| - CCITracing.TraceCall();
|
| - target = (uint)System.Text.Encoding.Default.CodePage;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_UpdateSequenceNumber(ULARGE_INTEGER[] li)
|
| - {
|
| - CCITracing.TraceCall();
|
| - li[0] = new ULARGE_INTEGER();
|
| - li[0].QuadPart = 0;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int OpenOutput(string name, out IVsOutput output)
|
| - {
|
| - CCITracing.TraceCall();
|
| - output = null;
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsDebuggableProjectCfg methods
|
| - /// <summary>
|
| - /// Called by the vs shell to start debugging (managed or unmanaged).
|
| - /// Override this method to support other debug engines.
|
| - /// </summary>
|
| - /// <param name="grfLaunch">A flag that determines the conditions under which to start the debugger. For valid grfLaunch values, see __VSDBGLAUNCHFLAGS</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code</returns>
|
| - public virtual int DebugLaunch(uint grfLaunch)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - try
|
| - {
|
| - VsDebugTargetInfo info = new VsDebugTargetInfo();
|
| - info.cbSize = (uint)Marshal.SizeOf(info);
|
| - info.dlo = Microsoft.VisualStudio.Shell.Interop.DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
|
| -
|
| - // On first call, reset the cache, following calls will use the cached values
|
| - string property = GetConfigurationProperty("StartProgram", true);
|
| - if (string.IsNullOrEmpty(property))
|
| - {
|
| - info.bstrExe = this.project.GetOutputAssembly(this.ConfigName);
|
| - }
|
| - else
|
| - {
|
| - info.bstrExe = property;
|
| - }
|
| -
|
| - property = GetConfigurationProperty("WorkingDirectory", false);
|
| - if (string.IsNullOrEmpty(property))
|
| - {
|
| - info.bstrCurDir = Path.GetDirectoryName(info.bstrExe);
|
| - }
|
| - else
|
| - {
|
| - info.bstrCurDir = property;
|
| - }
|
| -
|
| - property = GetConfigurationProperty("CmdArgs", false);
|
| - if (!string.IsNullOrEmpty(property))
|
| - {
|
| - info.bstrArg = property;
|
| - }
|
| -
|
| - property = GetConfigurationProperty("RemoteDebugMachine", false);
|
| - if (property != null && property.Length > 0)
|
| - {
|
| - info.bstrRemoteMachine = property;
|
| - }
|
| -
|
| - info.fSendStdoutToOutputWindow = 0;
|
| -
|
| - property = GetConfigurationProperty("EnableUnmanagedDebugging", false);
|
| - if (property != null && string.Compare(property, "true", StringComparison.OrdinalIgnoreCase) == 0)
|
| - {
|
| - //Set the unmanged debugger
|
| - //TODO change to vsconstant when it is available in VsConstants (guidNativeOnlyEng was the old name, maybe it has got a new name)
|
| - info.clsidCustom = new Guid("{3B476D35-A401-11D2-AAD4-00C04F990171}");
|
| - }
|
| - else
|
| - {
|
| - //Set the managed debugger
|
| - info.clsidCustom = VSConstants.CLSID_ComPlusOnlyDebugEngine;
|
| - }
|
| - info.grfLaunch = grfLaunch;
|
| - VsShellUtilities.LaunchDebugger(this.project.Site, info);
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| -
|
| - return Marshal.GetHRForException(e);
|
| - }
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Determines whether the debugger can be launched, given the state of the launch flags.
|
| - /// </summary>
|
| - /// <param name="flags">Flags that determine the conditions under which to launch the debugger.
|
| - /// For valid grfLaunch values, see __VSDBGLAUNCHFLAGS or __VSDBGLAUNCHFLAGS2.</param>
|
| - /// <param name="fCanLaunch">true if the debugger can be launched, otherwise false</param>
|
| - /// <returns>S_OK if the method succeeds, otherwise an error code</returns>
|
| - public virtual int QueryDebugLaunch(uint flags, out int fCanLaunch)
|
| - {
|
| - CCITracing.TraceCall();
|
| - string assembly = this.project.GetAssemblyName(this.ConfigName);
|
| - fCanLaunch = (assembly != null && assembly.ToUpperInvariant().EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) ? 1 : 0;
|
| - if (fCanLaunch == 0)
|
| - {
|
| - string property = GetConfigurationProperty("StartProgram", true);
|
| - fCanLaunch = (property != null && property.Length > 0) ? 1 : 0;
|
| - }
|
| - return VSConstants.S_OK;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsProjectCfg2 Members
|
| -
|
| - public virtual int OpenOutputGroup(string szCanonicalName, out IVsOutputGroup ppIVsOutputGroup)
|
| - {
|
| - ppIVsOutputGroup = null;
|
| - // Search through our list of groups to find the one they are looking forgroupName
|
| - foreach (OutputGroup group in OutputGroups)
|
| - {
|
| - string groupName;
|
| - group.get_CanonicalName(out groupName);
|
| - if (String.Compare(groupName, szCanonicalName, StringComparison.OrdinalIgnoreCase) == 0)
|
| - {
|
| - ppIVsOutputGroup = group;
|
| - break;
|
| - }
|
| - }
|
| - return (ppIVsOutputGroup != null) ? VSConstants.S_OK : VSConstants.E_FAIL;
|
| - }
|
| -
|
| - public virtual int OutputsRequireAppRoot(out int pfRequiresAppRoot)
|
| - {
|
| - pfRequiresAppRoot = 0;
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - public virtual int get_CfgType(ref Guid iidCfg, out IntPtr ppCfg)
|
| - {
|
| - // Delegate to the flavored configuration (to enable a flavor to take control)
|
| - // Since we can be asked for Configuration we don't support, avoid throwing and return the HRESULT directly
|
| - int hr = flavoredCfg.get_CfgType(ref iidCfg, out ppCfg);
|
| -
|
| - return hr;
|
| - }
|
| -
|
| - public virtual int get_IsPrivate(out int pfPrivate)
|
| - {
|
| - pfPrivate = 0;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_OutputGroups(uint celt, IVsOutputGroup[] rgpcfg, uint[] pcActual)
|
| - {
|
| - // Are they only asking for the number of groups?
|
| - if (celt == 0)
|
| - {
|
| - if ((null == pcActual) || (0 == pcActual.Length))
|
| - {
|
| - throw new ArgumentNullException("pcActual");
|
| - }
|
| - pcActual[0] = (uint)OutputGroups.Count;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - // Check that the array of output groups is not null
|
| - if ((null == rgpcfg) || (rgpcfg.Length == 0))
|
| - {
|
| - throw new ArgumentNullException("rgpcfg");
|
| - }
|
| -
|
| - // Fill the array with our output groups
|
| - uint count = 0;
|
| - foreach (OutputGroup group in OutputGroups)
|
| - {
|
| - if (rgpcfg.Length > count && celt > count && group != null)
|
| - {
|
| - rgpcfg[count] = group;
|
| - ++count;
|
| - }
|
| - }
|
| -
|
| - if (pcActual != null && pcActual.Length > 0)
|
| - pcActual[0] = count;
|
| -
|
| - // If the number asked for does not match the number returned, return S_FALSE
|
| - return (count == celt) ? VSConstants.S_OK : VSConstants.S_FALSE;
|
| - }
|
| -
|
| - public virtual int get_VirtualRoot(out string pbstrVRoot)
|
| - {
|
| - pbstrVRoot = null;
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - #endregion
|
| -
|
| - #region IVsCfgBrowseObject
|
| - /// <summary>
|
| - /// Maps back to the configuration corresponding to the browse object.
|
| - /// </summary>
|
| - /// <param name="cfg">The IVsCfg object represented by the browse object</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public virtual int GetCfg(out IVsCfg cfg)
|
| - {
|
| - cfg = this;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Maps back to the hierarchy or project item object corresponding to the browse object.
|
| - /// </summary>
|
| - /// <param name="hier">Reference to the hierarchy object.</param>
|
| - /// <param name="itemid">Reference to the project item.</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public virtual int GetProjectItem(out IVsHierarchy hier, out uint itemid)
|
| - {
|
| - if (this.project == null || this.project.NodeProperties == null)
|
| - {
|
| - throw new InvalidOperationException();
|
| - }
|
| - return this.project.NodeProperties.GetProjectItem(out hier, out itemid);
|
| - }
|
| - #endregion
|
| -
|
| - #region helper methods
|
| - /// <summary>
|
| - /// Splits the canonical configuration name into platform and configuration name.
|
| - /// </summary>
|
| - /// <param name="canonicalName">The canonicalName name.</param>
|
| - /// <param name="configName">The name of the configuration.</param>
|
| - /// <param name="platformName">The name of the platform.</param>
|
| - /// <returns>true if successfull.</returns>
|
| - internal static bool TrySplitConfigurationCanonicalName(string canonicalName, out string configName, out string platformName)
|
| - {
|
| - configName = String.Empty;
|
| - platformName = String.Empty;
|
| -
|
| - if (String.IsNullOrEmpty(canonicalName))
|
| - {
|
| - return false;
|
| - }
|
| -
|
| - string[] splittedCanonicalName = canonicalName.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
| -
|
| - if (splittedCanonicalName == null || (splittedCanonicalName.Length != 1 && splittedCanonicalName.Length != 2))
|
| - {
|
| - return false;
|
| - }
|
| -
|
| - configName = splittedCanonicalName[0];
|
| - if (splittedCanonicalName.Length == 2)
|
| - {
|
| - platformName = splittedCanonicalName[1];
|
| - }
|
| -
|
| - return true;
|
| - }
|
| -
|
| - protected MSBuild.BuildProperty GetMsBuildProperty(string propertyName, bool resetCache)
|
| - {
|
| - if (resetCache || this.currentConfig == null)
|
| - {
|
| - // Get properties for current configuration from project file and cache it
|
| - this.project.SetConfiguration(this.ConfigName);
|
| - this.currentConfig = this.project.BuildProject.EvaluatedProperties;
|
| -
|
| - project.SetCurrentConfiguration();
|
| - }
|
| -
|
| - if (this.currentConfig == null)
|
| - throw new Exception("Failed to retrieve properties");
|
| -
|
| - // return property asked for
|
| - return this.currentConfig[propertyName];
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Retrieves the configuration dependent property pages.
|
| - /// </summary>
|
| - /// <param name="pages">The pages to return.</param>
|
| - private void GetCfgPropertyPages(CAUUID[] pages)
|
| - {
|
| - // We do not check whether the supportsProjectDesigner is set to true on the ProjectNode.
|
| - // We rely that the caller knows what to call on us.
|
| - if (pages == null)
|
| - {
|
| - throw new ArgumentNullException("pages");
|
| - }
|
| -
|
| - if (pages.Length == 0)
|
| - {
|
| - throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "pages");
|
| - }
|
| -
|
| - // Retrive the list of guids from hierarchy properties.
|
| - // Because a flavor could modify that list we must make sure we are calling the outer most implementation of IVsHierarchy
|
| - string guidsList = String.Empty;
|
| - IVsHierarchy hierarchy = HierarchyNode.GetOuterHierarchy(this.project);
|
| - object variant = null;
|
| - ErrorHandler.ThrowOnFailure(hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList, out variant), new int[] { VSConstants.DISP_E_MEMBERNOTFOUND, VSConstants.E_NOTIMPL });
|
| - guidsList = (string)variant;
|
| -
|
| - Guid[] guids = Utilities.GuidsArrayFromSemicolonDelimitedStringOfGuids(guidsList);
|
| - if (guids == null || guids.Length == 0)
|
| - {
|
| - pages[0] = new CAUUID();
|
| - pages[0].cElems = 0;
|
| - }
|
| - else
|
| - {
|
| - pages[0] = PackageUtilities.CreateCAUUIDFromGuidArray(guids);
|
| - }
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsProjectFlavorCfg Members
|
| - /// <summary>
|
| - /// This is called to let the flavored config let go
|
| - /// of any reference it may still be holding to the base config
|
| - /// </summary>
|
| - /// <returns></returns>
|
| - int IVsProjectFlavorCfg.Close()
|
| - {
|
| - // This is used to release the reference the flavored config is holding
|
| - // on the base config, but in our scenario these 2 are the same object
|
| - // so we have nothing to do here.
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Actual implementation of get_CfgType.
|
| - /// When not flavored or when the flavor delegate to use
|
| - /// we end up creating the requested config if we support it.
|
| - /// </summary>
|
| - /// <param name="iidCfg">IID representing the type of config object we should create</param>
|
| - /// <param name="ppCfg">Config object that the method created</param>
|
| - /// <returns>HRESULT</returns>
|
| - int IVsProjectFlavorCfg.get_CfgType(ref Guid iidCfg, out IntPtr ppCfg)
|
| - {
|
| - ppCfg = IntPtr.Zero;
|
| -
|
| - // See if this is an interface we support
|
| - if (iidCfg == typeof(IVsDebuggableProjectCfg).GUID)
|
| - ppCfg = Marshal.GetComInterfaceForObject(this, typeof(IVsDebuggableProjectCfg));
|
| - else if (iidCfg == typeof(IVsBuildableProjectCfg).GUID)
|
| - {
|
| - IVsBuildableProjectCfg buildableConfig;
|
| - this.get_BuildableProjectCfg(out buildableConfig);
|
| - ppCfg = Marshal.GetComInterfaceForObject(buildableConfig, typeof(IVsBuildableProjectCfg));
|
| - }
|
| -
|
| - // If not supported
|
| - if (ppCfg == IntPtr.Zero)
|
| - return VSConstants.E_NOINTERFACE;
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - #endregion
|
| - }
|
| -
|
| - //=============================================================================
|
| - // NOTE: advises on out of proc build execution to maximize
|
| - // future cross-platform targeting capabilities of the VS tools.
|
| -
|
| - [CLSCompliant(false)]
|
| - [ComVisible(true)]
|
| - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Buildable")]
|
| - public class BuildableProjectConfig : IVsBuildableProjectCfg
|
| - {
|
| - #region fields
|
| - ProjectConfig config = null;
|
| - EventSinkCollection callbacks = new EventSinkCollection();
|
| - #endregion
|
| -
|
| - #region ctors
|
| - public BuildableProjectConfig(ProjectConfig config)
|
| - {
|
| - this.config = config;
|
| - }
|
| - #endregion
|
| -
|
| - #region IVsBuildableProjectCfg methods
|
| -
|
| - public virtual int AdviseBuildStatusCallback(IVsBuildStatusCallback callback, out uint cookie)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - cookie = callbacks.Add(callback);
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int get_ProjectCfg(out IVsProjectCfg p)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - p = config;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int QueryStartBuild(uint options, int[] supported, int[] ready)
|
| - {
|
| - CCITracing.TraceCall();
|
| - if (supported != null && supported.Length > 0)
|
| - supported[0] = 1;
|
| - if (ready != null && ready.Length > 0)
|
| - ready[0] = (this.config.ProjectMgr.BuildInProgress) ? 0 : 1;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int QueryStartClean(uint options, int[] supported, int[] ready)
|
| - {
|
| - CCITracing.TraceCall();
|
| - config.PrepareBuild(false);
|
| - if (supported != null && supported.Length > 0)
|
| - supported[0] = 1;
|
| - if (ready != null && ready.Length > 0)
|
| - ready[0] = (this.config.ProjectMgr.BuildInProgress) ? 0 : 1;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int QueryStartUpToDateCheck(uint options, int[] supported, int[] ready)
|
| - {
|
| - CCITracing.TraceCall();
|
| - config.PrepareBuild(false);
|
| - if (supported != null && supported.Length > 0)
|
| - supported[0] = 0; // TODO:
|
| - if (ready != null && ready.Length > 0)
|
| - ready[0] = (this.config.ProjectMgr.BuildInProgress) ? 0 : 1;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int QueryStatus(out int done)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - done = (this.config.ProjectMgr.BuildInProgress) ? 0 : 1;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int StartBuild(IVsOutputWindowPane pane, uint options)
|
| - {
|
| - CCITracing.TraceCall();
|
| - config.PrepareBuild(false);
|
| -
|
| - // Current version of MSBuild wish to be called in an STA
|
| - uint flags = VSConstants.VS_BUILDABLEPROJECTCFGOPTS_REBUILD;
|
| -
|
| - // If we are not asked for a rebuild, then we build the default target (by passing null)
|
| - this.Build(options, pane, ((options & flags) != 0) ? MsBuildTarget.Rebuild : null);
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int StartClean(IVsOutputWindowPane pane, uint options)
|
| - {
|
| - CCITracing.TraceCall();
|
| - config.PrepareBuild(true);
|
| - // Current version of MSBuild wish to be called in an STA
|
| - this.Build(options, pane, MsBuildTarget.Clean);
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int StartUpToDateCheck(IVsOutputWindowPane pane, uint options)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - public virtual int Stop(int fsync)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int UnadviseBuildStatusCallback(uint cookie)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| -
|
| - callbacks.RemoveAt(cookie);
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - public virtual int Wait(uint ms, int fTickWhenMessageQNotEmpty)
|
| - {
|
| - CCITracing.TraceCall();
|
| -
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| - #endregion
|
| -
|
| - #region helpers
|
| - private void Build(uint options, IVsOutputWindowPane output, string target)
|
| - {
|
| - if (!this.config.ProjectMgr.HasPassedSecurityChecks)
|
| - {
|
| - // From a security perspective, if there was something truly malicious about the project,
|
| - // the user is about to toast himself by requesting a build. Any further attempts at
|
| - // preventing damage by avoiding MSBuild targets/tasks are futile. So, from this point
|
| - // forward, we might as well pretend that this project has passed all security checks,
|
| - // and we're free to run any targets we like.
|
| - this.config.ProjectMgr.HasPassedSecurityChecks = true;
|
| - }
|
| -
|
| - // We want to refresh the references if we are building with the Build or Rebuild target or if the project was opened for browsing only.
|
| - bool shouldRepaintReferences = (target == null || target == MsBuildTarget.Build || target == MsBuildTarget.Rebuild
|
| - || !this.config.ProjectMgr.HasPassedSecurityChecks);
|
| -
|
| - int shouldContinue = 1;
|
| - foreach (IVsBuildStatusCallback cb in callbacks)
|
| - {
|
| - try
|
| - {
|
| - ErrorHandler.ThrowOnFailure(cb.BuildBegin(ref shouldContinue));
|
| - if (shouldContinue == 0)
|
| - return;
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - // If those who ask for status have bugs in their code it should not prevent the build/notification from happening
|
| - Debug.Fail(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.BuildEventError, CultureInfo.CurrentUICulture), e.Message));
|
| - }
|
| - }
|
| -
|
| - MSBuildResult result = MSBuildResult.Failed;
|
| - try
|
| - {
|
| - result = config.ProjectMgr.Build(options, this.config.ConfigName, output, target);
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| - ErrorHandler.ThrowOnFailure(output.OutputStringThreadSafe("Unhandled Exception:" + e.Message + "\n"));
|
| - throw;
|
| - }
|
| - finally
|
| - {
|
| -
|
| - int success = ((result == MSBuildResult.Successful) ? 1 : 0);
|
| -
|
| - foreach (IVsBuildStatusCallback cb in callbacks)
|
| - {
|
| - try
|
| - {
|
| - ErrorHandler.ThrowOnFailure(cb.BuildEnd(success));
|
| - }
|
| - catch (Exception e)
|
| - {
|
| - // If those who ask for status have bugs in their code it should not prevent the build/notification from happening
|
| - Debug.Fail(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.BuildEventError, CultureInfo.CurrentUICulture), e.Message));
|
| - }
|
| - }
|
| -
|
| - ErrorHandler.ThrowOnFailure(output.FlushToTaskList());
|
| -
|
| - // Now repaint references if that is needed.
|
| - // We hardly rely here on the fact the ResolveAssemblyReferences target has been run as part of the build.
|
| - // One scenario to think at is when an assembly reference is renamed on disk thus becomming unresolvable,
|
| - // but msbuild can actually resolve it.
|
| - // Another one if the project was opened only for browsing and now the user chooses to build or rebuild.
|
| - if (shouldRepaintReferences && (result == MSBuildResult.Successful))
|
| - {
|
| - this.RefreshReferences();
|
| - }
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Refreshes references and redraws them correctly.
|
| - /// </summary>
|
| - private void RefreshReferences()
|
| - {
|
| - // Refresh the reference container node for assemblies that could be resolved.
|
| - IReferenceContainer referenceContainer = this.config.ProjectMgr.GetReferenceContainer();
|
| - if (referenceContainer != null)
|
| - {
|
| - foreach (ReferenceNode referenceNode in referenceContainer.EnumReferences())
|
| - {
|
| - referenceNode.RefreshReference();
|
| - }
|
| - }
|
| - }
|
| - #endregion
|
| - }
|
| -}
|
|
|