public IVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool errorOnUnknown) { var start = 0; var defaulted = true; var delayed = false; var updated = false; while (Common.TryParseWixVariable(value, start, out var parsed)) { var variableNamespace = parsed.Namespace; var variableId = parsed.Name; var variableDefaultValue = parsed.DefaultValue; // check for an escape sequence of !! indicating the match is not a variable expression if (0 < parsed.Index && '!' == value[parsed.Index - 1]) { var sb = new StringBuilder(value); sb.Remove(parsed.Index - 1, 1); value = sb.ToString(); updated = true; start = parsed.Index + parsed.Length - 1; continue; } string resolvedValue = null; if ("loc" == variableNamespace) { // localization variables do not support inline default values if (variableDefaultValue != null) { this.Messaging.Write(ErrorMessages.IllegalInlineLocVariable(sourceLineNumbers, variableId, variableDefaultValue)); continue; } if (this.locVariables.TryGetValue(variableId, out var bindVariable)) { resolvedValue = bindVariable.Value; } } else if ("wix" == variableNamespace) { if (this.wixVariables.TryGetValue(variableId, out var bindVariable)) { resolvedValue = bindVariable.Value ?? String.Empty; defaulted = false; } else if (null != variableDefaultValue) // default the resolved value to the inline value if one was specified { resolvedValue = variableDefaultValue; } } if ("bind" == variableNamespace) { // Can't resolve these yet, but keep track of where we find them so they can be resolved later with less effort. delayed = true; start = parsed.Index + parsed.Length - 1; } else { // insert the resolved value if it was found or display an error if (null != resolvedValue) { if (parsed.Index == 0 && parsed.Length == value.Length) { value = resolvedValue; } else { var sb = new StringBuilder(value); sb.Remove(parsed.Index, parsed.Length); sb.Insert(parsed.Index, resolvedValue); value = sb.ToString(); } updated = true; start = parsed.Index; } else { if ("loc" == variableNamespace && errorOnUnknown) // unresolved loc variable { this.Messaging.Write(ErrorMessages.LocalizationVariableUnknown(sourceLineNumbers, variableId)); } else if ("wix" == variableNamespace && errorOnUnknown) // unresolved wix variable { this.Messaging.Write(ErrorMessages.WixVariableUnknown(sourceLineNumbers, variableId)); } start = parsed.Index + parsed.Length; } } } return(new VariableResolution { DelayedResolve = delayed, IsDefault = defaulted, UpdatedValue = updated, Value = value, }); }