// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Dtf.WindowsInstaller.Linq { using System; using System.IO; using WixToolset.Dtf.WindowsInstaller.Linq.Entities; /// /// Allows any Database instance to be converted into a queryable database. /// public static class Queryable { /// /// Converts any Database instance into a queryable database. /// /// /// Queryable database instance that operates on the same /// MSI handle. /// /// This extension method is meant for convenient on-the-fly conversion. /// If the existing database instance already happens to be a QDatabase, /// then it is returned unchanged. Otherwise since the new database /// carries the same MSI handle, only one of the instances needs to be /// closed, not both. /// public static QDatabase AsQueryable(this Database db) { QDatabase qdb = db as QDatabase; if (qdb == null && db != null) { qdb = new QDatabase(db.Handle, true, db.FilePath, db.OpenMode); } return qdb; } } /// /// Queryable MSI database - extends the base Database class with /// LINQ query functionality along with predefined entity types /// for common tables. /// public class QDatabase : Database { /// /// Opens an existing database in read-only mode. /// /// Path to the database file. /// the database could not be created/opened /// /// Because this constructor initiates database access, it cannot be used with a /// running installation. /// The Database object should be d after use. /// The finalizer will close the handle if it is still open, however due to the nondeterministic /// nature of finalization it is best that the handle be closed manually as soon as it is no /// longer needed, as leaving lots of unused handles open can degrade performance. /// public QDatabase(string filePath) : base(filePath) { } /// /// Opens an existing database with another database as output. /// /// Path to the database to be read. /// Open mode for the database /// Database object representing the created or opened database /// the database could not be created/opened /// /// When a database is opened as the output of another database, the summary information stream /// of the output database is actually a read-only mirror of the original database and thus cannot /// be changed. Additionally, it is not persisted with the database. To create or modify the /// summary information for the output database it must be closed and re-opened. /// The returned Database object should be d after use. /// The finalizer will close the handle if it is still open, however due to the nondeterministic /// nature of finalization it is best that the handle be closed manually as soon as it is no /// longer needed, as leaving lots of unused handles open can degrade performance. /// public QDatabase(string filePath, string outputPath) : base(filePath, outputPath) { } /// /// Opens an existing database or creates a new one. /// /// Path to the database file. If an empty string /// is supplied, a temporary database is created that is not persisted. /// Open mode for the database /// the database could not be created/opened /// /// To make and save changes to a database first open the database in transaction, /// create or, or direct mode. After making the changes, always call the Commit method /// before closing the database handle. The Commit method flushes all buffers. /// Always call the Commit method on a database that has been opened in direct /// mode before closing the database. Failure to do this may corrupt the database. /// Because this constructor initiates database access, it cannot be used with a /// running installation. /// The Database object should be d after use. /// The finalizer will close the handle if it is still open, however due to the nondeterministic /// nature of finalization it is best that the handle be closed manually as soon as it is no /// longer needed, as leaving lots of unused handles open can degrade performance. /// public QDatabase(string filePath, DatabaseOpenMode mode) : base(filePath, mode) { } /// /// Creates a new database from an MSI handle. /// /// Native MSI database handle. /// True if the handle should be closed /// when the database object is disposed /// Path of the database file, if known /// Mode the handle was originally opened in protected internal QDatabase( IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode) : base(handle, ownsHandle, filePath, openMode) { } /// /// Gets or sets a log where all MSI SQL queries are written. /// /// /// The log can be useful for debugging, or simply to watch the LINQ magic in action. /// public TextWriter Log { get; set; } /// /// Gets a queryable table from the datbaase. /// /// name of the table public QTable this[string table] { get { return new QTable(this, table); } } #if !CODE_ANALYSIS #region Queryable tables /// Queryable standard table with predefined specialized record type. public QTable Components { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable CreateFolders { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable CustomActions { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Directories { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable DuplicateFiles { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Features { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable FeatureComponents { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Files { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable FileHashes { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable InstallExecuteSequences { get { return new QTable(this, "InstallExecuteSequence"); } } /// Queryable standard table with predefined specialized record type. public QTable InstallUISequences { get { return new QTable(this, "InstallUISequence"); } } /// Queryable standard table with predefined specialized record type. public QTable LaunchConditions { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Medias { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Properties { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable Registries { get { return new QTable(this); } } /// Queryable standard table with predefined specialized record type. public QTable RemoveFiles { get { return new QTable(this); } } #endregion // Queryable tables #endif // !CODE_ANALYSIS } }