projectproperty.cs :  » Installers-Generators » WiX » Microsoft » Tools » WindowsInstallerXml » VisualStudio » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Installers Generators » WiX 
WiX » Microsoft » Tools » WindowsInstallerXml » VisualStudio » projectproperty.cs
//-------------------------------------------------------------------------------------------------
// <copyright file="ProjectProperty.cs" company="Microsoft">
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//    
//    The use and distribution terms for this software are covered by the
//    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
//    which can be found in the file CPL.TXT at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//    
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
// Contains the ProjectProperty class.
// </summary>
//-------------------------------------------------------------------------------------------------

namespace Microsoft.Tools.WindowsInstallerXml.VisualStudio{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using Microsoft.Build.BuildEngine;
    using Microsoft.VisualStudio.Package;
    
    /// <summary>
    /// Describes attributes of WiX project properties and allows getting/setting in context of those attributes.
    /// </summary>
    internal class ProjectProperty
    {
        // =========================================================================================
        // Constants
        // =========================================================================================

        private static readonly ICollection<char> MSBuildReservedChars = new char[]
        {
            '%', '$', '@', '(', ')', '\'', ';', '?', '*',
        };

        private static readonly ICollection<string> PerUserProperties = new string[]
        {
            WixProjectFileConstants.ReferencePaths,
        };

        private static readonly ICollection<string> NonPerConfigProperties = new string[]
        {
            WixProjectFileConstants.IncludeSearchPaths,
            WixProjectFileConstants.OutputName,
            WixProjectFileConstants.OutputType,
            WixProjectFileConstants.PreBuildEvent,
            WixProjectFileConstants.PostBuildEvent,
            WixProjectFileConstants.ReferencePaths,
            WixProjectFileConstants.RunPostBuildEvent,
        };

        private static readonly ICollection<string> AllowVariablesProperties = new string[]
        {
            WixProjectFileConstants.CompilerAdditionalOptions,
            WixProjectFileConstants.DefineConstants,
            WixProjectFileConstants.IntermediateOutputPath,
            WixProjectFileConstants.LibAdditionalOptions,
            WixProjectFileConstants.LinkerAdditionalOptions,
            WixProjectFileConstants.OutputName,
            WixProjectFileConstants.OutputPath,
            WixProjectFileConstants.PostBuildEvent,
            WixProjectFileConstants.PreBuildEvent,
            WixProjectFileConstants.WixVariables,
        };

        private static readonly ICollection<string> ListProperties = new string[]
        {
            WixProjectFileConstants.Cultures,
            WixProjectFileConstants.DefineConstants,
            WixProjectFileConstants.IncludeSearchPaths,
            WixProjectFileConstants.ReferencePaths,
            WixProjectFileConstants.SuppressIces,
            WixProjectFileConstants.SuppressSpecificWarnings,
            WixProjectFileConstants.WixVariables,
        };

        private static readonly ICollection<string> EndOfProjectFileProperties = new string[]
        {
            WixProjectFileConstants.PreBuildEvent,
            WixProjectFileConstants.PostBuildEvent,
        };

        // =========================================================================================
        // Member Variables
        // =========================================================================================

        private WixProjectNode project;
        private string propertyName;
        private bool perUser;
        private bool perConfig;
        private bool allowVariables;
        private bool list;
        private bool endOfProjectFile;

        // =========================================================================================
        // Constructors
        // =========================================================================================

        /// <summary>
        /// Creates a new project property object.
        /// </summary>
        /// <param name="project">Project that owns the property.</param>
        /// <param name="propertyName">Name of the property.</param>
        public ProjectProperty(WixProjectNode project, string propertyName)
        {
            WixHelperMethods.VerifyNonNullArgument(project, "project");
            WixHelperMethods.VerifyNonNullArgument(propertyName, "propertyName");

            this.project = project;
            this.propertyName = propertyName;

            this.perUser = ProjectProperty.PerUserProperties.Contains(propertyName);
            this.perConfig = !ProjectProperty.NonPerConfigProperties.Contains(propertyName);
            this.allowVariables = ProjectProperty.AllowVariablesProperties.Contains(propertyName);
            this.list = ProjectProperty.ListProperties.Contains(propertyName);
            this.endOfProjectFile = ProjectProperty.EndOfProjectFileProperties.Contains(propertyName);
        }

        // =========================================================================================
        // Properties
        // =========================================================================================

        /// <summary>
        /// Gets the name of the property.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        public string Name
        {
            get { return this.propertyName; }
        }

        /// <summary>
        /// Gets a flag indicating whether the property is stored in the user project file.
        /// </summary>
        public bool PerUser
        {
            get { return this.perUser; }
        }

        /// <summary>
        /// Gets a flag indicating whether the property is stored in a property group conditioned on the configuration.
        /// </summary>
        public bool PerConfig
        {
            get { return this.perConfig; }
        }

        /// <summary>
        /// Gets a flag indicating wether the property allows variables in the value (affects escaping behavior).
        /// </summary>
        public bool AllowVariables
        {
            get { return this.allowVariables; }
        }

        /// <summary>
        /// Gets a flag indicating wether the property value is a list of items (affects escaping behavior).
        /// </summary>
        public bool List
        {
            get { return this.list; }
        }

        /// <summary>
        /// Gets a flag indicating wether the property is stored at the end of the project file.
        /// </summary>
        public bool EndOfProjectFile
        {
            get { return this.endOfProjectFile; }
        }

        // =========================================================================================
        // Methods
        // =========================================================================================

        /// <summary>
        /// Gets the value of the property for the current project configuration.
        /// </summary>
        /// <param name="finalValue">Whether to evaluate variables in the value.</param>
        /// <returns>Value of the property, or null if the property is unset.</returns>
        public string GetValue(bool finalValue)
        {
            return this.GetValue(finalValue, null);
        }

        /// <summary>
        /// Gets the value of the property.
        /// </summary>
        /// <param name="finalValue">Whether to evaluate variables in the value.</param>
        /// <param name="configs">Optional list of configurations to retrieve the property from;
        /// defaults to the project current configuration</param>
        /// <returns>Value (unified across configs) of the property, or null if the property is unset or
        /// inconsistent across configurations.</returns>
        public string GetValue(bool finalValue, IList<ProjectConfig> configs)
        {
            Project buildProject = this.PerUser ? this.project.UserBuildProject : this.project.BuildProject;
            if (buildProject == null)
            {
                return null;
            }

            return this.GetValue(finalValue, configs, false);
        }

        /// <summary>
        /// Gets the value of a boolean property.
        /// </summary>
        /// <param name="configs">Optional list of configurations to retrieve the property from;
        /// defaults to the project current configuration</param>
        /// <returns>Value (unified across configs) of the property, null if the property is
        /// inconsistent across configurations, or false if the property is unset.</returns>
        public bool? GetBooleanValue(IList<ProjectConfig> configs)
        {
            Project buildProject = this.PerUser ? this.project.UserBuildProject : this.project.BuildProject;
            if (buildProject == null)
            {
                return null;
            }

            string value = this.GetValue(false, configs, true);

            if (String.Equals(value, Boolean.TrueString, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
            else if (String.Equals(value, Boolean.FalseString, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Sets the value of the property for the current project configuration.
        /// </summary>
        /// <param name="value">Property value to set.</param>
        /// <remarks>
        /// Before calling this method, the caller must ensure that the value is valid according to
        /// the <see cref="PropertyValidator"/> class, and that the project file is writable.
        /// In most cases the caller should also ensure that the new value is different from the
        /// existing value, to avoid dirtying the project file unnecessarily.
        /// </remarks>
        public void SetValue(string value)
        {
            this.SetValue(value, null);
        }

        /// <summary>
        /// Sets the value of the property.
        /// </summary>
        /// <param name="value">Property value to set.</param>
        /// <param name="configs">Optional list of configurations to set the property in;
        /// defaults to the project current configuration</param>
        /// <remarks>
        /// Before calling this method, the caller must ensure that the value is valid according to
        /// the <see cref="PropertyValidator"/> class, and that the project file is writable.
        /// In most cases the caller should also ensure that the new value is different from the
        /// existing value, to avoid dirtying the project file unnecessarily.
        /// </remarks>
        public void SetValue(string value, IList<ProjectConfig> configs)
        {
            WixHelperMethods.VerifyNonNullArgument(value, "value");

            value = value.Trim();

            PropertyPosition position = this.EndOfProjectFile ?
                PropertyPosition.UseExistingOrCreateAfterLastImport : PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup;

            Project buildProject = this.project.BuildProject;
            if (this.PerUser)
            {
                if (this.project.UserBuildProject == null)
                {
                    this.project.CreateUserBuildProject();
                }

                buildProject = this.project.UserBuildProject;
            }

            value = this.Escape(value);

            if (this.PerConfig)
            {
                if (configs == null || configs.Count == 0)
                {
                    configs = new ProjectConfig[] { this.project.CurrentConfig };
                }

                foreach (ProjectConfig config in configs)
                {
                    buildProject.SetProperty(this.propertyName, value, config.Condition, position);
                }
            }
            else
            {
                buildProject.SetProperty(this.propertyName, value, null, position);
            }

            this.project.InvalidatePropertyCache();
            this.project.SetProjectFileDirty(true);
        }

        private string GetValue(bool finalValue, IList<ProjectConfig> configs, bool booleanValue)
        {
            Project buildProject = this.PerUser ? this.project.UserBuildProject : this.project.BuildProject;
            if (buildProject == null)
            {
                return null;
            }

            string value;
            if (this.PerConfig)
            {
                if (configs == null || configs.Count == 0)
                {
                    configs = new ProjectConfig[] { this.project.CurrentConfig };
                }

                value = this.GetPerConfigValue(buildProject, finalValue, configs, booleanValue);
            }
            else
            {
                BuildProperty buildProperty = buildProject.EvaluatedProperties[this.propertyName];
                value = this.GetBuildPropertyValue(buildProperty, finalValue);
                if (booleanValue && String.IsNullOrEmpty(value))
                {
                    value = Boolean.FalseString;
                }
            }

            return value;
        }

        private string GetPerConfigValue(Project buildProject, bool finalValue, IList<ProjectConfig> configs, bool nullIsFalse)
        {
            string unifiedValue = null;

            for (int i = 0; i < configs.Count; i++)
            {
                ProjectConfig config = configs[i];
                bool resetCache = (i == 0);

                BuildProperty buildProperty = config.GetMsBuildProperty(this.propertyName, resetCache, buildProject);
                string value = this.GetBuildPropertyValue(buildProperty, finalValue);

                if (value != null)
                {
                    value = value.Trim();
                }

                if (nullIsFalse && String.IsNullOrEmpty(value))
                {
                    value = Boolean.FalseString;
                }

                if (i == 0)
                {
                    unifiedValue = value;
                }
                else if (unifiedValue != value)
                {
                    unifiedValue = null; // indicates indeterminate value
                    break;
                }
            }

            return unifiedValue;
        }

        private string GetBuildPropertyValue(BuildProperty buildProperty, bool finalValue)
        {
            if (buildProperty == null)
            {
                return null;
            }
            else if (finalValue)
            {
                return buildProperty.FinalValue;
            }
            else
            {
                // If the property definition contains the property itself, we want to return the final result
                // Ideally, we would like to expand only the value for the property but MSBuild does not allow that
                // That solves the case where OutputPath is define as $(OutputPath)\ if it's not ending with a backslash
                string propertyNameEscaped = "$(" + this.propertyName + ")";
                if (buildProperty.Value.Contains(propertyNameEscaped))
                {
                    return buildProperty.FinalValue;
                }
                else
                {
                    return this.Unescape(buildProperty.Value);
                }
            }
        }

        private string Escape(string value)
        {
            IList<char> charsToEscape = this.GetCharsToEscape();

            foreach (char c in charsToEscape)
            {
                if (value.IndexOf(Convert.ToString(c, CultureInfo.InvariantCulture), StringComparison.Ordinal) >= 0)
                {
                    string escapeCode = String.Format(CultureInfo.InvariantCulture, "%{0:x2}", (int) c);
                    value = value.Replace(c.ToString(), escapeCode);
                }
            }

            return value;
        }

        private string Unescape(string value)
        {
            IList<char> charsToEscape = this.GetCharsToEscape();

            foreach (char c in charsToEscape)
            {
                string escapeCode = String.Format(CultureInfo.InvariantCulture, "%{0:x2}", (int)c);
                if (value.IndexOf(escapeCode, StringComparison.Ordinal) >= 0)
                {
                    value = value.Replace(escapeCode, c.ToString());
                }
            }

            return value;
        }

        private IList<char> GetCharsToEscape()
        {
            IList<char> charsToEscape = new List<char>(ProjectProperty.MSBuildReservedChars);

            if (this.AllowVariables)
            {
                charsToEscape.Remove('$');
                charsToEscape.Remove('(');
                charsToEscape.Remove(')');
            }

            if (this.List)
            {
                charsToEscape.Remove(';');
            }

            // Never auto-escape the % sign because it just causes much confusion.
            charsToEscape.Remove('%');

            return charsToEscape;
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.