Exemple #1
1
        /// <summary>
        /// Merges in any modules to the output database.
        /// </summary>
        /// <param name="tempDatabaseFile">The temporary database file.</param>
        /// <param name="output">Output that specifies database and modules to merge.</param>
        /// <param name="fileRows">The indexed file rows.</param>
        /// <param name="suppressedTableNames">The names of tables that are suppressed.</param>
        /// <remarks>Expects that output's database has already been generated.</remarks>
        private void MergeModules(string tempDatabaseFile, Output output, FileRowCollection fileRows, StringCollection suppressedTableNames)
        {
            Debug.Assert(OutputType.Product == output.Type);

            Table wixMergeTable = output.Tables["WixMerge"];
            Table wixFeatureModulesTable = output.Tables["WixFeatureModules"];

            // check for merge rows to see if there is any work to do
            if (null == wixMergeTable || 0 == wixMergeTable.Rows.Count)
            {
                return;
            }

            IMsmMerge2 merge = null;
            bool commit = true;
            bool logOpen = false;
            bool databaseOpen = false;
            string logPath = null;
            try
            {
                merge = NativeMethods.GetMsmMerge();

                logPath = Path.Combine(this.TempFilesLocation, "merge.log");
                merge.OpenLog(logPath);
                logOpen = true;

                merge.OpenDatabase(tempDatabaseFile);
                databaseOpen = true;

                // process all the merge rows
                foreach (WixMergeRow wixMergeRow in wixMergeTable.Rows)
                {
                    bool moduleOpen = false;

                    try
                    {
                        short mergeLanguage;

                        try
                        {
                            mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture);
                        }
                        catch (System.FormatException)
                        {
                            this.core.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language));
                            continue;
                        }

                        this.core.OnMessage(WixVerboses.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage));
                        merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage);
                        moduleOpen = true;

                        // If there is merge configuration data, create a callback object to contain it all.
                        ConfigurationCallback callback = null;
                        if (!String.IsNullOrEmpty(wixMergeRow.ConfigurationData))
                        {
                            callback = new ConfigurationCallback(wixMergeRow.ConfigurationData);
                        }

                        // merge the module into the database that's being built
                        this.core.OnMessage(WixVerboses.MergingMergeModule(wixMergeRow.SourceFile));
                        merge.MergeEx(wixMergeRow.Feature, wixMergeRow.Directory, callback);

                        // connect any non-primary features
                        if (null != wixFeatureModulesTable)
                        {
                            foreach (Row row in wixFeatureModulesTable.Rows)
                            {
                                if (wixMergeRow.Id == (string)row[1])
                                {
                                    this.core.OnMessage(WixVerboses.ConnectingMergeModule(wixMergeRow.SourceFile, (string)row[0]));
                                    merge.Connect((string)row[0]);
                                }
                            }
                        }
                    }
                    catch (COMException)
                    {
                        commit = false;
                    }
                    finally
                    {
                        IMsmErrors mergeErrors = merge.Errors;

                        // display all the errors encountered during the merge operations for this module
                        for (int i = 1; i <= mergeErrors.Count; i++)
                        {
                            IMsmError mergeError = mergeErrors[i];
                            StringBuilder databaseKeys = new StringBuilder();
                            StringBuilder moduleKeys = new StringBuilder();

                            // build a string of the database keys
                            for (int j = 1; j <= mergeError.DatabaseKeys.Count; j++)
                            {
                                if (1 != j)
                                {
                                    databaseKeys.Append(';');
                                }
                                databaseKeys.Append(mergeError.DatabaseKeys[j]);
                            }

                            // build a string of the module keys
                            for (int j = 1; j <= mergeError.ModuleKeys.Count; j++)
                            {
                                if (1 != j)
                                {
                                    moduleKeys.Append(';');
                                }
                                moduleKeys.Append(mergeError.ModuleKeys[j]);
                            }

                            // display the merge error based on the msm error type
                            switch (mergeError.Type)
                            {
                                case MsmErrorType.msmErrorExclusion:
                                    this.core.OnMessage(WixErrors.MergeExcludedModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleKeys.ToString()));
                                    break;
                                case MsmErrorType.msmErrorFeatureRequired:
                                    this.core.OnMessage(WixErrors.MergeFeatureRequired(wixMergeRow.SourceLineNumbers, mergeError.ModuleTable, moduleKeys.ToString(), wixMergeRow.SourceFile, wixMergeRow.Id));
                                    break;
                                case MsmErrorType.msmErrorLanguageFailed:
                                    this.core.OnMessage(WixErrors.MergeLanguageFailed(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile));
                                    break;
                                case MsmErrorType.msmErrorLanguageUnsupported:
                                    this.core.OnMessage(WixErrors.MergeLanguageUnsupported(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile));
                                    break;
                                case MsmErrorType.msmErrorResequenceMerge:
                                    this.core.OnMessage(WixWarnings.MergeRescheduledAction(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile));
                                    break;
                                case MsmErrorType.msmErrorTableMerge:
                                    if ("_Validation" != mergeError.DatabaseTable) // ignore merge errors in the _Validation table
                                    {
                                        this.core.OnMessage(WixWarnings.MergeTableFailed(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile));
                                    }
                                    break;
                                case MsmErrorType.msmErrorPlatformMismatch:
                                    this.core.OnMessage(WixErrors.MergePlatformMismatch(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile));
                                    break;
                                default:
                                    this.core.OnMessage(WixErrors.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorWithType, Enum.GetName(typeof(MsmErrorType), mergeError.Type), logPath), "InvalidOperationException", Environment.StackTrace));
                                    break;
                            }
                        }

                        if (0 >= mergeErrors.Count && !commit)
                        {
                            this.core.OnMessage(WixErrors.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorInSourceFile, wixMergeRow.SourceFile, logPath), "InvalidOperationException", Environment.StackTrace));
                        }

                        if (moduleOpen)
                        {
                            merge.CloseModule();
                        }
                    }
                }
            }
            finally
            {
                if (databaseOpen)
                {
                    merge.CloseDatabase(commit);
                }

                if (logOpen)
                {
                    merge.CloseLog();
                }
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return;
            }

            using (Database db = new Database(tempDatabaseFile, OpenDatabase.Direct))
            {
                Table suppressActionTable = output.Tables["WixSuppressAction"];

                // suppress individual actions
                if (null != suppressActionTable)
                {
                    foreach (Row row in suppressActionTable.Rows)
                    {
                        if (db.TableExists((string)row[0]))
                        {
                            string query = String.Format(CultureInfo.InvariantCulture, "SELECT * FROM {0} WHERE `Action` = '{1}'", row[0].ToString(), (string)row[1]);

                            using (View view = db.OpenExecuteView(query))
                            {
                                using (Record record = view.Fetch())
                                {
                                    if (null != record)
                                    {
                                        this.core.OnMessage(WixWarnings.SuppressMergedAction((string)row[1], row[0].ToString()));
                                        view.Modify(ModifyView.Delete, record);
                                    }
                                }
                            }
                        }
                    }
                }

                // query for merge module actions in suppressed sequences and drop them
                foreach (string tableName in suppressedTableNames)
                {
                    if (!db.TableExists(tableName))
                    {
                        continue;
                    }

                    using (View view = db.OpenExecuteView(String.Concat("SELECT `Action` FROM ", tableName)))
                    {
                        while (true)
                        {
                            using (Record resultRecord = view.Fetch())
                            {
                                if (null == resultRecord)
                                {
                                    break;
                                }

                                this.core.OnMessage(WixWarnings.SuppressMergedAction(resultRecord.GetString(1), tableName));
                            }
                        }
                    }

                    // drop suppressed sequences
                    using (View view = db.OpenExecuteView(String.Concat("DROP TABLE ", tableName)))
                    {
                    }

                    // delete the validation rows
                    using (View view = db.OpenView(String.Concat("DELETE FROM _Validation WHERE `Table` = ?")))
                    {
                        using (Record record = new Record(1))
                        {
                            record.SetString(1, tableName);
                            view.Execute(record);
                        }
                    }
                }

                // now update the Attributes column for the files from the Merge Modules
                this.core.OnMessage(WixVerboses.ResequencingMergeModuleFiles());
                using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?"))
                {
                    foreach (FileRow fileRow in fileRows)
                    {
                        if (!fileRow.FromModule)
                        {
                            continue;
                        }

                        using (Record record = new Record(1))
                        {
                            record.SetString(1, fileRow.File);
                            view.Execute(record);
                        }

                        using (Record recordUpdate = view.Fetch())
                        {
                            if (null == recordUpdate)
                            {
                                throw new InvalidOperationException("Failed to fetch a File row from the database that was merged in from a module.");
                            }

                            recordUpdate.SetInteger(1, fileRow.Sequence);

                            // update the file attributes to match the compression specified
                            // on the Merge element or on the Package element
                            int attributes = 0;

                            // get the current value if its not null
                            if (!recordUpdate.IsNull(2))
                            {
                                attributes = recordUpdate.GetInteger(2);
                            }

                            if (YesNoType.Yes == fileRow.Compressed)
                            {
                                // these are mutually exclusive
                                attributes |= MsiInterop.MsidbFileAttributesCompressed;
                                attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed;
                            }
                            else if (YesNoType.No == fileRow.Compressed)
                            {
                                // these are mutually exclusive
                                attributes |= MsiInterop.MsidbFileAttributesNoncompressed;
                                attributes &= ~MsiInterop.MsidbFileAttributesCompressed;
                            }
                            else // not specified
                            {
                                Debug.Assert(YesNoType.NotSet == fileRow.Compressed);

                                // clear any compression bits
                                attributes &= ~MsiInterop.MsidbFileAttributesCompressed;
                                attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed;
                            }
                            recordUpdate.SetInteger(2, attributes);

                            view.Modify(ModifyView.Update, recordUpdate);
                        }
                    }
                }

                db.Commit();
            }
        }
        /// <summary>
        /// Opens the previous package (.msi or .exe) and reads the interesting information from it.
        /// </summary>
        /// <param name="filePath">Path to the package.</param>
        private void ReadPreviousPackage(string filePath)
        {
            using (Database db = new Database(filePath, OpenDatabase.ReadOnly))
            {
                using (View view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`=?"))
                {

                    string propertyValue;

                    // get the UpgradeCode
                    propertyValue = this.FetchPropertyValue(view, "UpgradeCode");
                    if (propertyValue != null)
                    {
                        this.previousUpgradeCode = new Guid(propertyValue);
                    }

                    // get the Version
                    propertyValue = this.FetchPropertyValue(view, "ProductVersion");
                    if (propertyValue != null)
                    {
                        this.previousVersion = new Version(propertyValue);
                    }

                    // get the Update URL
                    propertyValue = this.FetchPropertyValue(view, "ARPURLUPDATEINFO");
                    if (propertyValue != null)
                    {
                        this.previousUri = new Uri(propertyValue);
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Process uncompressed files.
        /// </summary>
        /// <param name="tempDatabaseFile">The temporary database file.</param>
        /// <param name="fileRows">The collection of files to copy into the image.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</param>
        /// <param name="mediaRows">The indexed media rows.</param>
        /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
        /// <param name="compressed">Flag if source image should be compressed.</param>
        /// <param name="longNamesInImage">Flag if long names should be used.</param>
        private void ProcessUncompressedFiles(string tempDatabaseFile, FileRowCollection fileRows, ArrayList fileTransfers, MediaRowCollection mediaRows, string layoutDirectory, bool compressed, bool longNamesInImage)
        {
            if (0 == fileRows.Count || this.core.EncounteredError)
            {
                return;
            }

            Hashtable directories = new Hashtable();
            using (Database db = new Database(tempDatabaseFile, OpenDatabase.ReadOnly))
            {
                using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
                {
                    while (true)
                    {
                        using (Record directoryRecord = directoryView.Fetch())
                        {
                            if (null == directoryRecord)
                            {
                                break;
                            }

                            string sourceName = Installer.GetName(directoryRecord.GetString(3), true, longNamesInImage);

                            directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName));
                        }
                    }
                }

                using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?"))
                {
                    using (Record fileQueryRecord = new Record(1))
                    {
                        // for each file in the array of uncompressed files
                        foreach (FileRow fileRow in fileRows)
                        {
                            string relativeFileLayoutPath = null;

                            string mediaLayoutDirectory = this.FileManager.ResolveMedia(mediaRows[fileRow.DiskId], layoutDirectory);

                            // setup up the query record and find the appropriate file in the
                            // previously executed file view
                            fileQueryRecord[1] = fileRow.File;
                            fileView.Execute(fileQueryRecord);

                            using (Record fileRecord = fileView.Fetch())
                            {
                                if (null == fileRecord)
                                {
                                    throw new WixException(WixErrors.FileIdentifierNotFound(fileRow.SourceLineNumbers, fileRow.File));
                                }

                                relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], compressed, longNamesInImage);
                            }

                            // finally put together the base media layout path and the relative file layout path
                            string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath);
                            FileTransfer transfer;
                            if (FileTransfer.TryCreate(fileRow.Source, fileLayoutPath, false, "File", fileRow.SourceLineNumbers, out transfer))
                            {
                                fileTransfers.Add(transfer);
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Unbind an MSI database file.
        /// </summary>
        /// <param name="databaseFile">The database file.</param>
        /// <param name="database">The opened database.</param>
        /// <param name="outputType">The type of output to create.</param>
        /// <param name="exportBasePath">The path where files should be exported.</param>
        /// <param name="skipSummaryInfo">Option to skip unbinding the _SummaryInformation table.</param>
        /// <returns>The output representing the database.</returns>
        private Output UnbindDatabase(string databaseFile, Database database, OutputType outputType, string exportBasePath, bool skipSummaryInfo)
        {
            string modularizationGuid = null;
            Output output = new Output(SourceLineNumberCollection.FromFileName(databaseFile));
            View validationView = null;

            // set the output type
            output.Type = outputType;

            // get the codepage
            database.Export("_ForceCodepage", this.TempFilesLocation, "_ForceCodepage.idt");
            using (StreamReader sr = File.OpenText(Path.Combine(this.TempFilesLocation, "_ForceCodepage.idt")))
            {
                string line;

                while (null != (line = sr.ReadLine()))
                {
                    string[] data = line.Split('\t');

                    if (2 == data.Length)
                    {
                        output.Codepage = Convert.ToInt32(data[0], CultureInfo.InvariantCulture);
                    }
                }
            }

            // get the summary information table if it exists; it won't if unbinding a transform
            if (!skipSummaryInfo)
            {
                using (SummaryInformation summaryInformation = new SummaryInformation(database))
                {
                    Table table = new Table(null, this.tableDefinitions["_SummaryInformation"]);

                    for (int i = 1; 19 >= i; i++)
                    {
                        string value = summaryInformation.GetProperty(i);

                        if (0 < value.Length)
                        {
                            Row row = table.CreateRow(output.SourceLineNumbers);
                            row[0] = i;
                            row[1] = value;
                        }
                    }

                    output.Tables.Add(table);
                }
            }

            try
            {
                // open a view on the validation table if it exists
                if (database.TableExists("_Validation"))
                {
                    validationView = database.OpenView("SELECT * FROM `_Validation` WHERE `Table` = ? AND `Column` = ?");
                }

                // get the normal tables
                using (View tablesView = database.OpenExecuteView("SELECT * FROM _Tables"))
                {
                    while (true)
                    {
                        using (Record tableRecord = tablesView.Fetch())
                        {
                            if (null == tableRecord)
                            {
                                break;
                            }

                            string tableName = tableRecord.GetString(1);

                            using (View tableView = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName)))
                            {
                                TableDefinition tableDefinition = new TableDefinition(tableName, false, false);
                                Hashtable tablePrimaryKeys = new Hashtable();

                                using (Record columnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES),
                                              columnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES))
                                {
                                    int columnCount = columnNameRecord.GetFieldCount();

                                    // index the primary keys
                                    using (Record primaryKeysRecord = database.PrimaryKeys(tableName))
                                    {
                                        int primaryKeysFieldCount = primaryKeysRecord.GetFieldCount();

                                        for (int i = 1; i <= primaryKeysFieldCount; i++)
                                        {
                                            tablePrimaryKeys[primaryKeysRecord.GetString(i)] = null;
                                        }
                                    }

                                    for (int i = 1; i <= columnCount; i++)
                                    {
                                        string columnName = columnNameRecord.GetString(i);
                                        string idtType = columnTypeRecord.GetString(i);

                                        ColumnType columnType;
                                        int length;
                                        bool nullable;

                                        ColumnCategory columnCategory = ColumnCategory.Unknown;
                                        ColumnModularizeType columnModularizeType = ColumnModularizeType.None;
                                        bool primary = tablePrimaryKeys.Contains(columnName);
                                        bool minValueSet = false;
                                        int minValue = -1;
                                        bool maxValueSet = false;
                                        int maxValue = -1;
                                        string keyTable = null;
                                        bool keyColumnSet = false;
                                        int keyColumn = -1;
                                        string category = null;
                                        string set = null;
                                        string description = null;

                                        // get the column type, length, and whether its nullable
                                        switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture))
                                        {
                                            case 'i':
                                                columnType = ColumnType.Number;
                                                break;
                                            case 'l':
                                                columnType = ColumnType.Localized;
                                                break;
                                            case 's':
                                                columnType = ColumnType.String;
                                                break;
                                            case 'v':
                                                columnType = ColumnType.Object;
                                                break;
                                            default:
                                                // TODO: error
                                                columnType = ColumnType.Unknown;
                                                break;
                                        }
                                        length = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture);
                                        nullable = Char.IsUpper(idtType[0]);

                                        // try to get validation information
                                        if (null != validationView)
                                        {
                                            using (Record validationRecord = new Record(2))
                                            {
                                                validationRecord.SetString(1, tableName);
                                                validationRecord.SetString(2, columnName);

                                                validationView.Execute(validationRecord);
                                            }

                                            using (Record validationRecord = validationView.Fetch())
                                            {
                                                if (null != validationRecord)
                                                {
                                                    string validationNullable = validationRecord.GetString(3);
                                                    minValueSet = !validationRecord.IsNull(4);
                                                    minValue = (minValueSet ? validationRecord.GetInteger(4) : -1);
                                                    maxValueSet = !validationRecord.IsNull(5);
                                                    maxValue = (maxValueSet ? validationRecord.GetInteger(5) : -1);
                                                    keyTable = (!validationRecord.IsNull(6) ? validationRecord.GetString(6) : null);
                                                    keyColumnSet = !validationRecord.IsNull(7);
                                                    keyColumn = (keyColumnSet ? validationRecord.GetInteger(7) : -1);
                                                    category = (!validationRecord.IsNull(8) ? validationRecord.GetString(8) : null);
                                                    set = (!validationRecord.IsNull(9) ? validationRecord.GetString(9) : null);
                                                    description = (!validationRecord.IsNull(10) ? validationRecord.GetString(10) : null);

                                                    // check the validation nullable value against the column definition
                                                    if (null == validationNullable)
                                                    {
                                                        // TODO: warn for illegal validation nullable column
                                                    }
                                                    else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable))
                                                    {
                                                        // TODO: warn for mismatch between column definition and validation nullable
                                                    }

                                                    // convert category to ColumnCategory
                                                    if (null != category)
                                                    {
                                                        try
                                                        {
                                                            columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true);
                                                        }
                                                        catch (ArgumentException)
                                                        {
                                                            columnCategory = ColumnCategory.Unknown;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    // TODO: warn about no validation information
                                                }
                                            }
                                        }

                                        // guess the modularization type
                                        if ("Icon" == keyTable && 1 == keyColumn)
                                        {
                                            columnModularizeType = ColumnModularizeType.Icon;
                                        }
                                        else if ("Condition" == columnName)
                                        {
                                            columnModularizeType = ColumnModularizeType.Condition;
                                        }
                                        else if (ColumnCategory.Formatted == columnCategory || ColumnCategory.FormattedSDDLText == columnCategory)
                                        {
                                            columnModularizeType = ColumnModularizeType.Property;
                                        }
                                        else if (ColumnCategory.Identifier == columnCategory)
                                        {
                                            columnModularizeType = ColumnModularizeType.Column;
                                        }

                                        tableDefinition.Columns.Add(new ColumnDefinition(columnName, columnType, length, primary, nullable, columnModularizeType, (ColumnType.Localized == columnType), minValueSet, minValue, maxValueSet, maxValue, keyTable, keyColumnSet, keyColumn, columnCategory, set, description, true, true));
                                    }
                                }
                                // use our table definitions if core properties are the same; this allows us to take advantage
                                // of wix concepts like localizable columns which current code assumes
                                if (this.tableDefinitions.Contains(tableName) && 0 == tableDefinition.CompareTo(this.tableDefinitions[tableName]))
                                {
                                    tableDefinition = this.tableDefinitions[tableName];
                                }
                                Table table = new Table(null, tableDefinition);

                                while (true)
                                {
                                    using (Record rowRecord = tableView.Fetch())
                                    {
                                        if (null == rowRecord)
                                        {
                                            break;
                                        }

                                        int recordCount = rowRecord.GetFieldCount();
                                        Row row = table.CreateRow(output.SourceLineNumbers);

                                        for (int i = 0; recordCount > i && row.Fields.Length > i; i++)
                                        {
                                            if (rowRecord.IsNull(i + 1))
                                            {
                                                if (!row.Fields[i].Column.IsNullable)
                                                {
                                                    // TODO: display an error for a null value in a non-nullable field OR
                                                    // display a warning and put an empty string in the value to let the compiler handle it
                                                    // (the second option is risky because the later code may make certain assumptions about
                                                    // the contents of a row value)
                                                }
                                            }
                                            else
                                            {
                                                switch (row.Fields[i].Column.Type)
                                                {
                                                    case ColumnType.Number:
                                                        bool success = false;
                                                        int intValue = rowRecord.GetInteger(i + 1);
                                                        if (row.Fields[i].Column.IsLocalizable)
                                                        {
                                                            success = row.BestEffortSetField(i, Convert.ToString(intValue, CultureInfo.InvariantCulture));
                                                        }
                                                        else
                                                        {
                                                            success = row.BestEffortSetField(i, intValue);
                                                        }

                                                        if (!success)
                                                        {
                                                            this.OnMessage(WixWarnings.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name));
                                                        }
                                                        break;
                                                    case ColumnType.Object:
                                                        string sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES";

                                                        if (null != exportBasePath)
                                                        {
                                                            string relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.'));
                                                            sourceFile = Path.Combine(exportBasePath, relativeSourceFile);

                                                            // ensure the parent directory exists
                                                            System.IO.Directory.CreateDirectory(Path.Combine(exportBasePath, tableName));

                                                            using (FileStream fs = System.IO.File.Create(sourceFile))
                                                            {
                                                                int bytesRead;
                                                                byte[] buffer = new byte[512];

                                                                while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length)))
                                                                {
                                                                    fs.Write(buffer, 0, bytesRead);
                                                                }
                                                            }
                                                        }

                                                        row[i] = sourceFile;
                                                        break;
                                                    default:
                                                        string value = rowRecord.GetString(i + 1);

                                                        switch (row.Fields[i].Column.Category)
                                                        {
                                                            case ColumnCategory.Guid:
                                                                value = value.ToUpper(CultureInfo.InvariantCulture);
                                                                break;
                                                        }

                                                        // de-modularize
                                                        if (!this.suppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType)
                                                        {
                                                            Regex modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}");

                                                            if (null == modularizationGuid)
                                                            {
                                                                Match match = modularization.Match(value);
                                                                if (match.Success)
                                                                {
                                                                    modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}');
                                                                }
                                                            }

                                                            value = modularization.Replace(value, String.Empty);
                                                        }

                                                        // escape "$(" for the preprocessor
                                                        value = value.Replace("$(", "$$(");

                                                        // escape things that look like wix variables
                                                        MatchCollection matches = Common.WixVariableRegex.Matches(value);
                                                        for (int j = matches.Count - 1; 0 <= j; j--)
                                                        {
                                                            value = value.Insert(matches[j].Index, "!");
                                                        }

                                                        row[i] = value;
                                                        break;
                                                }
                                            }
                                        }
                                    }
                                }

                                output.Tables.Add(table);
                            }

                        }
                    }
                }
            }
            finally
            {
                if (null != validationView)
                {
                    validationView.Close();
                }
            }

            // set the modularization guid as the PackageCode
            if (null != modularizationGuid)
            {
                Table table = output.Tables["_SummaryInformation"];

                foreach (Row row in table.Rows)
                {
                    if (9 == (int)row[0]) // PID_REVNUMBER
                    {
                        row[1] = modularizationGuid;
                    }
                }
            }

            if (this.isAdminImage)
            {
                GenerateWixFileTable(databaseFile, output);
                GenerateSectionIds(output);
            }

            return output;
        }
Exemple #5
0
        /// <summary>
        /// Extract the cabinets from a database.
        /// </summary>
        /// <param name="output">The output to use when finding cabinets.</param>
        /// <param name="database">The database containing the cabinets.</param>
        /// <param name="databaseFile">The location of the database file.</param>
        /// <param name="exportBasePath">The path where the files should be exported.</param>
        private void ExtractCabinets(Output output, Database database, string databaseFile, string exportBasePath)
        {
            string databaseBasePath = Path.GetDirectoryName(databaseFile);
            StringCollection cabinetFiles = new StringCollection();
            SortedList embeddedCabinets = new SortedList();

            // index all of the cabinet files
            if (OutputType.Module == output.Type)
            {
                embeddedCabinets.Add(0, "MergeModule.CABinet");
            }
            else if (null != output.Tables["Media"])
            {
                foreach (MediaRow mediaRow in output.Tables["Media"].Rows)
                {
                    if (null != mediaRow.Cabinet)
                    {
                        if (OutputType.Product == output.Type ||
                            (OutputType.Transform == output.Type && RowOperation.Add == mediaRow.Operation))
                        {
                            if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal))
                            {
                                embeddedCabinets.Add(mediaRow.DiskId, mediaRow.Cabinet.Substring(1));
                            }
                            else
                            {
                                cabinetFiles.Add(Path.Combine(databaseBasePath, mediaRow.Cabinet));
                            }
                        }
                    }
                }
            }

            // extract the embedded cabinet files from the database
            if (0 < embeddedCabinets.Count)
            {
                using (View streamsView = database.OpenView("SELECT `Data` FROM `_Streams` WHERE `Name` = ?"))
                {
                    foreach (int diskId in embeddedCabinets.Keys)
                    {
                        using(Record record = new Record(1))
                        {
                            record.SetString(1, (string)embeddedCabinets[diskId]);
                            streamsView.Execute(record);
                        }

                        using (Record record = streamsView.Fetch())
                        {
                            if (null != record)
                            {
                                // since the cabinets are stored in case-sensitive streams inside the msi, but the file system is not case-sensitive,
                                // embedded cabinets must be extracted to a canonical file name (like their diskid) to ensure extraction will always work
                                string cabinetFile = Path.Combine(this.TempFilesLocation, String.Concat("Media", Path.DirectorySeparatorChar, diskId.ToString(CultureInfo.InvariantCulture), ".cab"));

                                // ensure the parent directory exists
                                System.IO.Directory.CreateDirectory(Path.GetDirectoryName(cabinetFile));

                                using (FileStream fs = System.IO.File.Create(cabinetFile))
                                {
                                    int bytesRead;
                                    byte[] buffer = new byte[512];

                                    while (0 != (bytesRead = record.GetStream(1, buffer, buffer.Length)))
                                    {
                                        fs.Write(buffer, 0, bytesRead);
                                    }
                                }

                                cabinetFiles.Add(cabinetFile);
                            }
                            else
                            {
                                // TODO: warning about missing embedded cabinet
                            }
                        }
                    }
                }
            }

            // extract the cabinet files
            if (0 < cabinetFiles.Count)
            {
                string fileDirectory = Path.Combine(exportBasePath, "File");

                // delete the directory and its files to prevent cab extraction due to an existing file
                if (Directory.Exists(fileDirectory))
                {
                    Directory.Delete(fileDirectory, true);
                }

                // ensure the directory exists or extraction will fail
                Directory.CreateDirectory(fileDirectory);

                foreach (string cabinetFile in cabinetFiles)
                {
                    using (WixExtractCab extractCab = new WixExtractCab())
                    {
                        try
                        {
                            extractCab.Extract(cabinetFile, fileDirectory);
                        }
                        catch (FileNotFoundException)
                        {
                            throw new WixException(WixErrors.FileNotFound(SourceLineNumberCollection.FromFileName(databaseFile), cabinetFile));
                        }
                    }
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Lays out the binaries for the uncompressed portion of a source image.
        /// </summary>
        /// <param name="databasePath">Path to database.</param>
        /// <param name="output">Output being created.</param>
        /// <param name="files">Array of files to copy into image.</param>
        /// <param name="packageCompressed">Flag if package is compressed.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</param>
        private void CreateUncompressedImage(string databasePath, Output output, ArrayList files, bool packageCompressed, ArrayList fileTransfers)
        {
            if (0 == files.Count || this.foundError)
            {
                return;
            }

            bool longNamesInImage = output.LongFileNames;
            Hashtable directories = new Hashtable();
            using (Database db = new Database(databasePath, OpenDatabase.ReadOnly))
            {
                using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
                {
                    Record directoryRecord;

                    while (directoryView.Fetch(out directoryRecord))
                    {
                        string sourceName = GetSourceName(directoryRecord.GetString(3), longNamesInImage);

                        directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName));
                    }
                }

                using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?"))
                {
                    // if an output path was specified for our image, use that as our default base,
                    // otherwise use the directory where the output is being placed
                    string defaultBaseOuputPath = null != this.imagebaseOutputPath ? this.imagebaseOutputPath : Path.GetDirectoryName(output.Path);

                    using (Record fileQueryRecord = new Record(1))
                    {
                        // for each file in the array of uncompressed files
                        foreach (FileMediaInformation fmi in files)
                        {
                            string currentSourcePath = null;
                            string relativeSourcePath = null;

                            // determine what the base of the file should be.  If there was
                            // no src specified in the Media element (the default) then just
                            // use the default output path (usually the same directory as the
                            // output file).  If there was a build directory specified then
                            // check if it is a absolute path, and if not add the default
                            // output path to the root
                            MediaRow mediaRow = output.MediaRows[fmi.Media];
                            string baseRelativeSourcePath = mediaRow.Layout;
                            if (null == baseRelativeSourcePath)
                            {
                                baseRelativeSourcePath = defaultBaseOuputPath;
                            }
                            else if (!Path.IsPathRooted(baseRelativeSourcePath))
                            {
                                baseRelativeSourcePath = Path.Combine(defaultBaseOuputPath, baseRelativeSourcePath);
                            }

                            // setup up the query record and find the appropriate file in the
                            // previously executed file view
                            fileQueryRecord[1] = fmi.File;
                            fileView.Execute(fileQueryRecord);

                            Record fileRecord;
                            if (!fileView.Fetch(out fileRecord))
                            {
                                throw new WixFileMediaInformationKeyNotFoundException(fmi.File);
                            }

                            string fileName = GetSourceName(fileRecord[2], longNamesInImage);

                            if (packageCompressed)
                            {
                                // use just the file name of the file since all uncompressed files must appear
                                // in the root of the image in a compressed package
                                relativeSourcePath = fileName;
                            }
                            else
                            {
                                // get the relative path of where we want the source to be as specified
                                // in the Directory table
                                string directoryPath = GetDirectoryPath(directories, fileRecord[1], longNamesInImage);
                                relativeSourcePath = Path.Combine(directoryPath, fileName);
                            }

                            // if the relative source path was not resolved above then we have to bail
                            if (null == relativeSourcePath)
                            {
                                throw new WixFileMediaInformationKeyNotFoundException(fmi.File);
                            }

                            // strip off "SourceDir" if it's still on there
                            if (relativeSourcePath.StartsWith("SourceDir\\"))
                            {
                                relativeSourcePath = relativeSourcePath.Substring(10);
                            }

                            // resolve the src path for the file and ensure it exists
                            try
                            {
                                currentSourcePath = this.extension.FileResolutionHandler(fmi.Source, FileResolutionType.File);
                            }
                            catch (WixFileNotFoundException wfnfe)
                            {
                                this.OnMessage(WixErrors.BinderExtensionMissingFile(null, ErrorLevel.Normal, wfnfe.Message));
                                continue;
                            }

                            if (!(File.Exists(currentSourcePath)))
                            {
                                this.OnMessage(WixErrors.CannotFindFile(null, ErrorLevel.Normal, fmi.FileId, fmi.File, fmi.Source));
                                continue;
                            }

                            // finally put together the base image output path and the resolved source path
                            string resolvedSourcePath = Path.Combine(baseRelativeSourcePath, relativeSourcePath);

                            // if the current source path (where we know that the file already exists) and the resolved
                            // path as dictated by the Directory table are not the same, then propagate the file.  The
                            // image that we create may have already been done by some other process other than the linker, so
                            // there is no reason to copy the files to the resolved source if they are already there.
                            if (0 != String.Compare(Path.GetFullPath(currentSourcePath), Path.GetFullPath(resolvedSourcePath), true))
                            {
                                // just put the file in the transfers array, how anti-climatic
                                fileTransfers.Add(new FileTransfer(currentSourcePath, resolvedSourcePath, false));
                            }
                        }
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Merges in any modules to the output database.
        /// </summary>
        /// <param name="databasePath">Path to database.</param>
        /// <param name="output">Output that specifies database and modules to merge.</param>
        /// <remarks>Expects that output's database has already been generated.</remarks>
        private void MergeModules(string databasePath, Output output)
        {
            Debug.Assert(OutputType.Product == output.Type);

            if (0 == output.Modules.Count)   // no work to do
            {
                return;
            }

            IMsmMerge2 merge = null;
            bool commit = false;
            bool logOpen = false;
            bool databaseOpen = false;
            bool moduleOpen = false;
            try
            {
                bool foundError = false;
                MsmMerge msm = new MsmMerge();
                merge = (IMsmMerge2)msm;

                merge.OpenLog(String.Concat(this.tempFiles.BasePath, Path.DirectorySeparatorChar, "merge.log"));
                logOpen = true;

                merge.OpenDatabase(databasePath);
                databaseOpen = true;

                // process all the merge rows
                foreach (MergeRow mergeRow in output.Modules)
                {
                    string mergeModulePath = null;
                    try
                    {
                        mergeModulePath = this.extension.FileResolutionHandler(mergeRow.SourceFile, FileResolutionType.Module);
                    }
                    catch (WixFileNotFoundException wfnfe)
                    {
                        this.OnMessage(WixErrors.BinderExtensionMissingFile(mergeRow.SourceLineNumbers, ErrorLevel.Normal, wfnfe.Message));
                        foundError = true;
                        continue;
                    }

                    try
                    {
                        merge.OpenModule(mergeModulePath, mergeRow.Language);
                    }
                    catch (COMException ce)
                    {
                        if (-2147023273 == ce.ErrorCode) // 0x80070657 - ERROR_INSTALL_LANGUAGE_UNSUPPORTED
                        {
                            throw new WixUnknownMergeLanguageException(mergeRow.SourceLineNumbers, mergeRow.Id, mergeModulePath, mergeRow.Language, ce);
                        }
                        else
                        {
                            throw;
                        }
                    }
                    moduleOpen = true;

                    ConnectToFeature connection = output.ModulesToFeatures[mergeRow.Id];
                    if (null == connection)
                    {
                        throw new WixMergeModuleMissingFeatureException(mergeRow.SourceLineNumbers, mergeRow.Id);
                    }

                    string configData = mergeRow.ConfigurationData;
                    if (null != configData)
                    {
                        ConfigurationCallback callback = new ConfigurationCallback(configData);
                        merge.MergeEx(connection.PrimaryFeature, mergeRow.Directory, callback);
                    }
                    else
                    {
                        merge.Merge(connection.PrimaryFeature, mergeRow.Directory);
                    }

                    /*
                    IMsmErrors errorCollection = null;
                    merge.get_Errors(out errorCollection);
                    long count = errorCollection.get_Count();

                    if (0 < count)
                    {

                        throw new WixMergeFailureException(null, this.tempFiles.BasePath, count, null);
                    }
                    */

                    foreach (string connectTo in connection.ConnectFeatures)
                    {
                        merge.Connect(connectTo);
                    }

                    // if the module has files and creating layout
                    if (mergeRow.HasFiles && !this.suppressLayout)
                    {
                        string hashedMergeId = mergeRow.Id.GetHashCode().ToString("X4", CultureInfo.InvariantCulture.NumberFormat);

                        // extract the module cabinet, then explode all of the files to a temp directory
                        string moduleCabPath = String.Concat(this.tempFiles.BasePath, Path.DirectorySeparatorChar, hashedMergeId, ".module.cab");
                        merge.ExtractCAB(moduleCabPath);

                        string mergeIdPath = String.Concat(this.tempFiles.BasePath, Path.DirectorySeparatorChar, "MergeId.", hashedMergeId);
                        Directory.CreateDirectory(mergeIdPath);

                        WixExtractCab extCab = null;
                        try
                        {
                            extCab = new WixExtractCab();
                            extCab.Extract(moduleCabPath, mergeIdPath);
                        }
                        catch (WixCabExtractionException wce)
                        {
                            COMException comException = wce.InnerException as COMException;
                            foundError = true;
                            if (null != comException && 0x80070002 == unchecked((uint)comException.ErrorCode))
                            {
                                extCab = null; // Cab doesn't exist, so drop the object.
                                this.OnMessage(WixErrors.CabFileDoesNotExist(moduleCabPath, mergeModulePath, mergeIdPath));
                            }
                            else
                            {
                                this.OnMessage(WixErrors.CabExtractionFailed(moduleCabPath, mergeModulePath, mergeIdPath));
                            }
                        }
                        finally
                        {
                            if (null != extCab)
                            {
                                try
                                {
                                    extCab.Close();
                                }
                                catch (WixCabExtractionException)
                                {
                                    this.OnMessage(WixErrors.CabClosureFailed(moduleCabPath));
                                }
                            }
                        }
                    }

                    moduleOpen = false;
                    merge.CloseModule();
                }

                commit = !foundError; // if all seems to have progressed cleanly, feel free to commit the changes to the database
            }
            finally
            {
                if (moduleOpen)
                {
                    merge.CloseModule();
                }
                if (databaseOpen)
                {
                    merge.CloseDatabase(commit);
                }
                if (logOpen)
                {
                    merge.CloseLog();
                }
            }

            // create a Hashtable of all the suppressed sequence types
            Hashtable suppressedTableNames = new Hashtable();
            if (output.SuppressAdminSequence)
            {
                suppressedTableNames[Action.SequenceTypeToString(SequenceType.adminExecute)] = null;
                suppressedTableNames[Action.SequenceTypeToString(SequenceType.adminUI)] = null;
            }
            if (output.SuppressAdvertiseSequence)
            {
                suppressedTableNames[Action.SequenceTypeToString(SequenceType.advertiseExecute)] = null;
            }
            if (output.SuppressUISequence)
            {
                suppressedTableNames[Action.SequenceTypeToString(SequenceType.adminUI)] = null;
                suppressedTableNames[Action.SequenceTypeToString(SequenceType.installUI)] = null;
            }

            using (Database db = new Database(databasePath, OpenDatabase.Direct))
            {
                OutputTable suppressActionOutputTable = output.OutputTables["SuppressAction"];

                // suppress individual actions
                if (null != suppressActionOutputTable)
                {
                    foreach (OutputRow outputRow in suppressActionOutputTable.OutputRows)
                    {
                        if (db.TableExists((string)outputRow.Row[0]))
                        {
                            Row row = outputRow.Row;
                            string query = String.Format("SELECT * FROM {0} WHERE `Action` = '{1}'", row[0].ToString(), (string)row[1]);

                            using (View view = db.OpenExecuteView(query))
                            {
                                Record record;

                                if (view.Fetch(out record))
                                {
                                    this.OnMessage(WixWarnings.SuppressMergedAction((string)row[1], row[0].ToString()));
                                    view.Modify(ModifyView.Delete, record);
                                    record.Close();
                                }
                            }
                        }
                    }
                }

                // query for merge module actions in suppressed sequences and drop them
                foreach (string tableName in suppressedTableNames.Keys)
                {
                    if (!db.TableExists(tableName))
                    {
                        continue;
                    }

                    using (View view = db.OpenExecuteView(String.Concat("SELECT `Action` FROM ", tableName)))
                    {
                        Record resultRecord;
                        while (view.Fetch(out resultRecord))
                        {
                            this.OnMessage(WixWarnings.SuppressMergedAction(resultRecord.GetString(1), tableName));
                            resultRecord.Close();
                        }
                    }

                    // drop suppressed sequences
                    using (View view = db.OpenExecuteView(String.Concat("DROP TABLE ", tableName)))
                    {
                    }

                    // delete the validation rows
                    using (View view = db.OpenView(String.Concat("DELETE FROM _Validation WHERE `Table` = ?")))
                    {
                        Record record = new Record(1);
                        record.SetString(1, tableName);
                        view.Execute(record);
                    }
                }

                // now update the Attributes column for the files from the Merge Modules
                using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?"))
                {
                    foreach (FileMediaInformation fmi in output.FileMediaInformationCollection)
                    {
                        if (!fmi.IsInModule)
                        {
                            continue;
                        }

                        Record record = new Record(1);
                        record.SetString(1, fmi.File);
                        view.Execute(record);

                        Record recordUpdate;
                        view.Fetch(out recordUpdate);

                        if (null == recordUpdate)
                        {
                            throw new WixMergeFailureException(null, this.tempFiles.BasePath, 1, null);
                        }

                        recordUpdate.SetInteger(1, fmi.Sequence);

                        // update the file attributes to match the compression specified
                        // on the Merge element or on the Package element
                        int attributes = 0;

                        // get the current value if its not null
                        if (!recordUpdate.IsNull(2))
                        {
                            attributes = recordUpdate.GetInteger(2);
                        }

                        if (FileCompressionValue.Yes == fmi.FileCompression)
                        {
                            attributes |= MsiInterop.MsidbFileAttributesCompressed;
                        }
                        else if (FileCompressionValue.No == fmi.FileCompression)
                        {
                            attributes |= MsiInterop.MsidbFileAttributesNoncompressed;
                        }
                        else // not specified
                        {
                            Debug.Assert(FileCompressionValue.NotSpecified == fmi.FileCompression);

                            // clear any compression bits
                            attributes &= ~MsiInterop.MsidbFileAttributesCompressed;
                            attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed;
                        }
                        recordUpdate.SetInteger(2, attributes);

                        view.Modify(ModifyView.Update, recordUpdate);
                    }
                }

                db.Commit();
            }
        }
Exemple #8
0
        /// <summary>
        /// Opens the previous package (.msi or .exe) and reads the interesting information from it.
        /// </summary>
        /// <param name="filePath">Path to the package.</param>
        /// <param name="previousUpgradeCode">Upgrade code of the package.</param>
        /// <param name="previousVersion">Version of the package.</param>
        /// <param name="previousUri">Update URL of the package.</param>
        private void ReadPreviousPackage(string filePath, out Guid previousUpgradeCode, out Version previousVersion, out Uri previousUri)
        {
            // assume nothing about the previous package
            previousUpgradeCode = Guid.Empty;
            previousVersion = null;
            previousUri = null;

            string tempFileName = null;
            Database db = null;
            View view = null;

            try
            {
                string msiPath = filePath; // assume the file path is the path to the MSI

                // if the extension on the file path is ".exe" try to extract the MSI out of it
                if (String.Compare(Path.GetExtension(filePath), ".exe", true) == 0)
                {
                    tempFileName = Path.GetTempFileName();

                    Process process = new Process();
                    process.StartInfo.FileName = filePath;
                    process.StartInfo.CreateNoWindow = true;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.Arguments = String.Concat("-out ", tempFileName);

                    process.Start();
                    process.WaitForExit();

                    if (process.ExitCode != 0)
                    {
                        throw new ApplicationException(String.Concat("Failed to extract MSI from ", process.StartInfo.FileName));
                    }

                    msiPath = tempFileName; // the MSI is now at the temp filename location
                }

                db = new Database(msiPath, OpenDatabase.ReadOnly);
                view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`=?");

                string propertyValue;

                // get the UpgradeCode
                propertyValue = this.FetchPropertyValue(view, "UpgradeCode");
                if (propertyValue != null)
                {
                    previousUpgradeCode = new Guid(propertyValue);
                }

                // get the Version
                propertyValue = this.FetchPropertyValue(view, "ProductVersion");
                if (propertyValue != null)
                {
                    previousVersion = new Version(propertyValue);
                }

                // get the Update URL
                propertyValue = this.FetchPropertyValue(view, "ARPURLUPDATEINFO");
                if (propertyValue != null)
                {
                    previousUri = new Uri(propertyValue);
                }
            }
            finally
            {
                if (view != null)
                {
                    view.Close();
                }

                if (db != null)
                {
                    db.Close();
                }

                if (tempFileName != null)
                {
                    File.Delete(tempFileName);
                }
            }
        }