void ISetAttributes.SetAttribute(string name, string value) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (("Id" == name)) { this.idField = value; this.idFieldSet = true; } if (("FilterDefinition" == name)) { this.filterDefinitionField = value; this.filterDefinitionFieldSet = true; } if (("Name" == name)) { this.nameField = value; this.nameFieldSet = true; } if (("SuppressCustomActions" == name)) { this.suppressCustomActionsField = Enums.ParseYesNoType(value); this.suppressCustomActionsFieldSet = true; } }
/// <summary> /// Tries to parse a YesNoType from a string. /// </summary> public static bool TryParseYesNoType(string value, out YesNoType parsedValue) { parsedValue = YesNoType.NotSet; if (string.IsNullOrEmpty(value)) { return(false); } if (("no" == value)) { parsedValue = YesNoType.no; } else { if (("yes" == value)) { parsedValue = YesNoType.yes; } else { parsedValue = YesNoType.IllegalValue; return(false); } } return(true); }
void ISetAttributes.SetAttribute(string name, string value) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (("Id" == name)) { this.idField = value; this.idFieldSet = true; } if (("AttributeIndex" == name)) { this.attributeIndexField = value; this.attributeIndexFieldSet = true; } if (("Index" == name)) { this.indexField = value; this.indexFieldSet = true; } if (("Language" == name)) { this.languageField = Convert.ToInt32(value, CultureInfo.InvariantCulture); this.languageFieldSet = true; } if (("Name" == name)) { this.nameField = value; this.nameFieldSet = true; } if (("SampleLocation" == name)) { this.sampleLocationField = value; this.sampleLocationFieldSet = true; } if (("Search" == name)) { this.searchField = value; this.searchFieldSet = true; } if (("SuppressCustomActions" == name)) { this.suppressCustomActionsField = Enums.ParseYesNoType(value); this.suppressCustomActionsFieldSet = true; } }
void ISetAttributes.SetAttribute(string name, string value) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (("File" == name)) { this.fileField = value; this.fileFieldSet = true; } if (("PackageId" == name)) { this.packageIdField = value; this.packageIdFieldSet = true; } if (("Permanent" == name)) { this.permanentField = Enums.ParseYesNoType(value); this.permanentFieldSet = true; } if (("Target" == name)) { this.targetField = value; this.targetFieldSet = true; } if (("TargetVersion" == name)) { this.targetVersionField = value; this.targetVersionFieldSet = true; } if (("Vital" == name)) { this.vitalField = Enums.ParseYesNoType(value); this.vitalFieldSet = true; } if (("VsixInstallerPathProperty" == name)) { this.vsixInstallerPathPropertyField = value; this.vsixInstallerPathPropertyFieldSet = true; } }
/// <summary> /// Gets a yes/no value and displays an error for an illegal yes/no value. /// </summary> /// <param name="sourceLineNumbers">Source line information about the owner element.</param> /// <param name="attribute">The attribute containing the value to get.</param> /// <param name="messageHandler">A delegate that receives error messages.</param> /// <returns>The attribute's YesNoType value.</returns> internal static YesNoType GetAttributeYesNoValue(IMessaging messaging, SourceLineNumber sourceLineNumbers, XAttribute attribute) { string value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly); YesNoType yesNo = YesNoType.IllegalValue; if ("yes".Equals(value) || "true".Equals(value)) { yesNo = YesNoType.Yes; } else if ("no".Equals(value) || "false".Equals(value)) { yesNo = YesNoType.No; } else { messaging.Write(ErrorMessages.IllegalYesNoValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); } return(yesNo); }
internal static YesNoType GetAttributeYesNoValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, Action <MessageEventArgs> messageHandler) { string value = Common.GetAttributeValue(sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly, messageHandler); YesNoType yesNo = YesNoType.IllegalValue; if ("yes".Equals(value, StringComparison.Ordinal) || "true".Equals(value, StringComparison.Ordinal)) { yesNo = YesNoType.Yes; } else if ("no".Equals(value, StringComparison.Ordinal) || "false".Equals(value, StringComparison.Ordinal)) { yesNo = YesNoType.No; } else { if (null != messageHandler) { messageHandler(WixErrors.IllegalYesNoValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); } } return(yesNo); }
void ISetAttributes.SetAttribute(string name, string value) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (("Attributes" == name)) { this.attributesField = value; this.attributesFieldSet = true; } if (("TableOfContents" == name)) { this.tableOfContentsField = value; this.tableOfContentsFieldSet = true; } if (("TargetCollection" == name)) { this.targetCollectionField = value; this.targetCollectionFieldSet = true; } if (("TargetTableOfContents" == name)) { this.targetTableOfContentsField = value; this.targetTableOfContentsFieldSet = true; } if (("TargetFeature" == name)) { this.targetFeatureField = value; this.targetFeatureFieldSet = true; } if (("SuppressExternalNamespaces" == name)) { this.suppressExternalNamespacesField = Enums.ParseYesNoType(value); this.suppressExternalNamespacesFieldSet = true; } }
/// <summary> /// Parses a HelpFilter element. /// </summary> /// <param name="node">Element to process.</param> private void ParseHelpFilterElement(XmlNode node) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; string filterDefinition = null; string name = null; YesNoType suppressCAs = YesNoType.No; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "FilterDefinition": filterDefinition = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Name": name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "SuppressCustomActions": suppressCAs = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (null == id) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } if (null == name) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name")); } // find unexpected child elements foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (!this.Core.EncounteredError) { Row row = this.Core.CreateRow(sourceLineNumbers, "HelpFilter"); row[0] = id; row[1] = name; row[2] = filterDefinition; if (YesNoType.No == suppressCAs) { this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "CA_RegisterMicrosoftHelp.3643236F_FC70_11D3_A536_0090278A1BB8"); } } }
private void ParseHelpFilterElement(Intermediate intermediate, IntermediateSection section, XElement element) { SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); Identifier id = null; string filterDefinition = null; string name = null; YesNoType suppressCAs = YesNoType.No; foreach (XAttribute attrib in element.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "Id": id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); break; case "FilterDefinition": filterDefinition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "Name": name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "SuppressCustomActions": suppressCAs = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.ParseHelper.UnexpectedAttribute(element, attrib); break; } } else { this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); } } if (null == id) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); } if (null == name) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); } this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); if (!this.Messaging.EncounteredError) { var row = this.ParseHelper.CreateRow(section, sourceLineNumbers, "HelpFilter", id); row.Set(1, name); row.Set(2, filterDefinition); if (YesNoType.No == suppressCAs) { this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "CA_RegisterMicrosoftHelp.3643236F_FC70_11D3_A536_0090278A1BB8"); } } }
/// <summary> /// Parses a HelpFile element. /// </summary> /// <param name="node">Element to process.</param> /// <param name="fileId">Identifier of the parent file element.</param> private void ParseHelpFileElement(XmlNode node, string fileId) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; string name = null; int language = CompilerCore.IntegerNotSet; string hxi = null; string hxq = null; string hxr = null; string samples = null; YesNoType suppressCAs = YesNoType.No; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "AttributeIndex": hxr = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", hxr); break; case "Index": hxi = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", hxi); break; case "Language": language = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); break; case "Name": name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "SampleLocation": samples = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", samples); break; case "Search": hxq = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", hxq); break; case "SuppressCustomActions": suppressCAs = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (null == id) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } if (null == name) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name")); } //uninstall will always fail silently, leaving file registered, if Language is not set if (CompilerCore.IntegerNotSet == language) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Language")); } // find unexpected child elements foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (!this.Core.EncounteredError) { Row row = this.Core.CreateRow(sourceLineNumbers, "HelpFile"); row[0] = id; row[1] = name; row[2] = language; row[3] = fileId; row[4] = hxi; row[5] = hxq; row[6] = hxr; row[7] = samples; if (YesNoType.No == suppressCAs) { this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "CA_RegisterMicrosoftHelp.3643236F_FC70_11D3_A536_0090278A1BB8"); } } }
/// <summary> /// Parses a class element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">Optional Advertise State for the parent AppId element (if any).</param> /// <param name="fileServer">Optional file identifier for CLSID when not advertised.</param> /// <param name="typeLibId">Optional TypeLib GUID for CLSID.</param> /// <param name="typeLibVersion">Optional TypeLib Version for CLSID Interfaces (if any).</param> /// <param name="parentAppId">Optional parent AppId.</param> private void ParseClassElement(XmlNode node, string componentId, YesNoType advertise, string fileServer, string typeLibId, string typeLibVersion, string parentAppId) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string appId = null; string argument = null; bool class16bit = false; bool class32bit = false; string classId = null; StringCollection context = new StringCollection(); string formattedContextString = null; bool control = false; string defaultInprocHandler = null; string defaultProgId = null; string description = null; string fileTypeMask = null; string foreignServer = null; string icon = null; int iconIndex = CompilerCore.IntegerNotSet; string insertable = null; string localFileServer = null; bool programmable = false; YesNoType relativePath = YesNoType.NotSet; bool safeForInit = false; bool safeForScripting = false; bool shortServerPath = false; string threadingModel = null; string version = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": classId = this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; case "Advertise": YesNoType classAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == classAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == classAdvertise)) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, classAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat), advertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = classAdvertise; break; case "AppId": if (null != parentAppId) { this.core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name, attrib.Name, node.ParentNode.Name)); } appId = this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; case "Argument": argument = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Context": string[] value = this.core.GetAttributeValue(sourceLineNumbers, attrib).Split("\r\n\t ".ToCharArray()); for (int i = 0; i < value.Length; ++i) { if (0 == value[i].Length) { continue; } // check for duplicates in the list for (int j = 0; j < context.Count; ++j) { if (context[j] == value[i]) { this.core.OnMessage(WixErrors.DuplicateContextValue(sourceLineNumbers, value[i])); } } // check if this context is 32 bit or not if (value[i].EndsWith("32", StringComparison.Ordinal)) { class32bit = true; } else { class16bit = true; } context.Add(value[i]); } break; case "Control": control = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Description": description = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Handler": defaultInprocHandler = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Icon": icon = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "IconIndex": iconIndex = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, short.MinValue + 1, short.MaxValue); break; case "RelativePath": relativePath = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; // The following attributes result in rows always added to the Registry table rather than the Class table case "Insertable": if (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { insertable = "Insertable"; } else { insertable = "NotInsertable"; } break; case "Programmable": programmable = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SafeForInitializing": safeForInit = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SafeForScripting": safeForScripting = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ForeignServer": foreignServer = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Server": localFileServer = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", localFileServer); break; case "ShortPath": shortServerPath = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ThreadingModel": threadingModel = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Version": version = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } // If the advertise state has not been set, default to non-advertised. if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } if (null == classId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } if (YesNoType.Yes == advertise && 0 == context.Count) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Context", "Advertise", "yes")); } // Local variables used strictly for child node processing. int fileTypeMaskIndex = 0; YesNoType firstProgIdForClass = YesNoType.Yes; foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); switch (child.LocalName) { case "FileTypeMask": if (YesNoType.Yes == advertise) { fileTypeMask = String.Concat(fileTypeMask, null == fileTypeMask ? String.Empty : ";", this.ParseFileTypeMaskElement(child)); } else if (YesNoType.No == advertise) { this.core.CreateRegistryRow(childSourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("FileType\\", classId, "\\", fileTypeMaskIndex.ToString(CultureInfo.InvariantCulture.NumberFormat)), String.Empty, this.ParseFileTypeMaskElement(child), componentId); fileTypeMaskIndex++; } break; case "Interface": this.ParseInterfaceElement(child, componentId, class16bit ? classId : null, class32bit ? classId : null, typeLibId, typeLibVersion); break; case "ProgId": bool foundExtension = false; string progId = this.ParseProgIdElement(child, componentId, advertise, classId, description, null, ref foundExtension, firstProgIdForClass); if (null == defaultProgId) { defaultProgId = progId; } firstProgIdForClass = YesNoType.No; break; default: this.core.UnexpectedElement(node, child); break; } } else { this.core.UnsupportedExtensionElement(node, child); } } } // If this Class is being advertised. if (YesNoType.Yes == advertise) { if (null != fileServer || null != localFileServer) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Server", "Advertise", "yes")); } if (null != foreignServer) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "ForeignServer", "Advertise", "yes")); } if (null == appId && null != parentAppId) { appId = parentAppId; } // add a Class row for each context if (!this.core.EncounteredError) { for (int i = 0; i < context.Count; ++i) { Row row = this.core.CreateRow(sourceLineNumbers, "Class"); row[0] = classId; row[1] = context[i]; row[2] = componentId; row[3] = defaultProgId; row[4] = description; if (null != appId) { row[5] = appId; this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "AppId", appId); } row[6] = fileTypeMask; if (null != icon) { row[7] = icon; this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Icon", icon); } if (CompilerCore.IntegerNotSet != iconIndex) { row[8] = iconIndex; } row[9] = defaultInprocHandler; row[10] = argument; row[11] = Guid.Empty.ToString("B"); if (YesNoType.Yes == relativePath) { row[12] = MsiInterop.MsidbClassAttributesRelativePath; } } } } else if (YesNoType.No == advertise) { if (null == fileServer && null == localFileServer && null == foreignServer) { this.core.OnMessage(WixErrors.ExpectedAttributes(sourceLineNumbers, node.Name, "ForeignServer", "Server")); } if (null != fileServer && null != foreignServer) { this.core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.LocalName, "ForeignServer", "File")); } else if (null != localFileServer && null != foreignServer) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "ForeignServer", "Server")); } else if (null == fileServer) { fileServer = localFileServer; } if (null != appId) // need to use nesting (not a reference) for the unadvertised Class elements { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "AppId", "Advertise", "no")); } // add the core registry keys for each context in the class for (int i = 0; i < context.Count; ++i) { if (context[i].StartsWith("InprocServer", StringComparison.Ordinal)) // dll server { if (null != argument) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Arguments", "Context", context[i])); } if (null != fileServer) { formattedContextString = String.Concat("[", shortServerPath ? "!" : "#", fileServer, "]"); } else if (null != foreignServer) { formattedContextString = foreignServer; } } else if (context[i].StartsWith("LocalServer", StringComparison.Ordinal)) // exe server (quote the long path) { if (null != fileServer) { if (shortServerPath) { formattedContextString = String.Concat("[!", fileServer, "]"); } else { formattedContextString = String.Concat("\"[#", fileServer, "]\""); } } else if (null != foreignServer) { formattedContextString = foreignServer; } if (null != argument) { formattedContextString = String.Concat(formattedContextString, " ", argument); } } else { this.core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "Context", context[i], "InprocServer", "InprocServer32", "LocalServer", "LocalServer32")); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", context[i]), String.Empty, formattedContextString, componentId); // ClassId context if (null != icon) // ClassId default icon { this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", icon); icon = String.Format(CultureInfo.InvariantCulture, "\"[#{0}]\"", icon); if (CompilerCore.IntegerNotSet != iconIndex) { icon = String.Concat(icon, ",", iconIndex); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", context[i], "\\DefaultIcon"), String.Empty, icon, componentId); } } if (null != parentAppId) // ClassId AppId (must be specified via nesting, not with the AppId attribute) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId), "AppID", parentAppId, componentId); } if (null != description) // ClassId description { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId), String.Empty, description, componentId); } if (null != defaultInprocHandler) { switch (defaultInprocHandler) // ClassId Default Inproc Handler { case "1": this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\InprocHandler"), String.Empty, "ole.dll", componentId); break; case "2": this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\InprocHandler32"), String.Empty, "ole32.dll", componentId); break; case "3": this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\InprocHandler"), String.Empty, "ole.dll", componentId); this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\InprocHandler32"), String.Empty, "ole32.dll", componentId); break; default: this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\InprocHandler32"), String.Empty, defaultInprocHandler, componentId); break; } } if (YesNoType.NotSet != relativePath) // ClassId's RelativePath { this.core.OnMessage(WixErrors.RelativePathForRegistryElement(sourceLineNumbers)); } } if (null != threadingModel) { threadingModel = Compiler.UppercaseFirstChar(threadingModel); // add a threading model for each context in the class for (int i = 0; i < context.Count; ++i) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", context[i]), "ThreadingModel", threadingModel, componentId); } } if (null != typeLibId) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\TypeLib"), null, typeLibId, componentId); } if (null != version) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\Version"), null, version, componentId); } if (null != insertable) { // Add "*" for name so that any subkeys (shouldn't be any) are removed on uninstall. this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", insertable), "*", null, componentId); } if (control) { // Add "*" for name so that any subkeys (shouldn't be any) are removed on uninstall. this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\Control"), "*", null, componentId); } if (programmable) { // Add "*" for name so that any subkeys (shouldn't be any) are removed on uninstall. this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\Programmable"), "*", null, componentId); } if (safeForInit) { this.RegisterImplementedCategories(sourceLineNumbers, "{7DD95802-9882-11CF-9FA9-00AA006C42C4}", classId, componentId); } if (safeForScripting) { this.RegisterImplementedCategories(sourceLineNumbers, "{7DD95801-9882-11CF-9FA9-00AA006C42C4}", classId, componentId); } }
/// <summary> /// Parses a shortcut element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifer for parent component.</param> /// <param name="parentElementLocalName">Local name of parent element.</param> /// <param name="defaultTarget">Default identifier of parent (which is usually the target).</param> /// <param name="parentKeyPath">Flag to indicate whether the parent element is the keypath of a component or not (will only be true for file parent elements).</param> private void ParseShortcutElement(XmlNode node, string componentId, string parentElementLocalName, string defaultTarget, YesNoType parentKeyPath) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; bool advertise = false; string arguments = null; string description = null; string descriptionResourceDll = null; int descriptionResourceId = CompilerCore.IntegerNotSet; string directory = null; string displayResourceDll = null; int displayResourceId = CompilerCore.IntegerNotSet; int hotkey = CompilerCore.IntegerNotSet; string icon = null; int iconIndex = CompilerCore.IntegerNotSet; string longName = null; string name = null; string shortName = null; int show = CompilerCore.IntegerNotSet; string target = null; string workingDirectory = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": id = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "Advertise": advertise = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Arguments": arguments = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Description": description = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "DescriptionResourceDll": descriptionResourceDll = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "DescriptionResourceId": descriptionResourceId = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); break; case "Directory": directory = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Directory", directory); break; case "DisplayResourceDll": displayResourceDll = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "DisplayResourceId": displayResourceId = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); break; case "Hotkey": hotkey = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); break; case "Icon": icon = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Icon", icon); break; case "IconIndex": iconIndex = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, short.MinValue + 1, short.MaxValue); break; case "LongName": longName = this.core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); this.core.OnMessage(WixWarnings.DeprecatedLongNameAttribute(sourceLineNumbers, node.Name, attrib.Name, "Name", "ShortName")); break; case "Name": name = this.core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); break; case "ShortName": shortName = this.core.GetAttributeShortFilename(sourceLineNumbers, attrib, false); break; case "Show": string showValue = this.core.GetAttributeValue(sourceLineNumbers, attrib); if (showValue.Length == 0) { show = CompilerCore.IllegalInteger; } else { Wix.Shortcut.ShowType showType = Wix.Shortcut.ParseShowType(showValue); switch (showType) { case Wix.Shortcut.ShowType.normal: show = 1; break; case Wix.Shortcut.ShowType.maximized: show = 3; break; case Wix.Shortcut.ShowType.minimized: show = 7; break; default: this.core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "Show", showValue, "normal", "maximized", "minimized")); show = CompilerCore.IllegalInteger; break; } } break; case "Target": target = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "WorkingDirectory": workingDirectory = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (advertise && null != target) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Target", "Advertise", "yes")); } if (null == directory) { if ("Component" == parentElementLocalName) { directory = defaultTarget; } else { this.core.OnMessage(WixErrors.ExpectedAttributeWhenElementNotUnderElement(sourceLineNumbers, node.Name, "Directory", "Component")); } } if (null != descriptionResourceDll) { if (CompilerCore.IntegerNotSet == descriptionResourceId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "DescriptionResourceDll", "DescriptionResourceId")); } } else { if (CompilerCore.IntegerNotSet != descriptionResourceId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "DescriptionResourceId", "DescriptionResourceDll")); } } if (null != displayResourceDll) { if (CompilerCore.IntegerNotSet == displayResourceId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "DisplayResourceDll", "DisplayResourceId")); } } else { if (CompilerCore.IntegerNotSet != displayResourceId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "DisplayResourceId", "DisplayResourceDll")); } } // the ShortName and LongName attributes should not both be specified because LongName is only for // the old deprecated method of specifying a file name whereas ShortName is specifically for the new method if (null != shortName && null != longName) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "ShortName", "LongName")); } if (null == name) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name")); } else if (0 < name.Length) { if (CompilerCore.IsValidShortFilename(name, false)) { if (null == shortName) { shortName = name; } else { this.core.OnMessage(WixErrors.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name, "Name", name, "ShortName")); } } else { if (null == longName) { longName = name; // generate a short file name if (null == shortName) { shortName = this.core.GenerateShortName(name, true, false, node.LocalName, componentId, directory); } } else { this.core.OnMessage(WixErrors.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name, "Name", name, "LongName")); } } } if ("Component" != parentElementLocalName && null != target) { this.core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name, "Target", parentElementLocalName)); } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { switch (child.LocalName) { case "Icon": icon = this.ParseIconElement(child); break; case "ShortcutProperty": this.ParseShortcutPropertyElement(child, id); break; default: this.core.UnexpectedElement(node, child); break; } } else { this.core.UnsupportedExtensionElement(node, child); } } } if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "Shortcut"); row[0] = id; row[1] = directory; row[2] = GetMsiFilenameValue(shortName, longName); row[3] = componentId; if (advertise) { if (YesNoType.Yes != parentKeyPath && "Component" != parentElementLocalName) { this.core.OnMessage(WixWarnings.UnclearShortcut(sourceLineNumbers, id, componentId, defaultTarget)); } row[4] = Guid.Empty.ToString("B"); } else if (null != target) { row[4] = target; } else if ("Component" == parentElementLocalName || "CreateFolder" == parentElementLocalName) { row[4] = String.Format(CultureInfo.InvariantCulture, "[{0}]", defaultTarget); } else if ("File" == parentElementLocalName) { row[4] = String.Format(CultureInfo.InvariantCulture, "[#{0}]", defaultTarget); } row[5] = arguments; row[6] = description; if (CompilerCore.IntegerNotSet != hotkey) { row[7] = hotkey; } row[8] = icon; if (CompilerCore.IntegerNotSet != iconIndex) { row[9] = iconIndex; } if (CompilerCore.IntegerNotSet != show) { row[10] = show; } row[11] = workingDirectory; row[12] = displayResourceDll; if (CompilerCore.IntegerNotSet != displayResourceId) { row[13] = displayResourceId; } row[14] = descriptionResourceDll; if (CompilerCore.IntegerNotSet != descriptionResourceId) { row[15] = descriptionResourceId; } } }
/// <summary> /// Parses a Tag element for Software Id Tag registration under a Bundle element. /// </summary> /// <param name="node">The element to parse.</param> private void ParseBundleTagElement(XmlNode node) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string name = null; string regid = null; YesNoType licensed = YesNoType.NotSet; string type = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Name": name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); break; case "Regid": regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Licensed": licensed = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Type": type = this.ParseTagTypeAttribute(sourceLineNumbers, node, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.Schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (String.IsNullOrEmpty(name)) { XmlAttribute productNameAttribute = node.ParentNode.Attributes["Name"]; if (null != productNameAttribute) { name = productNameAttribute.Value; } else { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name")); } } if (!String.IsNullOrEmpty(name) && !CompilerCore.IsValidLongFilename(name, false)) { this.Core.OnMessage(TagErrors.IllegalName(sourceLineNumbers, node.ParentNode.LocalName, name)); } if (String.IsNullOrEmpty(regid)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Regid")); } if (!this.Core.EncounteredError) { string fileName = String.Concat(regid, " ", name, ".swidtag"); Row tagRow = this.Core.CreateRow(sourceLineNumbers, "WixBundleTag"); tagRow[0] = fileName; tagRow[1] = regid; tagRow[2] = name; if (YesNoType.Yes == licensed) { tagRow[3] = 1; } // field 4 is the TagXml set by the binder. tagRow[5] = type; } }
/// <summary> /// Converts an array to a magical bit. /// </summary> /// <param name="attributeNames">Array of attributes that map to bits.</param> /// <param name="attributeName">Name of attribute to check.</param> /// <param name="attributeValue">Value of attribute to check.</param> /// <returns>Bit set or -1 if not set.</returns> private static long NameToBit(string[] attributeNames, string attributeName, YesNoType attributeValue) { bool found = false; long bit = 1; if (null != attributeNames) // if there are no attributes to check there is no point in doing all the work in here { for (int i = 0; i < attributeNames.Length; i++) { if (attributeName == attributeNames[i]) // found the match, bail { if (YesNoType.Yes != attributeValue) // if the value was "no", reset the bit back to zero { bit = 0; } found = true; break; } // keep walking up the bit flags if (0x40000000 == bit) { bit = 0x80000000; // TODO: VBScript didn't handle the transition to the high bit, does C#? } else { bit += bit; // square the bit } } } return found ? bit : -1; }
/// <summary> /// Parses a progid element /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">Flag if progid is advertised.</param> /// <param name="classId">CLSID related to ProgId.</param> /// <param name="description">Default description of ProgId</param> /// <param name="parent">Optional parent ProgId</param> /// <param name="foundExtension">Set to true if an extension is found; used for error-checking.</param> /// <param name="firstProgIdForClass">Whether or not this ProgId is the first one found in the parent class.</param> /// <returns>This element's Id.</returns> private string ParseProgIdElement(XmlNode node, string componentId, YesNoType advertise, string classId, string description, string parent, ref bool foundExtension, YesNoType firstProgIdForClass) { SourceLineNumberCollection sourceLineNumbers = this.core.GetSourceLineNumbers(node); string icon = null; int iconIndex = CompilerCore.IntegerNotSet; string noOpen = null; string progId = null; foreach (XmlAttribute attrib in node.Attributes) { switch (attrib.LocalName) { case "Id": progId = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Advertise": YesNoType progIdAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == progIdAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == progIdAdvertise)) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, advertise.ToString(CultureInfo.InvariantCulture.NumberFormat), progIdAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = progIdAdvertise; break; case "Description": description = this.core.GetAttributeValue(sourceLineNumbers, attrib, true); break; case "Icon": icon = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "IconIndex": iconIndex = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib); break; case "NoOpen": noOpen = this.core.GetAttributeValue(sourceLineNumbers, attrib, true); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { switch (child.LocalName) { case "Extension": this.ParseExtensionElement(child, componentId, advertise, progId); foundExtension = true; break; case "ProgId": // Only allow one nested ProgId. If we have a child, we should not have a parent. if (null == parent) { if (YesNoType.Yes == advertise) { this.ParseProgIdElement(child, componentId, advertise, null, description, progId, ref foundExtension, firstProgIdForClass); } else if (YesNoType.No == advertise) { this.ParseProgIdElement(child, componentId, advertise, classId, description, progId, ref foundExtension, firstProgIdForClass); } } else { SourceLineNumberCollection childSourceLineNumbers = this.core.GetSourceLineNumbers(child); this.core.OnMessage(WixErrors.ProgIdNestedTooDeep(childSourceLineNumbers)); } break; default: this.core.UnexpectedElement(node, child); break; } } } if (YesNoType.Yes == advertise) { Row row = this.core.CreateRow(sourceLineNumbers, "ProgId"); row[0] = progId; row[1] = parent; row[2] = classId; row[3] = description; row[4] = icon; if (CompilerCore.IntegerNotSet != iconIndex) { row[5] = iconIndex; } } else if (YesNoType.No == advertise) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, progId, String.Empty, description, componentId); if (null != classId) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\CLSID"), String.Empty, classId, componentId); if (null != parent) // if this is a version independent ProgId { if (YesNoType.Yes == firstProgIdForClass) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\VersionIndependentProgID"), String.Empty, progId, componentId); } this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\CurVer"), String.Empty, parent, componentId); } else { if (YesNoType.Yes == firstProgIdForClass) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\ProgID"), String.Empty, progId, componentId); } } } if (null != icon) // ProgId's Default Icon { if (CompilerCore.IntegerNotSet != iconIndex) { icon = String.Concat(icon, ",", iconIndex); } this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\DefaultIcon"), String.Empty, icon, componentId); } } if (null != noOpen) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", progId), "NoOpen", noOpen, componentId); // ProgId NoOpen name } // raise an error for an orphaned ProgId if (YesNoType.Yes == advertise && !foundExtension && null == parent && null == classId) { this.core.OnMessage(WixWarnings.OrphanedProgId(sourceLineNumbers, WarningLevel.Moderate, progId)); } return progId; }
/// <summary> /// Parses a mime element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="extension">Identifier for parent extension.</param> /// <param name="componentId">Identifier for parent component.</param> /// <param name="advertise">Flag if mime should be advertised.</param> /// <returns>Content type if this is the default for the MIME type.</returns> private string ParseMIMEElement(XmlNode node, string extension, string componentId, YesNoType advertise) { SourceLineNumberCollection sourceLineNumbers = this.core.GetSourceLineNumbers(node); string classId = null; string contentType = null; YesNoType returnContentType = YesNoType.NotSet; foreach (XmlAttribute attrib in node.Attributes) { switch (attrib.LocalName) { case "Class": classId = String.Concat("{", this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false), "}"); break; case "ContentType": contentType = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Default": returnContentType = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } if (null == contentType) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "ContentType")); } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { this.core.UnexpectedElement(node, child); } } if (YesNoType.Yes == advertise) { Row row = this.core.CreateRow(sourceLineNumbers, "MIME"); row[0] = contentType; row[1] = extension; row[2] = classId; } else if (YesNoType.No == advertise) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("MIME\\Database\\Content Type\\", contentType), "Extension", String.Concat(".", extension), componentId); if (null != classId) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("MIME\\Database\\Content Type\\", contentType), "CLSID", classId, componentId); } } return YesNoType.Yes == returnContentType ? contentType : null; }
/// <summary> /// Sets a bit in a bit array based on the index at which an attribute name was found in a string array. /// </summary> /// <param name="attributeNames">Array of attributes that map to bits.</param> /// <param name="attributeName">Name of attribute to check.</param> /// <param name="attributeValue">Value of attribute to check.</param> /// <param name="bits">The bit array in which the bit will be set if found.</param> /// <param name="offset">The offset into the bit array.</param> /// <returns>true if the bit was set; false otherwise.</returns> public static bool NameToBit(string[] attributeNames, string attributeName, YesNoType attributeValue, BitArray bits, int offset) { for (int i = 0; i < attributeNames.Length; i++) { if (attributeNames[i] == attributeName) { if (YesNoType.Yes == attributeValue) { bits.Set(i + offset, true); } return true; } } return false; }
/// <summary> /// Parses a WixStandardBootstrapperApplication element for Bundles. /// </summary> /// <param name="node">The element to parse.</param> private void ParseWixStandardBootstrapperApplicationElement(XmlNode node) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string licenseFile = null; string licenseUrl = null; string logoFile = null; string themeFile = null; string localizationFile = null; YesNoType suppressOptionsUI = YesNoType.NotSet; YesNoType suppressDowngradeFailure = YesNoType.NotSet; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "LicenseFile": licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LicenseUrl": licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LogoFile": logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "ThemeFile": themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LocalizationFile": localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "SuppressOptionsUI": suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressDowngradeFailure": suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (String.IsNullOrEmpty(licenseFile) == String.IsNullOrEmpty(licenseUrl)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "LicenseFile", "LicenseUrl", true)); } if (!this.Core.EncounteredError) { if (!String.IsNullOrEmpty(licenseFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLicenseRtf", licenseFile, false); } if (!String.IsNullOrEmpty(licenseUrl)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLicenseUrl", licenseUrl, false); } if (!String.IsNullOrEmpty(logoFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLogo", logoFile, false); } if (!String.IsNullOrEmpty(themeFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaThemeXml", themeFile, false); } if (!String.IsNullOrEmpty(localizationFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaThemeWxl", localizationFile, false); } if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure) { Row row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOptions"); if (YesNoType.Yes == suppressOptionsUI) { row[0] = 1; } if (YesNoType.Yes == suppressDowngradeFailure) { row[1] = 1; } } } }
/// <summary> /// Parses a Tag element for Software Id Tag registration under a Bundle element. /// </summary> /// <param name="node">The element to parse.</param> private void ParseBundleTagElement(XElement node) { SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string name = null; string regid = null; YesNoType licensed = YesNoType.NotSet; string type = null; foreach (XAttribute attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "Name": name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); break; case "Regid": regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Licensed": licensed = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Type": type = this.ParseTagTypeAttribute(sourceLineNumbers, node, attrib); break; default: this.Core.UnexpectedAttribute(node, attrib); break; } } else { this.Core.ParseExtensionAttribute(node, attrib); } } this.Core.ParseForExtensionElements(node); if (String.IsNullOrEmpty(name)) { XAttribute productNameAttribute = node.Parent.Attribute("Name"); if (null != productNameAttribute) { name = productNameAttribute.Value; } else { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); } } if (!String.IsNullOrEmpty(name) && !this.Core.IsValidLongFilename(name, false)) { this.Core.OnMessage(TagErrors.IllegalName(sourceLineNumbers, node.Parent.Name.LocalName, name)); } if (String.IsNullOrEmpty(regid)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Regid")); } if (!this.Core.EncounteredError) { string fileName = String.Concat(regid, " ", name, ".swidtag"); Row tagRow = this.Core.CreateRow(sourceLineNumbers, "WixBundleTag"); tagRow[0] = fileName; tagRow[1] = regid; tagRow[2] = name; if (YesNoType.Yes == licensed) { tagRow[3] = 1; } // field 4 is the TagXml set by the binder. tagRow[5] = type; } }
/// <summary> /// Parses a HelpFilter element. /// </summary> /// <param name="node">Element to process.</param> private void ParseHelpFilterElement(XElement node) { SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; string filterDefinition = null; string name = null; YesNoType suppressCAs = YesNoType.No; foreach (XAttribute attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "Id": id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "FilterDefinition": filterDefinition = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Name": name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "SuppressCustomActions": suppressCAs = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.ParseExtensionAttribute(node, attrib); } } if (null == id) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); } if (null == name) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); } this.Core.ParseForExtensionElements(node); if (!this.Core.EncounteredError) { Row row = this.Core.CreateRow(sourceLineNumbers, "HelpFilter"); row[0] = id; row[1] = name; row[2] = filterDefinition; if (YesNoType.No == suppressCAs) { this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "CA_RegisterMicrosoftHelp.3643236F_FC70_11D3_A536_0090278A1BB8"); } } }
private void ParsePlugCollectionIntoElement(Intermediate intermediate, IntermediateSection section, XElement element, Identifier parentId) { SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); string hxa = null; string hxt = null; string hxtParent = null; string namespaceParent = null; string feature = null; YesNoType suppressExternalNamespaces = YesNoType.No; bool pluginVS05 = false; bool pluginVS08 = false; foreach (XAttribute attrib in element.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "Attributes": hxa = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TableOfContents": hxt = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetCollection": namespaceParent = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetTableOfContents": hxtParent = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetFeature": feature = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "SuppressExternalNamespaces": suppressExternalNamespaces = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.ParseHelper.UnexpectedAttribute(element, attrib); break; } } else { this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); } } pluginVS05 = namespaceParent.Equals("MS_VSIPCC_v80", StringComparison.Ordinal); pluginVS08 = namespaceParent.Equals("MS.VSIPCC.v90", StringComparison.Ordinal); if (null == namespaceParent) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "TargetCollection")); } if (null == feature && (pluginVS05 || pluginVS08) && YesNoType.No == suppressExternalNamespaces) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "TargetFeature")); } this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); if (!this.Messaging.EncounteredError) { var row = this.ParseHelper.CreateRow(section, sourceLineNumbers, "HelpPlugin", parentId); row.Set(1, namespaceParent); row.Set(2, hxt); row.Set(3, hxa); row.Set(4, hxtParent); if (pluginVS05) { if (YesNoType.No == suppressExternalNamespaces) { // Bring in the help 2 base namespace components for VS 2005 this.ParseHelper.CreateComplexReference(section, sourceLineNumbers, ComplexReferenceParentType.Feature, feature, String.Empty, ComplexReferenceChildType.ComponentGroup, "Help2_VS2005_Namespace_Components", false); // Reference CustomAction since nothing will happen without it this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "CA_HxMerge_VSIPCC_VSCC"); } } else if (pluginVS08) { if (YesNoType.No == suppressExternalNamespaces) { // Bring in the help 2 base namespace components for VS 2008 this.ParseHelper.CreateComplexReference(section, sourceLineNumbers, ComplexReferenceParentType.Feature, feature, String.Empty, ComplexReferenceChildType.ComponentGroup, "Help2_VS2008_Namespace_Components", false); // Reference CustomAction since nothing will happen without it this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "CA_ScheduleExtHelpPlugin_VSCC_VSIPCC"); } } else { // Reference the parent namespace to enforce the foreign key relationship this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "HelpNamespace", namespaceParent); } } }
/// <summary> /// Parses a PlugCollectionInto element. /// </summary> /// <param name="node">Element to process.</param> /// <param name="parentId">Identifier of the parent help collection.</param> private void ParsePlugCollectionIntoElement(XmlNode node, string parentId) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string hxa = null; string hxt = null; string hxtParent = null; string namespaceParent = null; string feature = null; YesNoType suppressExternalNamespaces = YesNoType.No; bool pluginVS05 = false; bool pluginVS08 = false; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Attributes": hxa = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TableOfContents": hxt = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetCollection": namespaceParent = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetTableOfContents": hxtParent = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "TargetFeature": feature = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "SuppressExternalNamespaces": suppressExternalNamespaces = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } pluginVS05 = namespaceParent.Equals("MS_VSIPCC_v80", StringComparison.Ordinal); pluginVS08 = namespaceParent.Equals("MS.VSIPCC.v90", StringComparison.Ordinal); if (null == namespaceParent) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "TargetCollection")); } if (null == feature && (pluginVS05 || pluginVS08) && YesNoType.No == suppressExternalNamespaces) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "TargetFeature")); } // find unexpected child elements foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (!this.Core.EncounteredError) { Row row = this.Core.CreateRow(sourceLineNumbers, "HelpPlugin"); row[0] = parentId; row[1] = namespaceParent; row[2] = hxt; row[3] = hxa; row[4] = hxtParent; if (pluginVS05) { if (YesNoType.No == suppressExternalNamespaces) { // Bring in the help 2 base namespace components for VS 2005 this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Feature, feature, String.Empty, ComplexReferenceChildType.ComponentGroup, "Help2_VS2005_Namespace_Components", false); // Reference CustomAction since nothing will happen without it this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "CA_HxMerge_VSIPCC_VSCC"); } } else if (pluginVS08) { if (YesNoType.No == suppressExternalNamespaces) { // Bring in the help 2 base namespace components for VS 2008 this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Feature, feature, String.Empty, ComplexReferenceChildType.ComponentGroup, "Help2_VS2008_Namespace_Components", false); // Reference CustomAction since nothing will happen without it this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "CA_ScheduleExtHelpPlugin_VSCC_VSIPCC"); } } else { // Reference the parent namespace to enforce the foreign key relationship this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "HelpNamespace", namespaceParent); } } }
/// <summary> /// Creates the row for a Payload. /// </summary> /// <param name="node">Element to parse</param> /// <param name="parentType">ComplexReferenceParentType of parent element</param> /// <param name="parentId">Identifier of parent element.</param> private void CreatePayloadRow(SourceLineNumberCollection sourceLineNumbers, string id, string name, string sourceFile, string downloadUrl, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId, YesNoDefaultType compressed, YesNoType suppressSignatureVerification, string displayName, string description) { if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "Payload"); row[0] = id; row[1] = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name; row[2] = sourceFile; row[3] = downloadUrl; if (YesNoDefaultType.Default != compressed) { row[4] = (YesNoDefaultType.Yes == compressed) ? 1 : 0; } row[5] = sourceFile; // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding. row[6] = (YesNoType.Yes == suppressSignatureVerification) ? 1 : 0; if (!String.IsNullOrEmpty(description) || !String.IsNullOrEmpty(displayName)) { Row rowDisplay = this.core.CreateRow(sourceLineNumbers, "PayloadDisplayInformation"); rowDisplay[0] = id; rowDisplay[1] = displayName; rowDisplay[2] = description; } this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, id, previousType, previousId); } }
/// <summary> /// Parses a VsixPackage element. /// </summary> /// <param name="node">Element to process.</param> /// <param name="componentId">Identifier of the parent Component element.</param> /// <param name="fileId">Identifier of the parent File element.</param> private void ParseVsixPackageElement(XmlNode node, string componentId, string fileId) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string propertyId = "VS_VSIX_INSTALLER_PATH"; string packageId = null; YesNoType permanent = YesNoType.NotSet; string target = null; string targetVersion = null; YesNoType vital = YesNoType.NotSet; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "File": if (String.IsNullOrEmpty(fileId)) { fileId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); } else { this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name, "File", "File")); } break; case "PackageId": packageId = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Permanent": permanent = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Target": target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); switch (target.ToLowerInvariant()) { case "integrated": case "integratedshell": target = "IntegratedShell"; break; case "professional": target = "Pro"; break; case "premium": target = "Premium"; break; case "ultimate": target = "Ultimate"; break; case "vbexpress": target = "VBExpress"; break; case "vcexpress": target = "VCExpress"; break; case "vcsexpress": target = "VCSExpress"; break; case "vwdexpress": target = "VWDExpress"; break; } break; case "TargetVersion": targetVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib, true); break; case "Vital": vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "VsixInstallerPathProperty": propertyId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.ParseExtensionAttribute(sourceLineNumbers, (XmlElement)node, attrib); } } if (String.IsNullOrEmpty(fileId)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "File")); } if (String.IsNullOrEmpty(packageId)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "PackageId")); } if (!String.IsNullOrEmpty(target) && String.IsNullOrEmpty(targetVersion)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "TargetVersion", "Target")); } else if (String.IsNullOrEmpty(target) && !String.IsNullOrEmpty(targetVersion)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Target", "TargetVersion")); } // find unexpected child elements foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (!this.Core.EncounteredError) { // Ensure there is a reference to the AppSearch Property that will find the VsixInstaller.exe. this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Property", propertyId); // Ensure there is a reference to the package file (even if we are a child under it). this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", fileId); string cmdlinePrefix = "/q "; if (!String.IsNullOrEmpty(target)) { cmdlinePrefix = String.Format("{0} /skuName:{1} /skuVersion:{2}", cmdlinePrefix, target, targetVersion); } string installAfter = "WriteRegistryValues"; // by default, come after the registry key registration. int installExtraBits = VSCompiler.MsidbCustomActionTypeInScript; // If the package is not vital, mark the install action as continue. if (vital == YesNoType.No) { installExtraBits |= VSCompiler.MsidbCustomActionTypeContinue; } else // the package is vital so ensure there is a rollback action scheduled. { string rollbackNamePerUser = this.Core.GenerateIdentifier("vru", componentId, fileId, "per-user", target ?? String.Empty, targetVersion ?? String.Empty); string rollbackNamePerMachine = this.Core.GenerateIdentifier("vrm", componentId, fileId, "per-machine", target ?? String.Empty, targetVersion ?? String.Empty); string rollbackCmdLinePerUser = String.Concat(cmdlinePrefix, " /u:\"", packageId, "\""); string rollbackCmdLinePerMachine = String.Concat(rollbackCmdLinePerUser, " /admin"); int rollbackExtraBitsPerUser = VSCompiler.MsidbCustomActionTypeContinue | VSCompiler.MsidbCustomActionTypeRollback | VSCompiler.MsidbCustomActionTypeInScript; int rollbackExtraBitsPerMachine = rollbackExtraBitsPerUser | VSCompiler.MsidbCustomActionTypeNoImpersonate; string rollbackConditionPerUser = String.Format("NOT ALLUSERS AND NOT Installed AND ${0}=2 AND ?{0}>2", componentId); // NOT Installed && Component being installed but not installed already. string rollbackConditionPerMachine = String.Format("ALLUSERS AND NOT Installed AND ${0}=2 AND ?{0}>2", componentId); // NOT Installed && Component being installed but not installed already. this.SchedulePropertyExeAction(sourceLineNumbers, rollbackNamePerUser, propertyId, rollbackCmdLinePerUser, rollbackExtraBitsPerUser, rollbackConditionPerUser, null, installAfter); this.SchedulePropertyExeAction(sourceLineNumbers, rollbackNamePerMachine, propertyId, rollbackCmdLinePerMachine, rollbackExtraBitsPerMachine, rollbackConditionPerMachine, null, rollbackNamePerUser); installAfter = rollbackNamePerMachine; } string installNamePerUser = this.Core.GenerateIdentifier("viu", componentId, fileId, "per-user", target ?? String.Empty, targetVersion ?? String.Empty); string installNamePerMachine = this.Core.GenerateIdentifier("vim", componentId, fileId, "per-machine", target ?? String.Empty, targetVersion ?? String.Empty); string installCmdLinePerUser = String.Format("{0} \"[#{1}]\"", cmdlinePrefix, fileId); string installCmdLinePerMachine = String.Concat(installCmdLinePerUser, " /admin"); string installConditionPerUser = String.Format("NOT ALLUSERS AND ${0}=3", componentId); // only execute if the Component being installed. string installConditionPerMachine = String.Format("ALLUSERS AND ${0}=3", componentId); // only execute if the Component being installed. this.SchedulePropertyExeAction(sourceLineNumbers, installNamePerUser, propertyId, installCmdLinePerUser, installExtraBits, installConditionPerUser, null, installAfter); this.SchedulePropertyExeAction(sourceLineNumbers, installNamePerMachine, propertyId, installCmdLinePerMachine, installExtraBits | VSCompiler.MsidbCustomActionTypeNoImpersonate, installConditionPerMachine, null, installNamePerUser); // If not permanent, schedule the uninstall custom action. if (permanent != YesNoType.Yes) { string uninstallNamePerUser = this.Core.GenerateIdentifier("vuu", componentId, fileId, "per-user", target ?? String.Empty, targetVersion ?? String.Empty); string uninstallNamePerMachine = this.Core.GenerateIdentifier("vum", componentId, fileId, "per-machine", target ?? String.Empty, targetVersion ?? String.Empty); string uninstallCmdLinePerUser = String.Concat(cmdlinePrefix, " /u:\"", packageId, "\""); string uninstallCmdLinePerMachine = String.Concat(uninstallCmdLinePerUser, " /admin"); int uninstallExtraBitsPerUser = VSCompiler.MsidbCustomActionTypeContinue | VSCompiler.MsidbCustomActionTypeInScript; int uninstallExtraBitsPerMachine = uninstallExtraBitsPerUser | VSCompiler.MsidbCustomActionTypeNoImpersonate; string uninstallConditionPerUser = String.Format("NOT ALLUSERS AND ${0}=2 AND ?{0}>2", componentId); // Only execute if component is being uninstalled. string uninstallConditionPerMachine = String.Format("ALLUSERS AND ${0}=2 AND ?{0}>2", componentId); // Only execute if component is being uninstalled. this.SchedulePropertyExeAction(sourceLineNumbers, uninstallNamePerUser, propertyId, uninstallCmdLinePerUser, uninstallExtraBitsPerUser, uninstallConditionPerUser, "InstallFinalize", null); this.SchedulePropertyExeAction(sourceLineNumbers, uninstallNamePerMachine, propertyId, uninstallCmdLinePerMachine, uninstallExtraBitsPerMachine, uninstallConditionPerMachine, "InstallFinalize", null); } } }
/// <summary> /// Parses an extension element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">Flag if this extension is advertised.</param> /// <param name="progId">ProgId for extension.</param> private void ParseExtensionElement(XmlNode node, string componentId, YesNoType advertise, string progId) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string extension = null; string mime = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": extension = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Advertise": YesNoType extensionAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == extensionAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == extensionAdvertise)) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, extensionAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat), advertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = extensionAdvertise; break; case "ContentType": mime = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { Dictionary<string, string> contextValues = new Dictionary<string, string>(); contextValues["ProgId"] = progId; contextValues["ComponentId"] = componentId; this.core.ParseExtensionAttribute(sourceLineNumbers, (XmlElement)node, attrib, contextValues); } } if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { switch (child.LocalName) { case "Verb": this.ParseVerbElement(child, extension, progId, componentId, advertise); break; case "MIME": string newMime = this.ParseMIMEElement(child, extension, componentId, advertise); if (null != newMime && null == mime) { mime = newMime; } break; default: this.core.UnexpectedElement(node, child); break; } } else { this.core.UnsupportedExtensionElement(node, child); } } } if (YesNoType.Yes == advertise) { if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "Extension"); row[0] = extension; row[1] = componentId; row[2] = progId; row[3] = mime; row[4] = Guid.Empty.ToString("B"); this.core.EnsureTable(sourceLineNumbers, "Verb"); } } else if (YesNoType.No == advertise) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension), String.Empty, progId, componentId); // Extension if (null != mime) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension), "Content Type", mime, componentId); // Extension's MIME ContentType } } }
/// <summary> /// Parses a Tag element for Software Id Tag registration under a Product element. /// </summary> /// <param name="node">The element to parse.</param> private void ParseProductTagElement(XmlNode node) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string name = null; string regid = null; string feature = "WixSwidTag"; YesNoType licensed = YesNoType.NotSet; string type = null;; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Name": name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); break; case "Regid": regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Feature": feature = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "Licensed": licensed = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Type": type = this.ParseTagTypeAttribute(sourceLineNumbers, node, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.Schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (String.IsNullOrEmpty(name)) { XmlAttribute productNameAttribute = node.ParentNode.Attributes["Name"]; if (null != productNameAttribute) { name = productNameAttribute.Value; } else { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name")); } } if (!String.IsNullOrEmpty(name) && !CompilerCore.IsValidLongFilename(name, false)) { this.Core.OnMessage(TagErrors.IllegalName(sourceLineNumbers, node.ParentNode.LocalName, name)); } if (String.IsNullOrEmpty(regid)) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Regid")); } if (!this.Core.EncounteredError) { string directoryId = "WixTagRegidFolder"; string fileId = this.Core.GenerateIdentifier("tag", regid, ".product.tag"); string fileName = String.Concat(regid, " ", name, ".swidtag"); string shortName = this.Core.GenerateShortName(fileName, false, false); this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Directory", directoryId); ComponentRow componentRow = (ComponentRow)this.Core.CreateRow(sourceLineNumbers, "Component"); componentRow.Component = fileId; componentRow.Guid = "*"; componentRow[3] = 0; componentRow.Directory = directoryId; componentRow.IsLocalOnly = true; componentRow.KeyPath = fileId; this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Feature", feature); this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Feature, feature, null, ComplexReferenceChildType.Component, fileId, true); FileRow fileRow = (FileRow)this.Core.CreateRow(sourceLineNumbers, "File"); fileRow.File = fileId; fileRow.Component = fileId; fileRow.FileName = String.Concat(shortName, "|", fileName); WixFileRow wixFileRow = (WixFileRow)this.Core.CreateRow(sourceLineNumbers, "WixFile"); wixFileRow.Directory = directoryId; wixFileRow.File = fileId; wixFileRow.DiskId = 1; wixFileRow.Attributes = 1; wixFileRow.Source = String.Concat("%TEMP%\\", fileName); this.Core.EnsureTable(sourceLineNumbers, "SoftwareIdentificationTag"); Row row = this.Core.CreateRow(sourceLineNumbers, "WixProductTag"); row[0] = fileId; row[1] = regid; row[2] = name; if (YesNoType.Yes == licensed) { row[3] = 1; } row[4] = type; this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", fileId); } }
private void ParseFileElement(XmlNode node) { SourceLineNumberCollection sourceLineNumber = Preprocessor.GetSourceLineNumbers(node); string superElementId = null; string file = null; string arguments = null; var elevated = YesNoType.No; YesNoType ignoreErrors = YesNoType.No; foreach (XmlAttribute attribute in node.Attributes) { if (attribute.NamespaceURI.Length == 0 || attribute.NamespaceURI == _schema.TargetNamespace) { switch (attribute.LocalName) { case "Id": superElementId = Core.GetAttributeIdentifierValue(sourceLineNumber, attribute); break; case "File": file = Core.GetAttributeValue(sourceLineNumber, attribute, false); break; case "Arguments": arguments = Core.GetAttributeValue(sourceLineNumber, attribute); break; case "Elevated": elevated = Core.GetAttributeYesNoValue(sourceLineNumber, attribute); break; case "IgnoreErrors": ignoreErrors = Core.GetAttributeYesNoValue(sourceLineNumber, attribute); break; default: Core.UnexpectedAttribute(sourceLineNumber, attribute); break; } } else { Core.UnsupportedExtensionAttribute(sourceLineNumber, attribute); } } if (string.IsNullOrEmpty(superElementId)) { Core.OnMessage( WixErrors.ExpectedAttribute(sourceLineNumber, node.Name, "Id")); } if (string.IsNullOrEmpty(file)) { Core.OnMessage( WixErrors.ExpectedElement(sourceLineNumber, node.Name, "File")); } if (!Core.EncounteredError) { Row superElementRow = Core.CreateRow(sourceLineNumber, "PowerShellFiles"); superElementRow[0] = superElementId; superElementRow[1] = file; superElementRow[2] = arguments; superElementRow[3] = elevated == YesNoType.Yes ? 1 : 0; superElementRow[4] = (ignoreErrors == YesNoType.Yes) ? 1 : 0; } Core.CreateWixSimpleReferenceRow(sourceLineNumber, "CustomAction", "PowerShellFilesImmediate"); }
/// <summary> /// Parses a WixExtendedBootstrapperApplication element for Bundles. /// </summary> /// <param name="node">The element to parse.</param> private void ParseWixExtendedBootstrapperApplicationElement(XmlNode node) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string launchTarget = null; string launchTargetElevatedId = null; string launchArguments = null; YesNoType launchHidden = YesNoType.NotSet; string launchWorkingDir = null; string licenseFile = null; string licenseUrl = null; string logoFile = null; string logoSideFile = null; string themeFile = null; string localizationFile = null; YesNoType suppressOptionsUI = YesNoType.NotSet; YesNoType suppressDowngradeFailure = YesNoType.NotSet; YesNoType suppressRepair = YesNoType.NotSet; YesNoType showVersion = YesNoType.NotSet; YesNoType supportCacheOnly = YesNoType.NotSet; YesNoType showFilesInUse = YesNoType.NotSet; YesNoType launchPassive = YesNoType.NotSet; YesNoType launchQuiet = YesNoType.NotSet; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "LaunchTarget": launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LaunchTargetElevatedId": launchTargetElevatedId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "LaunchArguments": launchArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LaunchHidden": launchHidden = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "LaunchWorkingFolder": launchWorkingDir = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LicenseFile": licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LicenseUrl": licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, true); break; case "LogoFile": logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LogoSideFile": logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "ThemeFile": themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LocalizationFile": localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "SuppressOptionsUI": suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "LaunchPassive": launchPassive = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "LaunchQuiet": launchQuiet = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressDowngradeFailure": suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressRepair": suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ShowVersion": showVersion = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SupportCacheOnly": supportCacheOnly = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ShowFilesInUse": showFilesInUse = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.Core.UnexpectedElement(node, child); } else { this.Core.UnsupportedExtensionElement(node, child); } } } if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "LicenseFile", "LicenseUrl", true)); } if (!this.Core.EncounteredError) { if (!String.IsNullOrEmpty(launchTarget)) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchTarget", launchTarget, "string", false, false); } if (!String.IsNullOrEmpty(launchTargetElevatedId)) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchTargetElevatedId", launchTargetElevatedId, "string", false, false); } if (!String.IsNullOrEmpty(launchArguments)) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchArguments", launchArguments, "string", false, false); } if (YesNoType.Yes == launchHidden) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchHidden", "yes", "string", false, false); } if (!String.IsNullOrEmpty(launchWorkingDir)) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchWorkingFolder", launchWorkingDir, "string", false, false); } if (!String.IsNullOrEmpty(licenseFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLicenseRtf", licenseFile, false); } if (null != licenseUrl) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLicenseUrl", licenseUrl, false); } if (!String.IsNullOrEmpty(logoFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLogo", logoFile, false); } if (!String.IsNullOrEmpty(logoSideFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLogoSide", logoSideFile, false); } if (!String.IsNullOrEmpty(themeFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaThemeXml", themeFile, false); } if (!String.IsNullOrEmpty(localizationFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaThemeWxl", localizationFile, false); } if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair || YesNoType.Yes == showVersion || YesNoType.Yes == supportCacheOnly || YesNoType.Yes == showFilesInUse) { Row row = this.Core.CreateRow(sourceLineNumbers, "WixExtbaOptions"); if (YesNoType.Yes == suppressOptionsUI) { row[0] = 1; } if (YesNoType.Yes == suppressDowngradeFailure) { row[1] = 1; } if (YesNoType.Yes == suppressRepair) { row[2] = 1; } if (YesNoType.Yes == showVersion) { row[3] = 1; } if (YesNoType.Yes == showFilesInUse) { row[4] = 1; } if (YesNoType.Yes == supportCacheOnly) { row[5] = 1; } if (YesNoType.Yes == launchPassive) { row[6] = 1; } if (YesNoType.Yes == launchQuiet) { row[7] = 1; } } } }
/// <summary> /// Parses a verb element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="extension">Extension verb is releated to.</param> /// <param name="progId">Optional progId for extension.</param> /// <param name="componentId">Identifier for parent component.</param> /// <param name="advertise">Flag if extension is advertised.</param> private void ParseVerbElement(XmlNode node, string extension, string progId, string componentId, YesNoType advertise) { SourceLineNumberCollection sourceLineNumbers = this.core.GetSourceLineNumbers(node); string id = null; string target = null; string command = null; string argument = null; int sequence = CompilerCore.IntegerNotSet; foreach (XmlAttribute attrib in node.Attributes) { switch (attrib.LocalName) { case "Id": id = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Argument": argument = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Command": command = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Sequence": sequence = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib); break; case "Target": target = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } if (null == id) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { this.core.UnexpectedElement(node, child); } } if (YesNoType.Yes == advertise) { if (null != target) { this.core.OnMessage(WixErrors.IllegalAttributeWhenAdvertised(sourceLineNumbers, node.Name, "Target")); } Row row = this.core.CreateRow(sourceLineNumbers, "Verb"); row[0] = extension; row[1] = id; if (CompilerCore.IntegerNotSet != sequence) { row[2] = sequence; } row[3] = command; row[4] = argument; } else if (YesNoType.No == advertise) { if (null == target) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Target", "Advertise", "no")); } if (null != argument) { target = String.Concat(target, " ", argument); } if (null != progId) { if (null != command) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\shell\\", id), String.Empty, command, componentId); } this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\shell\\", id, "\\command"), String.Empty, target, componentId); } else { if (null != command) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension, "\\shell\\", id), String.Empty, command, componentId); } this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension, "\\shell\\", id, "\\command"), String.Empty, target, componentId); } } }
/// <summary> /// Parses a progid element /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">Flag if progid is advertised.</param> /// <param name="classId">CLSID related to ProgId.</param> /// <param name="description">Default description of ProgId</param> /// <param name="parent">Optional parent ProgId</param> /// <param name="foundExtension">Set to true if an extension is found; used for error-checking.</param> /// <param name="firstProgIdForClass">Whether or not this ProgId is the first one found in the parent class.</param> /// <returns>This element's Id.</returns> private string ParseProgIdElement(XmlNode node, string componentId, YesNoType advertise, string classId, string description, string parent, ref bool foundExtension, YesNoType firstProgIdForClass) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string icon = null; int iconIndex = CompilerCore.IntegerNotSet; string noOpen = null; string progId = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": progId = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Advertise": YesNoType progIdAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == progIdAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == progIdAdvertise)) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, advertise.ToString(CultureInfo.InvariantCulture.NumberFormat), progIdAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = progIdAdvertise; break; case "Description": description = this.core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); break; case "Icon": icon = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "IconIndex": iconIndex = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, short.MinValue + 1, short.MaxValue); break; case "NoOpen": noOpen = this.core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } if (null != parent && (null != icon || CompilerCore.IntegerNotSet != iconIndex)) { this.core.OnMessage(WixErrors.VersionIndependentProgIdsCannotHaveIcons(sourceLineNumbers)); } YesNoType firstProgIdForNestedClass = YesNoType.Yes; foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { switch (child.LocalName) { case "Extension": this.ParseExtensionElement(child, componentId, advertise, progId); foundExtension = true; break; case "ProgId": // Only allow one nested ProgId. If we have a child, we should not have a parent. if (null == parent) { if (YesNoType.Yes == advertise) { this.ParseProgIdElement(child, componentId, advertise, null, description, progId, ref foundExtension, firstProgIdForNestedClass); } else if (YesNoType.No == advertise) { this.ParseProgIdElement(child, componentId, advertise, classId, description, progId, ref foundExtension, firstProgIdForNestedClass); } firstProgIdForNestedClass = YesNoType.No; // any ProgId after this one is definitely not the first. } else { SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); this.core.OnMessage(WixErrors.ProgIdNestedTooDeep(childSourceLineNumbers)); } break; default: this.core.UnexpectedElement(node, child); break; } } else { this.core.UnsupportedExtensionElement(node, child); } } } if (YesNoType.Yes == advertise) { if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "ProgId"); row[0] = progId; row[1] = parent; row[2] = classId; row[3] = description; if (null != icon) { row[4] = icon; this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Icon", icon); } if (CompilerCore.IntegerNotSet != iconIndex) { row[5] = iconIndex; } this.core.EnsureTable(sourceLineNumbers, "Class"); } } else if (YesNoType.No == advertise) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, progId, String.Empty, description, componentId); if (null != classId) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\CLSID"), String.Empty, classId, componentId); if (null != parent) // if this is a version independent ProgId { if (YesNoType.Yes == firstProgIdForClass) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\VersionIndependentProgID"), String.Empty, progId, componentId); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\CurVer"), String.Empty, parent, componentId); } else { if (YesNoType.Yes == firstProgIdForClass) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\ProgID"), String.Empty, progId, componentId); } } } if (null != icon) // ProgId's Default Icon { this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", icon); icon = String.Format(CultureInfo.InvariantCulture, "\"[#{0}]\"", icon); if (CompilerCore.IntegerNotSet != iconIndex) { icon = String.Concat(icon, ",", iconIndex); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(progId, "\\DefaultIcon"), String.Empty, icon, componentId); } } if (null != noOpen) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, progId, "NoOpen", noOpen, componentId); // ProgId NoOpen name } // raise an error for an orphaned ProgId if (YesNoType.Yes == advertise && !foundExtension && null == parent && null == classId) { this.core.OnMessage(WixWarnings.OrphanedProgId(sourceLineNumbers, progId)); } return progId; }
/// <summary> /// Parses an extension element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">Flag if this extension is advertised.</param> /// <param name="progId">ProgId for extension.</param> private void ParseExtensionElement(XmlNode node, string componentId, YesNoType advertise, string progId) { SourceLineNumberCollection sourceLineNumbers = this.core.GetSourceLineNumbers(node); string extension = null; string mime = null; foreach (XmlAttribute attrib in node.Attributes) { switch (attrib.LocalName) { case "Id": extension = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Advertise": YesNoType extensionAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == extensionAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == extensionAdvertise)) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, extensionAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat), advertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = extensionAdvertise; break; case "ContentType": mime = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { switch (child.LocalName) { case "Verb": this.ParseVerbElement(child, extension, progId, componentId, advertise); break; case "MIME": string newMime = this.ParseMIMEElement(child, extension, componentId, advertise); if (null != newMime && null == mime) { mime = newMime; } break; default: this.core.UnexpectedElement(node, child); break; } } } if (YesNoType.Yes == advertise) { Row row = this.core.CreateRow(sourceLineNumbers, "Extension"); row[0] = extension; row[1] = componentId; row[2] = progId; row[3] = mime; row[4] = Guid.Empty.ToString("B"); this.core.AddFeatureBacklink(new FeatureBacklink(componentId, FeatureBacklinkType.Extension, row.Symbol)); } else if (YesNoType.No == advertise) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension), String.Empty, progId, componentId); // Extension if (null != mime) { this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(".", extension), "Content Type", mime, componentId); // Extension's MIME ContentType } } }
/// <summary> /// Parses a verb element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="extension">Extension verb is releated to.</param> /// <param name="progId">Optional progId for extension.</param> /// <param name="componentId">Identifier for parent component.</param> /// <param name="advertise">Flag if verb is advertised.</param> private void ParseVerbElement(XmlNode node, string extension, string progId, string componentId, YesNoType advertise) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; string argument = null; string command = null; int sequence = CompilerCore.IntegerNotSet; string target = null; string targetFile = null; string targetProperty = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": id = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Argument": argument = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Command": command = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Sequence": sequence = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); break; case "Target": target = this.core.GetAttributeValue(sourceLineNumbers, attrib); this.core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name, attrib.Name, "TargetFile", "TargetProperty")); break; case "TargetFile": targetFile = this.core.GetAttributeValue(sourceLineNumbers, attrib); this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", targetFile); break; case "TargetProperty": targetProperty = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (null == id) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } if (null != target && null != targetFile) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Target", "TargetFile")); } if (null != target && null != targetProperty) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Target", "TargetProperty")); } if (null != targetFile && null != targetProperty) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "TargetFile", "TargetProperty")); } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.core.UnexpectedElement(node, child); } else { this.core.UnsupportedExtensionElement(node, child); } } } if (YesNoType.Yes == advertise) { if (null != target) { this.core.OnMessage(WixErrors.IllegalAttributeWhenAdvertised(sourceLineNumbers, node.Name, "Target")); } if (null != targetFile) { this.core.OnMessage(WixErrors.IllegalAttributeWhenAdvertised(sourceLineNumbers, node.Name, "TargetFile")); } if (null != targetProperty) { this.core.OnMessage(WixErrors.IllegalAttributeWhenAdvertised(sourceLineNumbers, node.Name, "TargetProperty")); } if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "Verb"); row[0] = extension; row[1] = id; if (CompilerCore.IntegerNotSet != sequence) { row[2] = sequence; } row[3] = command; row[4] = argument; } } else if (YesNoType.No == advertise) { if (CompilerCore.IntegerNotSet != sequence) { this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Sequence", "Advertise", "no")); } if (null == target && null == targetFile && null == targetProperty) { this.core.OnMessage(WixErrors.ExpectedAttributesWithOtherAttribute(sourceLineNumbers, node.Name, "TargetFile", "TargetProperty", "Advertise", "no")); } if (null == target) { if (null != targetFile) { target = String.Concat("\"[#", targetFile, "]\""); } if (null != targetProperty) { target = String.Concat("\"[", targetProperty, "]\""); } } if (null != argument) { target = String.Concat(target, " ", argument); } string prefix = (null != progId ? progId : String.Concat(".", extension)); if (null != command) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(prefix, "\\shell\\", id), String.Empty, command, componentId); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat(prefix, "\\shell\\", id, "\\command"), String.Empty, target, componentId); } }
private void ParseHelpFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId) { SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); Identifier id = null; string name = null; int language = CompilerConstants.IntegerNotSet; string hxi = null; string hxq = null; string hxr = null; string samples = null; YesNoType suppressCAs = YesNoType.No; foreach (XAttribute attrib in element.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "Id": id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); break; case "AttributeIndex": hxr = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", hxr); break; case "Index": hxi = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", hxi); break; case "Language": language = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue); break; case "Name": name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "SampleLocation": samples = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", samples); break; case "Search": hxq = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", hxq); break; case "SuppressCustomActions": suppressCAs = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.ParseHelper.UnexpectedAttribute(element, attrib); break; } } else { this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); } } if (null == id) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); } if (null == name) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); } // Uninstall will always fail silently, leaving file registered, if Language is not set if (CompilerConstants.IntegerNotSet == language) { this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Language")); } this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); if (!this.Messaging.EncounteredError) { var row = this.ParseHelper.CreateRow(section, sourceLineNumbers, "HelpFile", id); row.Set(1, name); row.Set(2, language); row.Set(3, fileId); row.Set(4, hxi); row.Set(5, hxq); row.Set(6, hxr); row.Set(7, samples); if (YesNoType.No == suppressCAs) { this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "CA_RegisterMicrosoftHelp.3643236F_FC70_11D3_A536_0090278A1BB8"); } } }
/// <summary> /// Parses an application identifer element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="componentId">Identifier of parent component.</param> /// <param name="advertise">The required advertise state (set depending upon the parent).</param> /// <param name="fileServer">Optional file identifier for CLSID when not advertised.</param> /// <param name="typeLibId">Optional TypeLib GUID for CLSID.</param> /// <param name="typeLibVersion">Optional TypeLib Version for CLSID Interfaces (if any).</param> private void ParseAppIdElement(XmlNode node, string componentId, YesNoType advertise, string fileServer, string typeLibId, string typeLibVersion) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string appId = null; string remoteServerName = null; string localService = null; string serviceParameters = null; string dllSurrogate = null; YesNoType activateAtStorage = YesNoType.NotSet; YesNoType runAsInteractiveUser = YesNoType.NotSet; string description = null; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Id": appId = this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; case "ActivateAtStorage": activateAtStorage = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Advertise": YesNoType appIdAdvertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); if ((YesNoType.No == advertise && YesNoType.Yes == appIdAdvertise) || (YesNoType.Yes == advertise && YesNoType.No == appIdAdvertise)) { this.core.OnMessage(WixErrors.AppIdIncompatibleAdvertiseState(sourceLineNumbers, node.Name, attrib.Name, appIdAdvertise.ToString(CultureInfo.InvariantCulture.NumberFormat), advertise.ToString(CultureInfo.InvariantCulture.NumberFormat))); } advertise = appIdAdvertise; break; case "Description": description = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "DllSurrogate": dllSurrogate = this.core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); break; case "LocalService": localService = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "RemoteServerName": remoteServerName = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "RunAsInteractiveUser": runAsInteractiveUser = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ServiceParameters": serviceParameters = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (null == appId) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id")); } // if the advertise state has not been set, default to non-advertised if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { switch (child.LocalName) { case "Class": this.ParseClassElement(child, componentId, advertise, fileServer, typeLibId, typeLibVersion, appId); break; default: this.core.UnexpectedElement(node, child); break; } } else { this.core.UnsupportedExtensionElement(node, child); } } } Debug.Assert((YesNoType.Yes == advertise) || (YesNoType.No == advertise) || (YesNoType.IllegalValue == advertise), "Unexpected YesNoType value encountered."); if (YesNoType.Yes == advertise) { if (null != description) { this.core.OnMessage(WixErrors.IllegalAttributeWhenAdvertised(sourceLineNumbers, node.Name, "Description")); } if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "AppId"); row[0] = appId; row[1] = remoteServerName; row[2] = localService; row[3] = serviceParameters; row[4] = dllSurrogate; if (YesNoType.Yes == activateAtStorage) { row[5] = 1; } if (YesNoType.Yes == runAsInteractiveUser) { row[6] = 1; } } } else if (YesNoType.No == advertise) { if (null != description) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), null, description, componentId); } else { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "+", null, componentId); } if (null != remoteServerName) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "RemoteServerName", remoteServerName, componentId); } if (null != localService) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "LocalService", localService, componentId); } if (null != serviceParameters) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "ServiceParameters", serviceParameters, componentId); } if (null != dllSurrogate) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "DllSurrogate", dllSurrogate, componentId); } if (YesNoType.Yes == activateAtStorage) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "ActivateAtStorage", "Y", componentId); } if (YesNoType.Yes == runAsInteractiveUser) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("AppID\\", appId), "RunAs", "Interactive User", componentId); } } }
private void ParseScriptElement(XmlNode node) { SourceLineNumberCollection sourceLineNumber = Preprocessor.GetSourceLineNumbers(node); string superElementId = null; string scriptData = null; var elevated = YesNoType.No; YesNoType ignoreErrors = YesNoType.No; foreach (XmlAttribute attribute in node.Attributes) { if (attribute.NamespaceURI.Length == 0 || attribute.NamespaceURI == _schema.TargetNamespace) { switch (attribute.LocalName) { case "Id": superElementId = Core.GetAttributeIdentifierValue(sourceLineNumber, attribute); break; case "Elevated": elevated = Core.GetAttributeYesNoValue(sourceLineNumber, attribute); break; case "IgnoreErrors": ignoreErrors = Core.GetAttributeYesNoValue(sourceLineNumber, attribute); break; default: Core.UnexpectedAttribute(sourceLineNumber, attribute); break; } } else { Core.UnsupportedExtensionAttribute(sourceLineNumber, attribute); } } if (node.HasChildNodes) { var cdata = node.ChildNodes[0] as XmlCDataSection; if (cdata != null) { // Need to encode, as column doesn't like having line feeds scriptData = Convert.ToBase64String(Encoding.Unicode.GetBytes(cdata.Data)); } } if (string.IsNullOrEmpty(superElementId)) { Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumber, node.Name, "Id")); } if (string.IsNullOrEmpty(scriptData)) { Core.OnMessage(WixErrors.ExpectedElement(sourceLineNumber, node.Name, "CDATA")); } if (!Core.EncounteredError) { Row superElementRow = Core.CreateRow(sourceLineNumber, "PowerShellScripts"); superElementRow[0] = superElementId; superElementRow[1] = scriptData; superElementRow[2] = elevated == YesNoType.Yes ? 1 : 0; superElementRow[3] = (ignoreErrors == YesNoType.Yes) ? 1 : 0; } Core.CreateWixSimpleReferenceRow(sourceLineNumber, "CustomAction", "PowerShellScriptsImmediate"); }
/// <summary> /// Parses a mime element. /// </summary> /// <param name="node">Element to parse.</param> /// <param name="extension">Identifier for parent extension.</param> /// <param name="componentId">Identifier for parent component.</param> /// <param name="parentAdvertised">Flag if the parent element is advertised.</param> /// <returns>Content type if this is the default for the MIME type.</returns> private string ParseMIMEElement(XmlNode node, string extension, string componentId, YesNoType parentAdvertised) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string classId = null; string contentType = null; YesNoType advertise = parentAdvertised; YesNoType returnContentType = YesNoType.NotSet; foreach (XmlAttribute attrib in node.Attributes) { if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) { switch (attrib.LocalName) { case "Advertise": advertise = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Class": classId = this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; case "ContentType": contentType = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Default": returnContentType = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); } } if (null == contentType) { this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "ContentType")); } // if the advertise state has not been set, default to non-advertised if (YesNoType.NotSet == advertise) { advertise = YesNoType.No; } foreach (XmlNode child in node.ChildNodes) { if (XmlNodeType.Element == child.NodeType) { if (child.NamespaceURI == this.schema.TargetNamespace) { this.core.UnexpectedElement(node, child); } else { this.core.UnsupportedExtensionElement(node, child); } } } if (YesNoType.Yes == advertise) { if (YesNoType.Yes != parentAdvertised) { this.core.OnMessage(WixErrors.AdvertiseStateMustMatch(sourceLineNumbers, advertise.ToString(CultureInfo.InvariantCulture.NumberFormat), parentAdvertised.ToString(CultureInfo.InvariantCulture.NumberFormat))); } if (!this.core.EncounteredError) { Row row = this.core.CreateRow(sourceLineNumbers, "MIME"); row[0] = contentType; row[1] = extension; row[2] = classId; } } else if (YesNoType.No == advertise) { if (YesNoType.Yes == returnContentType && YesNoType.Yes == parentAdvertised) { this.core.OnMessage(WixErrors.CannotDefaultMismatchedAdvertiseStates(sourceLineNumbers)); } this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("MIME\\Database\\Content Type\\", contentType), "Extension", String.Concat(".", extension), componentId); if (null != classId) { this.core.CreateRegistryRow(sourceLineNumbers, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("MIME\\Database\\Content Type\\", contentType), "CLSID", classId, componentId); } } return YesNoType.Yes == returnContentType ? contentType : null; }
/// <summary> /// Initializes package state from the MSI contents. /// </summary> private void ResolveMsiPackage(BinderFileManager fileManager, Dictionary<string, PayloadInfoRow> allPayloads, Dictionary<string, ContainerInfo> containers, YesNoType suppressLooseFilePayloadGeneration, YesNoType enableFeatureSelection, YesNoType forcePerMachine, Output bundle) { string sourcePath = this.PackagePayload.FullFileName; bool longNamesInImage = false; bool compressed = false; try { // Read data out of the msi database... using (Microsoft.Deployment.WindowsInstaller.SummaryInfo sumInfo = new Microsoft.Deployment.WindowsInstaller.SummaryInfo(sourcePath, false)) { // 1 is the Word Count summary information stream bit that means // the MSI uses short file names when set. We care about long file // names so check when the bit is not set. longNamesInImage = 0 == (sumInfo.WordCount & 1); // 2 is the Word Count summary information stream bit that means // files are compressed in the MSI by default when the bit is set. compressed = 2 == (sumInfo.WordCount & 2); // 8 is the Word Count summary information stream bit that means // "Elevated privileges are not required to install this package." // in MSI 4.5 and below, if this bit is 0, elevation is required. this.PerMachine = (0 == (sumInfo.WordCount & 8)) ? YesNoDefaultType.Yes : YesNoDefaultType.No; } using (Microsoft.Deployment.WindowsInstaller.Database db = new Microsoft.Deployment.WindowsInstaller.Database(sourcePath)) { this.ProductCode = ChainPackageInfo.GetProperty(db, "ProductCode"); this.Language = ChainPackageInfo.GetProperty(db, "ProductLanguage"); this.Version = ChainPackageInfo.GetProperty(db, "ProductVersion"); if (!Common.IsValidModuleOrBundleVersion(this.Version)) { // not a proper .NET version (i.e., five fields); can we get a valid version number up to four fields? string version = null; string[] versionParts = this.Version.Split('.'); int count = versionParts.Length; if (0 < count) { version = versionParts[0]; for (int i = 1; i < 4 && i < count; ++i) { version = String.Concat(version, ".", versionParts[i]); } } if (!String.IsNullOrEmpty(version) && Common.IsValidModuleOrBundleVersion(version)) { this.core.OnMessage(WixWarnings.VersionTruncated(this.PackagePayload.SourceLineNumbers, this.Version, sourcePath, version)); this.Version = version; } else { this.core.OnMessage(WixErrors.InvalidProductVersion(this.PackagePayload.SourceLineNumbers, this.Version, sourcePath)); } } if (String.IsNullOrEmpty(this.CacheId)) { this.CacheId = String.Format("{0}v{1}", this.ProductCode, this.Version); } if (String.IsNullOrEmpty(this.DisplayName)) { this.DisplayName = ChainPackageInfo.GetProperty(db, "ProductName"); } this.Manufacturer = ChainPackageInfo.GetProperty(db, "Manufacturer"); this.VerifyMsiProperties(); if (YesNoType.Yes == forcePerMachine) { if (YesNoDefaultType.No == this.PerMachine) { this.core.OnMessage(WixWarnings.PerUserButForcingPerMachine(this.PackagePayload.SourceLineNumbers, sourcePath)); this.PerMachine = YesNoDefaultType.Yes; // ensure that we think the MSI is per-machine. } this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "ALLUSERS", "1")); // force ALLUSERS=1 via the MSI command-line. } else if (ChainPackageInfo.HasProperty(db, "ALLUSERS")) { string allusers = ChainPackageInfo.GetProperty(db, "ALLUSERS"); if (allusers.Equals("1", StringComparison.Ordinal)) { if (YesNoDefaultType.No == this.PerMachine) { this.core.OnMessage(WixErrors.PerUserButAllUsersEquals1(this.PackagePayload.SourceLineNumbers, sourcePath)); } } else if (allusers.Equals("2", StringComparison.Ordinal)) { this.core.OnMessage(WixWarnings.DiscouragedAllUsersValue(this.PackagePayload.SourceLineNumbers, sourcePath, (YesNoDefaultType.Yes == this.PerMachine) ? "machine" : "user")); } else { this.core.OnMessage(WixErrors.UnsupportedAllUsersValue(this.PackagePayload.SourceLineNumbers, sourcePath, allusers)); } } else if (YesNoDefaultType.Yes == this.PerMachine) // not forced per-machine and no ALLUSERS property, flip back to per-user { this.core.OnMessage(WixWarnings.ImplicitlyPerUser(this.PackagePayload.SourceLineNumbers, sourcePath)); this.PerMachine = YesNoDefaultType.No; } if (String.IsNullOrEmpty(this.Description) && ChainPackageInfo.HasProperty(db, "ARPCOMMENTS")) { this.Description = ChainPackageInfo.GetProperty(db, "ARPCOMMENTS"); } // Ensure the MSI package is appropriately marked visible or not. bool alreadyVisible = !ChainPackageInfo.HasProperty(db, "ARPSYSTEMCOMPONENT"); if (alreadyVisible != this.Visible) // if not already set to the correct visibility. { // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. bool sysComponentSet = false; foreach (MsiPropertyInfo propertyInfo in this.MsiProperties) { if ("ARPSYSTEMCOMPONENT".Equals(propertyInfo.Name, StringComparison.Ordinal)) { sysComponentSet = true; break; } } if (!sysComponentSet) { this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "ARPSYSTEMCOMPONENT", this.Visible ? "" : "1")); } } // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. if (!ChainPackageInfo.HasProperty(db, "MSIFASTINSTALL")) { bool fastInstallSet = false; foreach (MsiPropertyInfo propertyInfo in this.MsiProperties) { if ("MSIFASTINSTALL".Equals(propertyInfo.Name, StringComparison.Ordinal)) { fastInstallSet = true; break; } } if (!fastInstallSet) { this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "MSIFASTINSTALL", "7")); } } this.UpgradeCode = ChainPackageInfo.GetProperty(db, "UpgradeCode"); // Represent the Upgrade table as related packages. if (db.Tables.Contains("Upgrade") && !String.IsNullOrEmpty(this.UpgradeCode)) { using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes` FROM `Upgrade`")) { view.Execute(); while (true) { using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch()) { if (null == record) { break; } RelatedPackage related = new RelatedPackage(); related.Id = record.GetString(1); related.MinVersion = record.GetString(2); related.MaxVersion = record.GetString(3); string languages = record.GetString(4); if (!String.IsNullOrEmpty(languages)) { string[] splitLanguages = languages.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); related.Languages.AddRange(splitLanguages); } int attributes = record.GetInteger(5); // when an Upgrade row has an upgrade code different than this package's upgrade code, don't count it as a possible downgrade to this package related.OnlyDetect = ((attributes & MsiInterop.MsidbUpgradeAttributesOnlyDetect) == MsiInterop.MsidbUpgradeAttributesOnlyDetect) && this.UpgradeCode.Equals(related.Id, StringComparison.OrdinalIgnoreCase); related.MinInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMinInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMinInclusive; related.MaxInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive; related.LangInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesLanguagesExclusive) == 0; this.RelatedPackages.Add(related); } } } } // If feature selection is enabled, represent the Feature table in the manifest. if (YesNoType.Yes == enableFeatureSelection && db.Tables.Contains("Feature")) { using (Microsoft.Deployment.WindowsInstaller.View featureView = db.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = ?"), componentView = db.OpenView("SELECT `FileSize` FROM `File` WHERE `Component_` = ?")) { using (Microsoft.Deployment.WindowsInstaller.Record featureRecord = new Microsoft.Deployment.WindowsInstaller.Record(1), componentRecord = new Microsoft.Deployment.WindowsInstaller.Record(1)) { using (Microsoft.Deployment.WindowsInstaller.View allFeaturesView = db.OpenView("SELECT * FROM `Feature`")) { allFeaturesView.Execute(); while (true) { using (Microsoft.Deployment.WindowsInstaller.Record allFeaturesResultRecord = allFeaturesView.Fetch()) { if (null == allFeaturesResultRecord) { break; } MsiFeature feature = new MsiFeature(); string featureName = allFeaturesResultRecord.GetString(1); feature.Name = featureName; feature.Size = 0; feature.Parent = allFeaturesResultRecord.GetString(2); feature.Title = allFeaturesResultRecord.GetString(3); feature.Description = allFeaturesResultRecord.GetString(4); feature.Display = allFeaturesResultRecord.GetInteger(5); feature.Level = allFeaturesResultRecord.GetInteger(6); feature.Directory = allFeaturesResultRecord.GetString(7); feature.Attributes = allFeaturesResultRecord.GetInteger(8); this.MsiFeatures.Add(feature); // Determine Feature Size featureRecord.SetString(1, featureName); featureView.Execute(featureRecord); // Loop over all the components while (true) { using (Microsoft.Deployment.WindowsInstaller.Record componentResultRecord = featureView.Fetch()) { if (null == componentResultRecord) { break; } string component = componentResultRecord.GetString(1); componentRecord.SetString(1, component); componentView.Execute(componentRecord); // Loop over all the files while (true) { using (Microsoft.Deployment.WindowsInstaller.Record fileResultRecord = componentView.Fetch()) { if (null == fileResultRecord) { break; } string fileSize = fileResultRecord.GetString(1); feature.Size += Convert.ToInt32(fileSize, CultureInfo.InvariantCulture.NumberFormat); } } } } } } } } } } // Add all external cabinets as package payloads. if (db.Tables.Contains("Media")) { foreach (string cabinet in db.ExecuteStringQuery("SELECT `Cabinet` FROM `Media`")) { if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal)) { // If we didn't find the Payload as an existing child of the package, we need to // add it. We expect the file to exist on-disk in the same relative location as // the MSI expects to find it... string cabinetName = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), cabinet); if (!this.IsExistingPayload(cabinetName)) { string generatedId = Common.GenerateIdentifier("cab", true, this.PackagePayload.Id, cabinet); string payloadSourceFile = fileManager.ResolveRelatedFile(this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.PackagePayload.SourceLineNumbers, BindStage.Normal); PayloadInfoRow payloadNew = PayloadInfoRow.Create(this.SourceLineNumbers, bundle, generatedId, cabinetName, payloadSourceFile, true, this.PackagePayload.SuppressSignatureValidation, null, this.PackagePayload.Container, this.PackagePayload.Packaging); payloadNew.ParentPackagePayload = this.PackagePayload.Id; if (!String.IsNullOrEmpty(payloadNew.Container)) { containers[payloadNew.Container].Payloads.Add(payloadNew); } this.Payloads.Add(payloadNew); allPayloads.Add(payloadNew.Id, payloadNew); this.Size += payloadNew.FileSize; // add the newly added payload to the package size. } } } } // Add all external files as package payloads and calculate the total install size as the rollup of // File table's sizes. this.InstallSize = 0; if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File")) { Hashtable directories = new Hashtable(); // Load up the directory hash table so we will be able to resolve source paths // for files in the MSI database. using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) { view.Execute(); while (true) { using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch()) { if (null == record) { break; } string sourceName = Installer.GetName(record.GetString(3), true, longNamesInImage); directories.Add(record.GetString(1), new ResolvedDirectory(record.GetString(2), sourceName)); } } } // Resolve the source paths to external files and add each file size to the total // install size of the package. using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) { view.Execute(); while (true) { using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch()) { if (null == record) { break; } // Skip adding the loose files as payloads if it was suppressed. if (suppressLooseFilePayloadGeneration != YesNoType.Yes) { // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not // explicitly marked compressed then this is an external file. if (MsiInterop.MsidbFileAttributesNoncompressed == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesNoncompressed) || (!compressed && 0 == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesCompressed))) { string generatedId = Common.GenerateIdentifier("f", true, this.PackagePayload.Id, record.GetString(2)); string fileSourcePath = Binder.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); string payloadSourceFile = fileManager.ResolveRelatedFile(this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.PackagePayload.SourceLineNumbers, BindStage.Normal); string name = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), fileSourcePath); if (!this.IsExistingPayload(name)) { PayloadInfoRow payloadNew = PayloadInfoRow.Create(this.SourceLineNumbers, bundle, generatedId, name, payloadSourceFile, true, this.PackagePayload.SuppressSignatureValidation, null, this.PackagePayload.Container, this.PackagePayload.Packaging); payloadNew.ParentPackagePayload = this.PackagePayload.Id; if (!String.IsNullOrEmpty(payloadNew.Container)) { containers[payloadNew.Container].Payloads.Add(payloadNew); } this.Payloads.Add(payloadNew); allPayloads.Add(payloadNew.Id, payloadNew); this.Size += payloadNew.FileSize; // add the newly added payload to the package size. } } } this.InstallSize += record.GetInteger(5); } } } } // Import any dependency providers from the MSI. if (db.Tables.Contains("WixDependencyProvider")) { // Use the old schema (v1) if the Version column does not exist. bool hasVersion = db.Tables["WixDependencyProvider"].Columns.Contains("Version"); string query = "SELECT `ProviderKey`, `Version`, `DisplayName`, `Attributes` FROM `WixDependencyProvider`"; if (!hasVersion) { query = "SELECT `ProviderKey`, `Attributes` FROM `WixDependencyProvider`"; } using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView(query)) { view.Execute(); while (true) { using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch()) { if (null == record) { break; } // Import the provider key and attributes. ProvidesDependency dependency = null; string providerKey = record.GetString(1); if (hasVersion) { string version = record.GetString(2) ?? this.Version; string displayName = record.GetString(3) ?? this.DisplayName; int attributes = record.GetInteger(4); dependency = new ProvidesDependency(providerKey, version, displayName, attributes); } else { int attributes = record.GetInteger(2); dependency = new ProvidesDependency(providerKey, this.Version, this.DisplayName, attributes); } dependency.Imported = true; this.Provides.Add(dependency); } } } } } } catch (Microsoft.Deployment.WindowsInstaller.InstallerException e) { this.core.OnMessage(WixErrors.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message)); } }
/// <summary> /// Parses a WixStandardBootstrapperApplication element for Bundles. /// </summary> /// <param name="node">The element to parse.</param> private void ParseWixStandardBootstrapperApplicationElement(XElement node) { SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string launchTarget = null; string licenseFile = null; string licenseUrl = null; string logoFile = null; string logoSideFile = null; string themeFile = null; string localizationFile = null; YesNoType suppressOptionsUI = YesNoType.NotSet; YesNoType suppressDowngradeFailure = YesNoType.NotSet; YesNoType suppressRepair = YesNoType.NotSet; YesNoType showVersion = YesNoType.NotSet; foreach (XAttribute attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "LaunchTarget": launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LicenseFile": licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LicenseUrl": licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, true); break; case "LogoFile": logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LogoSideFile": logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "ThemeFile": themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "LocalizationFile": localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); break; case "SuppressOptionsUI": suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressDowngradeFailure": suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressRepair": suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ShowVersion": showVersion = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); break; } } else { this.Core.ParseExtensionAttribute(node, attrib); } } this.Core.ParseForExtensionElements(node); if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "LicenseFile", "LicenseUrl", true)); } if (!this.Core.EncounteredError) { if (!String.IsNullOrEmpty(launchTarget)) { this.Core.CreateVariableRow(sourceLineNumbers, "LaunchTarget", launchTarget, "string", false, false); } if (!String.IsNullOrEmpty(licenseFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLicenseRtf", licenseFile, false); } if (null != licenseUrl) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLicenseUrl", licenseUrl, false); } if (!String.IsNullOrEmpty(logoFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLogo", logoFile, false); } if (!String.IsNullOrEmpty(logoSideFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaLogoSide", logoSideFile, false); } if (!String.IsNullOrEmpty(themeFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaThemeXml", themeFile, false); } if (!String.IsNullOrEmpty(localizationFile)) { this.Core.CreateWixVariableRow(sourceLineNumbers, "WixStdbaThemeWxl", localizationFile, false); } if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair || YesNoType.Yes == showVersion) { Row row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOptions"); if (YesNoType.Yes == suppressOptionsUI) { row[0] = 1; } if (YesNoType.Yes == suppressDowngradeFailure) { row[1] = 1; } if (YesNoType.Yes == suppressRepair) { row[2] = 1; } if (YesNoType.Yes == showVersion) { row[3] = 1; } } } }
/// <summary> /// Parses a WixStandardBootstrapperApplication element for Bundles. /// </summary> /// <param name="node">The element to parse.</param> private void ParseWixStandardBootstrapperApplicationElement(XElement node) { SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string launchTarget = null; string launchTargetElevatedId = null; string launchArguments = null; YesNoType launchHidden = YesNoType.NotSet; string launchWorkingDir = null; string licenseFile = null; string licenseUrl = null; string logoFile = null; string logoSideFile = null; string themeFile = null; string localizationFile = null; YesNoType suppressOptionsUI = YesNoType.NotSet; YesNoType suppressDowngradeFailure = YesNoType.NotSet; YesNoType suppressRepair = YesNoType.NotSet; YesNoType showVersion = YesNoType.NotSet; YesNoType supportCacheOnly = YesNoType.NotSet; foreach (XAttribute attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "LaunchTarget": launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LaunchTargetElevatedId": launchTargetElevatedId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "LaunchArguments": launchArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LaunchHidden": launchHidden = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "LaunchWorkingFolder": launchWorkingDir = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LicenseFile": licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LicenseUrl": licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); break; case "LogoFile": logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LogoSideFile": logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "ThemeFile": themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "LocalizationFile": localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "SuppressOptionsUI": suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressDowngradeFailure": suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressRepair": suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ShowVersion": showVersion = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SupportCacheOnly": supportCacheOnly = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(node, attrib); break; } } else { this.Core.ParseExtensionAttribute(node, attrib); } } this.Core.ParseForExtensionElements(node); if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl) { this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "LicenseFile", "LicenseUrl", true)); } if (!this.Core.EncounteredError) { if (!String.IsNullOrEmpty(launchTarget)) { WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); row.Id = "LaunchTarget"; row.Value = launchTarget; row.Type = "string"; } if (!String.IsNullOrEmpty(launchTargetElevatedId)) { WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); row.Id = "LaunchTargetElevatedId"; row.Value = launchTargetElevatedId; row.Type = "string"; } if (!String.IsNullOrEmpty(launchArguments)) { WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); row.Id = "LaunchArguments"; row.Value = launchArguments; row.Type = "string"; } if (YesNoType.Yes == launchHidden) { WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); row.Id = "LaunchHidden"; row.Value = "yes"; row.Type = "string"; } if (!String.IsNullOrEmpty(launchWorkingDir)) { WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "Variable"); row.Id = "LaunchWorkingFolder"; row.Value = launchWorkingDir; row.Type = "string"; } if (!String.IsNullOrEmpty(licenseFile)) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaLicenseRtf"; wixVariableRow.Value = licenseFile; } if (null != licenseUrl) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaLicenseUrl"; wixVariableRow.Value = licenseUrl; } if (!String.IsNullOrEmpty(logoFile)) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaLogo"; wixVariableRow.Value = logoFile; } if (!String.IsNullOrEmpty(logoSideFile)) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaLogoSide"; wixVariableRow.Value = logoSideFile; } if (!String.IsNullOrEmpty(themeFile)) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaThemeXml"; wixVariableRow.Value = themeFile; } if (!String.IsNullOrEmpty(localizationFile)) { WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); wixVariableRow.Id = "WixStdbaThemeWxl"; wixVariableRow.Value = localizationFile; } if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair || YesNoType.Yes == showVersion || YesNoType.Yes == supportCacheOnly) { Row row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOptions"); if (YesNoType.Yes == suppressOptionsUI) { row[0] = 1; } if (YesNoType.Yes == suppressDowngradeFailure) { row[1] = 1; } if (YesNoType.Yes == suppressRepair) { row[2] = 1; } if (YesNoType.Yes == showVersion) { row[3] = 1; } if (YesNoType.Yes == supportCacheOnly) { row[4] = 1; } } } }