Example #1
0
        public void Execute()
        {
            var delayedFields = this.SupportDelayedResolution ? new List <DelayedField>() : null;

            var fileResolver = new FileResolver(this.BindPaths, this.Extensions);

            // Build the column lookup only when needed.
            Dictionary <string, WixCustomTableColumnSymbol> customColumnsById = null;

            foreach (var sections in this.Intermediate.Sections)
            {
                foreach (var symbol in sections.Symbols)
                {
                    foreach (var field in symbol.Fields)
                    {
                        if (field.IsNull())
                        {
                            continue;
                        }

                        var fieldType = field.Type;

                        // Custom table cells require an extra look up to the column definition as the
                        // cell's data type is always a string (because strings can store anything) but
                        // the column definition may be more specific.
                        if (symbol.Definition.Type == SymbolDefinitionType.WixCustomTableCell)
                        {
                            // We only care about the Data in a CustomTable cell.
                            if (field.Name != nameof(WixCustomTableCellSymbolFields.Data))
                            {
                                continue;
                            }

                            if (customColumnsById == null)
                            {
                                customColumnsById = this.Intermediate.Sections.SelectMany(s => s.Symbols.OfType <WixCustomTableColumnSymbol>()).ToDictionary(t => t.Id.Id);
                            }

                            if (customColumnsById.TryGetValue(symbol.Fields[(int)WixCustomTableCellSymbolFields.TableRef].AsString() + "/" + symbol.Fields[(int)WixCustomTableCellSymbolFields.ColumnRef].AsString(), out var customColumn))
                            {
                                fieldType = customColumn.Type;
                            }
                        }

                        // Check to make sure we're in a scenario where we can handle variable resolution.
                        if (null != delayedFields)
                        {
                            // resolve localization and wix variables
                            if (fieldType == IntermediateFieldType.String)
                            {
                                var original = field.AsString();
                                if (!String.IsNullOrEmpty(original))
                                {
                                    var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, original, !this.AllowUnresolvedVariables);
                                    if (resolution.UpdatedValue)
                                    {
                                        field.Set(resolution.Value);
                                    }

                                    if (resolution.DelayedResolve)
                                    {
                                        delayedFields.Add(new DelayedField(symbol, field));
                                    }
                                }
                            }
                        }

                        // Move to next symbol if we've hit an error resolving variables.
                        if (this.Messaging.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                        {
                            continue;
                        }

                        // Resolve file paths
                        if (fieldType == IntermediateFieldType.Path)
                        {
                            this.ResolvePathField(fileResolver, symbol, field);

#if TODO_PATCHING
                            if (null != objectField.PreviousData)
                            {
                                objectField.PreviousData = this.BindVariableResolver.ResolveVariables(symbol.SourceLineNumbers, objectField.PreviousData, false, out isDefault);

                                if (!Messaging.Instance.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                                {
                                    // file is compressed in a cabinet (and not modified above)
                                    if (objectField.PreviousEmbeddedFileIndex.HasValue && isDefault)
                                    {
                                        // when loading transforms from disk, PreviousBaseUri may not have been set
                                        if (null == objectField.PreviousBaseUri)
                                        {
                                            objectField.PreviousBaseUri = objectField.BaseUri;
                                        }

                                        string extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.PreviousBaseUri, objectField.PreviousEmbeddedFileIndex.Value, this.IntermediateFolder);

                                        // set the path to the file once its extracted from the cabinet
                                        objectField.PreviousData = extractPath;
                                    }
                                    else if (null != objectField.PreviousData) // non-compressed file (or localized value)
                                    {
                                        try
                                        {
                                            if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated)
                                            {
                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Normal);
                                            }
                                            else
                                            {
                                                if (fileResolver.RebaseTarget)
                                                {
                                                    // if -bt is used, it come here
                                                    // Try to use the original unresolved source from either target build or update build
                                                    // If both target and updated are of old wixpdb, it behaves the same as today, no re-base logic here
                                                    // If target is old version and updated is new version, it uses unresolved path from updated build
                                                    // If both target and updated are of new versions, it uses unresolved path from target build
                                                    if (null != objectField.UnresolvedPreviousData || null != objectField.UnresolvedData)
                                                    {
                                                        objectField.PreviousData = objectField.UnresolvedPreviousData ?? objectField.UnresolvedData;
                                                    }
                                                }

                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Target);
                                            }
                                        }
                                        catch (WixFileNotFoundException)
                                        {
                                            // display the error with source line information
                                            Messaging.Instance.Write(WixErrors.FileNotFound(symbol.SourceLineNumbers, (string)objectField.PreviousData));
                                        }
                                    }
                                }
                            }
#endif
                        }
                    }
                }
            }

            this.DelayedFields = delayedFields;
        }
Example #2
0
        public void Execute()
        {
            var delayedFields = this.SupportDelayedResolution ? new List <DelayedField>() : null;

            var fileResolver = new FileResolver(this.BindPaths, this.Extensions);

            // Build the column lookup only when needed.
            Dictionary <string, WixCustomTableColumnSymbol> customColumnsById = null;

            foreach (var sections in this.Intermediate.Sections)
            {
                foreach (var symbol in sections.Symbols)
                {
                    foreach (var field in symbol.Fields)
                    {
                        if (field.IsNull())
                        {
                            continue;
                        }

                        var fieldType = field.Type;

                        // Custom table cells require an extra look up to the column definition as the
                        // cell's data type is always a string (because strings can store anything) but
                        // the column definition may be more specific.
                        if (symbol.Definition.Type == SymbolDefinitionType.WixCustomTableCell)
                        {
                            // We only care about the Data in a CustomTable cell.
                            if (field.Name != nameof(WixCustomTableCellSymbolFields.Data))
                            {
                                continue;
                            }

                            if (customColumnsById == null)
                            {
                                customColumnsById = this.Intermediate.Sections.SelectMany(s => s.Symbols.OfType <WixCustomTableColumnSymbol>()).ToDictionary(t => t.Id.Id);
                            }

                            if (customColumnsById.TryGetValue(symbol.Fields[(int)WixCustomTableCellSymbolFields.TableRef].AsString() + "/" + symbol.Fields[(int)WixCustomTableCellSymbolFields.ColumnRef].AsString(), out var customColumn))
                            {
                                fieldType = customColumn.Type;
                            }
                        }

                        var isDefault = true;

                        // Check to make sure we're in a scenario where we can handle variable resolution.
                        if (null != delayedFields)
                        {
                            // resolve localization and wix variables
                            if (fieldType == IntermediateFieldType.String || fieldType == IntermediateFieldType.Path)
                            {
                                var original = field.AsString();
                                if (!String.IsNullOrEmpty(original))
                                {
                                    var resolution = fieldType == IntermediateFieldType.Path
                                        ? this.ResolvePathField(field, symbol.SourceLineNumbers)
                                        : this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, original, !this.AllowUnresolvedVariables);

                                    if (resolution.UpdatedValue)
                                    {
                                        field.Set(resolution.Value);
                                    }

                                    if (resolution.DelayedResolve)
                                    {
                                        delayedFields.Add(new DelayedField(symbol, field));
                                    }

                                    isDefault = resolution.IsDefault;
                                }
                            }
                        }

                        // Move to next symbol if we've hit an error resolving variables.
                        if (this.Messaging.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                        {
                            continue;
                        }

                        // Resolve file paths
                        if (fieldType == IntermediateFieldType.Path)
                        {
                            var pathValue = field.AsPath();

#if TODO_PATCHING
                            // Skip file resolution if the file is to be deleted.
                            if (RowOperation.Delete == symbol.Operation)
                            {
                                continue;
                            }
#endif

                            // File is embedded and path to it was not modified above.
                            if (isDefault && pathValue.Embed)
                            {
                                var extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileToExtract(pathValue.BaseUri, pathValue.Path, this.IntermediateFolder);

                                // Set the path to the embedded file once where it will be extracted.
                                field.Set(extractPath);
                            }
                            else if (null != pathValue.Path) // non-compressed file (or localized value)
                            {
                                try
                                {
                                    if (!this.BuildingPatch) // Normal binding for non-Patch scenario such as link (light.exe)
                                    {
#if TODO_PATCHING
                                        // keep a copy of the un-resolved data for future replay. This will be saved into wixpdb file
                                        if (null == objectField.UnresolvedData)
                                        {
                                            objectField.UnresolvedData = (string)objectField.Data;
                                        }
#endif

                                        // resolve the path to the file
                                        var value = fileResolver.ResolveFile(pathValue.Path, symbol.Definition, symbol.SourceLineNumbers, BindStage.Normal);
                                        field.Set(value);
                                    }
                                    else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic)
                                    {
                                        // resolve the path to the file
                                        var value = fileResolver.ResolveFile(pathValue.Path, symbol.Definition, symbol.SourceLineNumbers, BindStage.Normal);
                                        field.Set(value);
                                    }
#if TODO_PATCHING
                                    else // Re-base binding path scenario caused by pyro.exe -bt -bu
                                    {
                                        // by default, use the resolved Data for file lookup
                                        string filePathToResolve = (string)objectField.Data;

                                        // if -bu is used in pyro command, this condition holds true and the tool
                                        // will use pre-resolved source for new wixpdb file
                                        if (fileResolver.RebaseUpdated)
                                        {
                                            // try to use the unResolved Source if it exists.
                                            // New version of wixpdb file keeps a copy of pre-resolved Source. i.e. !(bindpath.test)\foo.dll
                                            // Old version of winpdb file does not contain this attribute and the value is null.
                                            if (null != objectField.UnresolvedData)
                                            {
                                                filePathToResolve = objectField.UnresolvedData;
                                            }
                                        }

                                        objectField.Data = fileResolver.ResolveFile(filePathToResolve, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Updated);
                                    }
#endif
                                }
                                catch (WixException e)
                                {
                                    this.Messaging.Write(e.Error);
                                }
                            }

#if TODO_PATCHING
                            if (null != objectField.PreviousData)
                            {
                                objectField.PreviousData = this.BindVariableResolver.ResolveVariables(symbol.SourceLineNumbers, objectField.PreviousData, false, out isDefault);

                                if (!Messaging.Instance.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                                {
                                    // file is compressed in a cabinet (and not modified above)
                                    if (objectField.PreviousEmbeddedFileIndex.HasValue && isDefault)
                                    {
                                        // when loading transforms from disk, PreviousBaseUri may not have been set
                                        if (null == objectField.PreviousBaseUri)
                                        {
                                            objectField.PreviousBaseUri = objectField.BaseUri;
                                        }

                                        string extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.PreviousBaseUri, objectField.PreviousEmbeddedFileIndex.Value, this.IntermediateFolder);

                                        // set the path to the file once its extracted from the cabinet
                                        objectField.PreviousData = extractPath;
                                    }
                                    else if (null != objectField.PreviousData) // non-compressed file (or localized value)
                                    {
                                        try
                                        {
                                            if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated)
                                            {
                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Normal);
                                            }
                                            else
                                            {
                                                if (fileResolver.RebaseTarget)
                                                {
                                                    // if -bt is used, it come here
                                                    // Try to use the original unresolved source from either target build or update build
                                                    // If both target and updated are of old wixpdb, it behaves the same as today, no re-base logic here
                                                    // If target is old version and updated is new version, it uses unresolved path from updated build
                                                    // If both target and updated are of new versions, it uses unresolved path from target build
                                                    if (null != objectField.UnresolvedPreviousData || null != objectField.UnresolvedData)
                                                    {
                                                        objectField.PreviousData = objectField.UnresolvedPreviousData ?? objectField.UnresolvedData;
                                                    }
                                                }

                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Target);
                                            }
                                        }
                                        catch (WixFileNotFoundException)
                                        {
                                            // display the error with source line information
                                            Messaging.Instance.Write(WixErrors.FileNotFound(symbol.SourceLineNumbers, (string)objectField.PreviousData));
                                        }
                                    }
                                }
                            }
#endif
                        }
                    }
                }
            }

            this.DelayedFields = delayedFields;
        }
Example #3
0
        private void ResolvePathField(FileResolver fileResolver, IntermediateSymbol symbol, IntermediateField field)
        {
            var fieldValue        = field.AsPath();
            var originalFieldPath = fieldValue.Path;

#if TODO_PATCHING
            // Skip file resolution if the file is to be deleted.
            if (RowOperation.Delete == symbol.Operation)
            {
                continue;
            }
#endif

            // If the file is embedded and if the previous value has a bind variable in the path
            // which gets modified by resolving the previous value again then switch to that newly
            // resolved path instead of using the embedded file.
            if (fieldValue.Embed && field.PreviousValue != null)
            {
                var resolution = this.VariableResolver.ResolveVariables(symbol.SourceLineNumbers, field.PreviousValue.AsString(), errorOnUnknown: false);

                if (resolution.UpdatedValue && !resolution.IsDefault)
                {
                    fieldValue = new IntermediateFieldPathValue {
                        Path = resolution.Value
                    };
                }
            }

            // If we're still using the embedded file.
            if (fieldValue.Embed)
            {
                // Set the path to the embedded file once where it will be extracted.
                var extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileToExtract(fieldValue.BaseUri, fieldValue.Path, this.IntermediateFolder);

                field.Set(extractPath);
            }
            else if (fieldValue.Path != null)
            {
                try
                {
                    var resolvedPath = fieldValue.Path;

                    if (!this.BuildingPatch) // Normal binding for non-Patch scenario such as link (light.exe)
                    {
#if TODO_PATCHING
                        // keep a copy of the un-resolved data for future replay. This will be saved into wixpdb file
                        if (null == objectField.UnresolvedData)
                        {
                            objectField.UnresolvedData = (string)objectField.Data;
                        }
#endif
                        resolvedPath = fileResolver.ResolveFile(fieldValue.Path, symbol.Definition, symbol.SourceLineNumbers, BindStage.Normal);
                    }
                    else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic)
                    {
                        resolvedPath = fileResolver.ResolveFile(fieldValue.Path, symbol.Definition, symbol.SourceLineNumbers, BindStage.Normal);
                    }
#if TODO_PATCHING
                    else // Re-base binding path scenario caused by pyro.exe -bt -bu
                    {
                        // by default, use the resolved Data for file lookup
                        string filePathToResolve = (string)objectField.Data;

                        // if -bu is used in pyro command, this condition holds true and the tool
                        // will use pre-resolved source for new wixpdb file
                        if (fileResolver.RebaseUpdated)
                        {
                            // try to use the unResolved Source if it exists.
                            // New version of wixpdb file keeps a copy of pre-resolved Source. i.e. !(bindpath.test)\foo.dll
                            // Old version of winpdb file does not contain this attribute and the value is null.
                            if (null != objectField.UnresolvedData)
                            {
                                filePathToResolve = objectField.UnresolvedData;
                            }
                        }

                        objectField.Data = fileResolver.ResolveFile(filePathToResolve, symbol.Definition.Name, symbol.SourceLineNumbers, BindStage.Updated);
                    }
#endif

                    if (!String.Equals(originalFieldPath, resolvedPath, StringComparison.OrdinalIgnoreCase))
                    {
                        field.Set(resolvedPath);
                    }
                }
                catch (WixException e)
                {
                    this.Messaging.Write(e.Error);
                }
            }
        }
Example #4
0
        public void Execute()
        {
            List <DelayedField> delayedFields = this.SupportDelayedResolution ? new List <DelayedField>() : null;

            var fileResolver = new FileResolver(this.BindPaths, this.Extensions);

            foreach (var sections in this.Intermediate.Sections)
            {
                foreach (var row in sections.Tuples)
                {
                    foreach (var field in row.Fields)
                    {
                        if (field == null)
                        {
                            continue;
                        }

                        var isDefault = true;

                        // Check to make sure we're in a scenario where we can handle variable resolution.
                        if (null != delayedFields)
                        {
                            // resolve localization and wix variables
                            if (field.Type == IntermediateFieldType.String)
                            {
                                var original = field.AsString();
                                if (!String.IsNullOrEmpty(original))
                                {
                                    var resolution = this.VariableResolver.ResolveVariables(row.SourceLineNumbers, original, false);
                                    if (resolution.UpdatedValue)
                                    {
                                        field.Set(resolution.Value);
                                    }

                                    if (resolution.DelayedResolve)
                                    {
                                        delayedFields.Add(new DelayedField(row, field));
                                    }

                                    isDefault = resolution.IsDefault;
                                }
                            }
                        }

                        // Move to next row if we've hit an error resolving variables.
                        if (this.Messaging.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                        {
                            continue;
                        }

                        // Resolve file paths
                        if (field.Type == IntermediateFieldType.Path)
                        {
                            var objectField = field.AsPath();

#if REVISIT_FOR_PATCHING
                            // Skip file resolution if the file is to be deleted.
                            if (RowOperation.Delete == row.Operation)
                            {
                                continue;
                            }
#endif

                            // File is embedded and path to it was not modified above.
                            if (objectField.EmbeddedFileIndex.HasValue && isDefault)
                            {
                                var extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.BaseUri, objectField.EmbeddedFileIndex.Value, this.IntermediateFolder);

                                // Set the path to the embedded file once where it will be extracted.
                                field.Set(extractPath);
                            }
                            else if (null != objectField.Path) // non-compressed file (or localized value)
                            {
                                try
                                {
                                    if (!this.BuildingPatch) // Normal binding for non-Patch scenario such as link (light.exe)
                                    {
#if REVISIT_FOR_PATCHING
                                        // keep a copy of the un-resolved data for future replay. This will be saved into wixpdb file
                                        if (null == objectField.UnresolvedData)
                                        {
                                            objectField.UnresolvedData = (string)objectField.Data;
                                        }
#endif

                                        // resolve the path to the file
                                        var value = fileResolver.ResolveFile(objectField.Path, row.Definition, row.SourceLineNumbers, BindStage.Normal);
                                        field.Set(value);
                                    }
                                    else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic)
                                    {
                                        // resolve the path to the file
                                        var value = fileResolver.ResolveFile(objectField.Path, row.Definition, row.SourceLineNumbers, BindStage.Normal);
                                        field.Set(value);
                                    }
#if REVISIT_FOR_PATCHING
                                    else // Re-base binding path scenario caused by pyro.exe -bt -bu
                                    {
                                        // by default, use the resolved Data for file lookup
                                        string filePathToResolve = (string)objectField.Data;

                                        // if -bu is used in pyro command, this condition holds true and the tool
                                        // will use pre-resolved source for new wixpdb file
                                        if (fileResolver.RebaseUpdated)
                                        {
                                            // try to use the unResolved Source if it exists.
                                            // New version of wixpdb file keeps a copy of pre-resolved Source. i.e. !(bindpath.test)\foo.dll
                                            // Old version of winpdb file does not contain this attribute and the value is null.
                                            if (null != objectField.UnresolvedData)
                                            {
                                                filePathToResolve = objectField.UnresolvedData;
                                            }
                                        }

                                        objectField.Data = fileResolver.ResolveFile(filePathToResolve, row.Definition.Name, row.SourceLineNumbers, BindStage.Updated);
                                    }
#endif
                                }
                                catch (WixFileNotFoundException)
                                {
                                    // display the error with source line information
                                    this.Messaging.Write(ErrorMessages.FileNotFound(row.SourceLineNumbers, objectField.Path));
                                }
                            }

#if REVISIT_FOR_PATCHING
                            if (null != objectField.PreviousData)
                            {
                                objectField.PreviousData = this.BindVariableResolver.ResolveVariables(row.SourceLineNumbers, objectField.PreviousData, false, out isDefault);

                                if (!Messaging.Instance.EncounteredError) // TODO: make this error handling more specific to just the failure to resolve variables in this field.
                                {
                                    // file is compressed in a cabinet (and not modified above)
                                    if (objectField.PreviousEmbeddedFileIndex.HasValue && isDefault)
                                    {
                                        // when loading transforms from disk, PreviousBaseUri may not have been set
                                        if (null == objectField.PreviousBaseUri)
                                        {
                                            objectField.PreviousBaseUri = objectField.BaseUri;
                                        }

                                        string extractPath = this.FilesWithEmbeddedFiles.AddEmbeddedFileIndex(objectField.PreviousBaseUri, objectField.PreviousEmbeddedFileIndex.Value, this.IntermediateFolder);

                                        // set the path to the file once its extracted from the cabinet
                                        objectField.PreviousData = extractPath;
                                    }
                                    else if (null != objectField.PreviousData) // non-compressed file (or localized value)
                                    {
                                        try
                                        {
                                            if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated)
                                            {
                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, row.Definition.Name, row.SourceLineNumbers, BindStage.Normal);
                                            }
                                            else
                                            {
                                                if (fileResolver.RebaseTarget)
                                                {
                                                    // if -bt is used, it come here
                                                    // Try to use the original unresolved source from either target build or update build
                                                    // If both target and updated are of old wixpdb, it behaves the same as today, no re-base logic here
                                                    // If target is old version and updated is new version, it uses unresolved path from updated build
                                                    // If both target and updated are of new versions, it uses unresolved path from target build
                                                    if (null != objectField.UnresolvedPreviousData || null != objectField.UnresolvedData)
                                                    {
                                                        objectField.PreviousData = objectField.UnresolvedPreviousData ?? objectField.UnresolvedData;
                                                    }
                                                }

                                                // resolve the path to the file
                                                objectField.PreviousData = fileResolver.ResolveFile((string)objectField.PreviousData, row.Definition.Name, row.SourceLineNumbers, BindStage.Target);
                                            }
                                        }
                                        catch (WixFileNotFoundException)
                                        {
                                            // display the error with source line information
                                            Messaging.Instance.Write(WixErrors.FileNotFound(row.SourceLineNumbers, (string)objectField.PreviousData));
                                        }
                                    }
                                }
                            }
#endif
                        }
                    }
                }
            }

            this.DelayedFields = delayedFields;
        }