public static string GetValueForProperty(DataProperty property)
        {
            var propertylist = new Collection<DataProperty> { property };
            CacheProperties(propertylist);
            var dataProperty = PropertiesCache.FirstOrDefault(x => x.Id == property.Id);
            if (dataProperty != null)
            {
                return dataProperty.Value;
            }

            throw new InstallerVerificationLibraryException("Could not find property : " + property.Id);
        }
        public static int Compare(DataProperty left, DataProperty right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }

            if (left.Equals(right))
            {
                return 0;
            }

            if (ReferenceEquals(left, null))
            {
                return -1;
            }

            return left.CompareTo(right);
        }
        private static Collection<DataProperty> ReadEnvironmentVariable(ICollection<XElement> properties)
        {
            var proplist = new Collection<DataProperty>();
            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.EnvironmentVariable))
            {
                var prop = new DataProperty
                               {
                                   Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                   PropertyType = DataPropertyType.EnvironmentVariable,
                                   Value = XmlTools.GetNamedAttributeValue(property, "value", null)
                               };

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                if (prop.Value != null)
                {
                    prop.Value = Environment.GetEnvironmentVariable(prop.Value);
                    proplist.Add(prop);
                }
                else
                {
                    var msg = "Missing 'value' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }
            }

            return proplist;
        }
        private static Collection<DataProperty> ReadWindowsInstallerValue(ICollection<XElement> properties)
        {
            var proplist = new Collection<DataProperty>();
            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.WindowsInstaller))
            {
                var prop = new DataProperty
                            {
                                Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                PropertyType = DataPropertyType.WindowsInstaller,
                                Value = XmlTools.GetNamedAttributeValue(property, "valueIfNotFound", null),
                            };

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                proplist.Add(prop);
            }

            WindowsInstallerPropertyExtractor.CacheProperties(proplist);

            foreach (var prop in proplist)
            {
                var value = WindowsInstallerPropertyExtractor.GetValueForProperty(prop);
                if (!string.IsNullOrEmpty(value))
                {
                    prop.Value = value;
                }
                else if (prop.Value == null)
                {
                    var msg = "Missing 'valueIfNotFound' attribute for property '" + prop.Id + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }
            }

            return proplist;
        }
        private static Collection<DataProperty> ReadSpecialFolderPath(ICollection<XElement> properties)
        {
            var proplist = new Collection<DataProperty>();
            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.SpecialFolderPath))
            {
                var prop = new DataProperty
                               {
                                   Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                   PropertyType = DataPropertyType.SpecialFolderPath,
                                   Value = null
                               };

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                var value = XmlTools.GetNamedAttributeValue(property, "value", null);
                if (value != null)
                {
                    foreach (int specialFolderIndex in Enum.GetValues(typeof(Environment.SpecialFolder)))
                    {
                        if (((Environment.SpecialFolder)specialFolderIndex).ToString() == value)
                        {
                            prop.Value = Environment.GetFolderPath((Environment.SpecialFolder) specialFolderIndex);
                            break;
                        }
                    }

                    if (prop.Value != null)
                    {
                        proplist.Add(prop);
                    }
                    else
                    {
                        var msg = "Could not find folder path '" + value + "' in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                        Log.WriteError(msg, "ExtractProperties");
                        throw new InstallerVerificationLibraryException(msg);
                    }
                }
                else
                {
                    var msg = "Missing 'value' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }
            }

            return proplist;
        }
        private static Collection<DataProperty> ReadRegistryValue(ICollection<XElement> properties)
        {
            var proplist = new Collection<DataProperty>();
            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.RegistryValue))
            {
                var prop = new DataProperty
                               {
                                   Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                   PropertyType = DataPropertyType.RegistryValue
                               };

                var keyName = XmlTools.GetNamedAttributeValue(property, "key", null);
                var valueName = XmlTools.GetNamedAttributeValue(property, "valueName", null);
                var valueIfNotFound = XmlTools.GetNamedAttributeValue(property, "valueIfNotFound", null);

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                if (string.IsNullOrEmpty(keyName))
                {
                    var msg = "Missing 'key' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                if (string.IsNullOrEmpty(valueName))
                {
                    var msg = "Missing 'valueName' attribute in Property Node: '" + XmlTools.GetOuterXml(property) +
                              "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                var value = (string) RegistryTool.RegistryValue(keyName, valueName, null);

                if (value == null)
                {
                    if (valueIfNotFound == null)
                    {
                        var msg = "Missing 'valueIfNotFound' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                        Log.WriteError(msg, "ExtractProperties");
                        throw new InstallerVerificationLibraryException(msg);
                    }

                    prop.Value = valueIfNotFound;
                }
                else
                {
                    prop.Value = value;
                }

                proplist.Add(prop);
            }

            return proplist;
        }
        private static Collection<DataProperty> ReadRegistryPathExistValue(ICollection<XElement> properties)
        {
            var proplist = new Collection<DataProperty>();
            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.RegistryPathExist))
            {
                var prop = new DataProperty
                               {
                                   Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                   PropertyType = DataPropertyType.RegistryPathExist
                               };
                var keyName = XmlTools.GetNamedAttributeValue(property, "key", null);

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                if (keyName == null)
                {
                    var msg = "Missing 'value' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                prop.Value = RegistryTool.RegistryKeyExist(keyName).ToString();
                proplist.Add(prop);
            }

            return proplist;
        }
        private static ICollection<DataProperty> ReadParameter(ICollection<XElement> properties,
            ICollection<Parameter> parameters)
        {
            var proplist = new Collection<DataProperty>();
            var proplistError = new Collection<DataProperty>();

            foreach (var property in GetPropertyNodesWithSpecificType(properties, DataPropertyType.Parameter))
            {
                var prop = new DataProperty
                               {
                                   Id = XmlTools.GetNamedAttributeValue(property, "id", null),
                                   PropertyType = DataPropertyType.Parameter
                               };

                if (prop.Id == null)
                {
                    var msg = "Missing 'id' attribute in Property Node: '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }

                var parameterId = XmlTools.GetNamedAttributeValue(property, "parameterID", null);
                if (!string.IsNullOrEmpty(parameterId))
                {
                    var found = false;
                    foreach (var parm in parameters.Where(parm => parm.Id == parameterId))
                    {
                        prop.Value = parm.Value;
                        proplist.Add(prop);
                        found = true;
                        break;
                    }

                    if (found)
                    {
                        //// If found delete if property exist in error list
                        if (proplistError.Contains(prop))
                        {
                            proplistError.Remove(prop);
                        }
                    }
                    else
                    {
                        //// If not found and it doesn't allready exist add property to error list
                        if (!proplist.Contains(prop))
                        {
                            prop.Value = XmlTools.GetOuterXml(property);
                            proplistError.Add(prop);
                        }
                    }
                }
                else
                {
                    var msg = "parameterID attribute is missing for property '" + XmlTools.GetOuterXml(property) + "'";
                    Log.WriteError(msg, "ExtractProperties");
                    throw new InstallerVerificationLibraryException(msg);
                }
            }

            //// Check if any error exist
            if (proplistError.Count > 0)
            {
                var msg = proplistError.Aggregate(string.Empty, (current, prop) => current + ("Property Node: '" + prop.Value + "' doesn't contain a valid parameterId"));

                Log.WriteError(msg, "ExtractProperties");
                throw new InstallerVerificationLibraryException(msg);
            }

            return proplist;
        }
 public DataProperty Clone()
 {
     var dat = new DataProperty(Id, Value, PropertyType);
     return dat;
 }