Exemple #1
0
 /// <summary>
 /// Creates a new database from an MSI handle.
 /// </summary>
 /// <param name="handle">Native MSI database handle.</param>
 /// <param name="ownsHandle">True if the handle should be closed
 /// when the database object is disposed</param>
 /// <param name="filePath">Path of the database file, if known</param>
 /// <param name="openMode">Mode the handle was originally opened in</param>
 protected internal Database(
     IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode)
     : base(handle, ownsHandle)
 {
     this.filePath = filePath;
     this.openMode = openMode;
 }
Exemple #2
0
        private static int Open(string filePath, DatabaseOpenMode mode)
        {
            if (String.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath");
            }

            if (Path.GetExtension(filePath).Equals(".msp", StringComparison.Ordinal))
            {
                const int DATABASEOPENMODE_PATCH = 32;
                int       patchMode = (int)mode | DATABASEOPENMODE_PATCH;
                mode = (DatabaseOpenMode)patchMode;
            }

            int  hDb;
            uint ret = NativeMethods.MsiOpenDatabase(filePath, (IntPtr)mode, out hDb);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(
                          ret,
                          String.Format(CultureInfo.InvariantCulture, "Database=\"{0}\"", filePath));
            }
            return(hDb);
        }
Exemple #3
0
    /// <summary>
    /// Creates a new InstallPackage object, specifying an alternate file source
    /// directory and/or working directory.
    /// </summary>
    /// <param name="packagePath">Path to the install package to be created or opened</param>
    /// <param name="openMode">Open mode for the database</param>
    /// <param name="sourceDir">Location to obtain source files and cabinets when extracting
    /// or updating files in the working directory. This is often the location of an original
    /// copy of the package that is not meant to be modified. If this parameter is null, it
    /// defaults to the directory of <paramref name="packagePath"/>.</param>
    /// <param name="workingDir">Location where files will be extracted to/updated from. Also
    /// the location where a temporary folder is created during some operations. If this
    /// parameter is null, it defaults to the directory of <paramref name="packagePath"/>.</param>
    /// <remarks>If the source location is different than the working directory, then
    /// no files will be modified at the source location.
    /// </remarks>
    public InstallPackage(string packagePath, DatabaseOpenMode openMode,
        string sourceDir, string workingDir) : base(packagePath, openMode)
    {
        this.sourceDir  = (sourceDir  != null ? sourceDir  : Path.GetDirectoryName(packagePath));
        this.workingDir = (workingDir != null ? workingDir : Path.GetDirectoryName(packagePath));
        this.compressionLevel = CompressionLevel.Normal;

        this.DeleteOnClose(this.TempDirectory);
    }
        /// <summary>
        /// Attach an existing database and return a connection to
        /// the database.
        /// </summary>
        /// <param name="database">The path to the database.</param>
        /// <param name="mode">The mode to open the database in.</param>
        /// <returns>A new connection to the database.</returns>
        public virtual Connection AttachDatabase(string database, DatabaseOpenMode mode)
        {
            database = Path.GetFullPath(database);

            lock (this.lockObject)
            {
                this.SetGlobalParameters();
                this.Tracer.TraceInfo("attach database '{0}'", database);

                if (!this.instances.ContainsKey(database))
                {
                    return(this.CreateNewInstanceAndConnection(database, mode));
                }

                return(this.CreateNewConnection(database, mode));
            }
        }
        /// <summary>
        /// Create a new instance and a connection on that instance.
        /// A new InstanceInfo is added to the instance dictionary.
        /// </summary>
        /// <param name="database">The database to connect to.</param>
        /// <param name="mode">The mode to connect to the database in.</param>
        /// <returns>A new Connection to the database.</returns>
        private Connection CreateNewInstanceAndConnection(string database, DatabaseOpenMode mode)
        {
            var instanceName = this.GetNewInstanceName();
            var instance     = new Instance(instanceName);

            this.Tracer.TraceInfo("created instance '{0}'", instanceName);
            try
            {
                SetParametersAndInitializeInstance(database, instance);
                this.instances[database] = new InstanceInfo(instance, database);
                return(this.CreateNewConnection(database, mode));
            }
            catch (Exception)
            {
                // Creating the new instance failed. Terminate ESE and remove the
                // instance information.
                instance.Term();
                this.instances.Remove(database);
                throw;
            }
        }
        /// <summary>
        /// Create a new connection to an existing instance.
        /// </summary>
        /// <param name="database">The database to connect to.</param>
        /// <param name="mode">The mode to connect to the database in.</param>
        /// <returns>A new connection to the database.</returns>
        private Connection CreateNewConnection(string database, DatabaseOpenMode mode)
        {
            Instance       instance       = this.instances[database].Instance;
            string         connectionName = Path.GetFileName(database);
            ConnectionBase connection;

            if (DatabaseOpenMode.ReadOnly == mode)
            {
                connection = new ReadOnlyConnection(instance, connectionName, database);
            }
            else
            {
                Debug.Assert(DatabaseOpenMode.ReadWrite == mode, "Unknown DatabaseOpenMode");
                connection = new ReadWriteConnection(instance, connectionName, database);
            }

            this.instances[database].Connections.Add(connection);
            connection.Disposed += this.OnConnectionClose;

            this.Tracer.TraceVerbose("created new connection '{0}'", connectionName);
            this.Tracer.TraceVerbose("database '{0}' has {1} connections", database, this.instances[database].Connections.Count);
            return(connection);
        }
Exemple #7
0
 /// <summary>
 /// Opens an existing database or creates a new one.
 /// </summary>
 /// <param name="filePath">Path to the database file. If an empty string
 /// is supplied, a temporary database is created that is not persisted.</param>
 /// <param name="mode">Open mode for the database</param>
 /// <exception cref="InstallerException">the database could not be created/opened</exception>
 /// <remarks><p>
 /// Because this constructor initiates database access, it cannot be used with a
 /// running installation.
 /// </p><p>
 /// The database object should be <see cref="InstallerHandle.Close"/>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.
 /// </p><p>
 /// A database opened in <see cref="DatabaseOpenMode.CreateDirect" /> or
 /// <see cref="DatabaseOpenMode.Direct" /> mode will be automatically commited when it is
 /// closed. However a database opened in <see cref="DatabaseOpenMode.Create" /> or
 /// <see cref="DatabaseOpenMode.Transact" /> mode must have the <see cref="Commit" /> method
 /// called before it is closed, otherwise no changes will be persisted.
 /// </p><p>
 /// Win32 MSI API:
 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiopendatabase.asp">MsiOpenDatabase</a>
 /// </p></remarks>
 public Database(string filePath, DatabaseOpenMode mode)
     : this((IntPtr) Database.Open(filePath, mode), true, filePath, mode)
 {
 }
Exemple #8
0
 /// <summary>
 /// Opens an existing database or creates a new one.
 /// </summary>
 /// <param name="filePath">Path to the database file. If an empty string
 /// is supplied, a temporary database is created that is not persisted.</param>
 /// <param name="mode">Open mode for the database</param>
 /// <exception cref="InstallerException">the database could not be created/opened</exception>
 /// <remarks><p>
 /// Because this constructor initiates database access, it cannot be used with a
 /// running installation.
 /// </p><p>
 /// The database object should be <see cref="InstallerHandle.Close"/>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.
 /// </p><p>
 /// A database opened in <see cref="DatabaseOpenMode.CreateDirect" /> or
 /// <see cref="DatabaseOpenMode.Direct" /> mode will be automatically commited when it is
 /// closed. However a database opened in <see cref="DatabaseOpenMode.Create" /> or
 /// <see cref="DatabaseOpenMode.Transact" /> mode must have the <see cref="Commit" /> method
 /// called before it is closed, otherwise no changes will be persisted.
 /// </p><p>
 /// Win32 MSI API:
 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiopendatabase.asp">MsiOpenDatabase</a>
 /// </p></remarks>
 public Database(string filePath, DatabaseOpenMode mode)
     : this((IntPtr)Database.Open(filePath, mode), true, filePath, mode)
 {
 }
Exemple #9
0
 /// <summary>
 /// Opens an existing database and returns a connection to it.
 /// </summary>
 /// <param name="database">The database to open.</param>
 /// <param name="mode">The mode to open the database in.</param>
 /// <returns>A connection to the database.</returns>
 public static Connection OpenDatabase(string database, DatabaseOpenMode mode)
 {
     return ConnectionManager().AttachDatabase(database, mode);
 }
Exemple #10
0
 /// <summary>
 /// Creates a new database from an MSI handle.
 /// </summary>
 /// <param name="handle">Native MSI database handle.</param>
 /// <param name="ownsHandle">True if the handle should be closed
 /// when the database object is disposed</param>
 /// <param name="filePath">Path of the database file, if known</param>
 /// <param name="openMode">Mode the handle was originally opened in</param>
 protected internal QDatabase(
     IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode)
     : base(handle, ownsHandle, filePath, openMode)
 {
 }
Exemple #11
0
 /// <summary>
 /// Opens an existing database or creates a new one.
 /// </summary>
 /// <param name="filePath">Path to the database file. If an empty string
 /// is supplied, a temporary database is created that is not persisted.</param>
 /// <param name="mode">Open mode for the database</param>
 /// <exception cref="InstallerException">the database could not be created/opened</exception>
 /// <remarks>
 /// 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.
 /// <para>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.</para>
 /// <para>Because this constructor initiates database access, it cannot be used with a
 /// running installation.</para>
 /// <para>The Database object should be <see cref="InstallerHandle.Close"/>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.</para>
 /// </remarks>
 public QDatabase(string filePath, DatabaseOpenMode mode)
     : base(filePath, mode)
 {
 }
Exemple #12
0
        private static int Open(string filePath, DatabaseOpenMode mode)
        {
            if (string.IsNullOrWhiteSpace(filePath))
            {
                throw new ArgumentNullException("filePath");
            }

            if (Path.GetExtension(filePath).Equals(".msp", StringComparison.Ordinal))
            {
                const int DATABASEOPENMODE_PATCH = 32;
                int patchMode = (int) mode | DATABASEOPENMODE_PATCH;
                mode = (DatabaseOpenMode) patchMode;
            }

            int hDb;
            uint ret = NativeMethods.MsiOpenDatabase(filePath, (IntPtr) mode, out hDb);
            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(
                    ret,
                    String.Format(CultureInfo.InvariantCulture, "Database=\"{0}\"", filePath));
            }
            return hDb;
        }
Exemple #13
0
 /// <summary>
 /// Opens an existing database or creates a new one.
 /// </summary>
 /// <param name="filePath">Path to the database file. If an empty string
 /// is supplied, a temporary database is created that is not persisted.</param>
 /// <param name="mode">Open mode for the database</param>
 /// <exception cref="InstallerException">the database could not be created/opened</exception>
 /// <remarks>
 /// 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.
 /// <para>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.</para>
 /// <para>Because this constructor initiates database access, it cannot be used with a
 /// running installation.</para>
 /// <para>The Database object should be <see cref="InstallerHandle.Close"/>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.</para>
 /// </remarks>
 public QDatabase(string filePath, DatabaseOpenMode mode)
     : base(filePath, mode)
 {
 }
Exemple #14
0
 /// <summary>
 /// Opens an existing database and returns a connection to it.
 /// </summary>
 /// <param name="database">The database to open.</param>
 /// <param name="mode">The mode to open the database in.</param>
 /// <returns>A connection to the database.</returns>
 public static Connection OpenDatabase(string database, DatabaseOpenMode mode)
 {
     return(ConnectionManager().AttachDatabase(database, mode));
 }
Exemple #15
0
 /// <summary>
 /// Creates a new InstallPackage object.  The file source directory and working
 /// directory are the same as the location as the package file.
 /// </summary>
 /// <param name="packagePath">Path to the install package to be created or opened</param>
 /// <param name="openMode">Open mode for the database</param>
 public InstallPackage(string packagePath, DatabaseOpenMode openMode)
     : this(packagePath, openMode, null, null)
 {
 }
Exemple #16
0
        /// <summary>
        /// Create a new connection to an existing instance.
        /// </summary>
        /// <param name="database">The database to connect to.</param>
        /// <param name="mode">The mode to connect to the database in.</param>
        /// <returns>A new connection to the database.</returns>
        private Connection CreateNewConnection(string database, DatabaseOpenMode mode)
        {
            Instance instance = this.instances[database].Instance;
            string connectionName = Path.GetFileName(database);
            ConnectionBase connection;
            if (DatabaseOpenMode.ReadOnly == mode)
            {
                connection = new ReadOnlyConnection(instance, connectionName, database);
            }
            else
            {
                Debug.Assert(DatabaseOpenMode.ReadWrite == mode, "Unknown DatabaseOpenMode");
                connection = new ReadWriteConnection(instance, connectionName, database);
            }

            this.instances[database].Connections.Add(connection);
            connection.Disposed += this.OnConnectionClose;

            this.Tracer.TraceVerbose("created new connection '{0}'", connectionName);
            this.Tracer.TraceVerbose("database '{0}' has {1} connections", database, this.instances[database].Connections.Count);
            return connection;
        }
Exemple #17
0
 /// <summary>
 /// Create a new instance and a connection on that instance.
 /// A new InstanceInfo is added to the instance dictionary.
 /// </summary>
 /// <param name="database">The database to connect to.</param>
 /// <param name="mode">The mode to connect to the database in.</param>
 /// <returns>A new Connection to the database.</returns>
 private Connection CreateNewInstanceAndConnection(string database, DatabaseOpenMode mode)
 {
     var instanceName = this.GetNewInstanceName();
     var instance = new Instance(instanceName);
     this.Tracer.TraceInfo("created instance '{0}'", instanceName);
     try
     {
         SetParametersAndInitializeInstance(database, instance);
         this.instances[database] = new InstanceInfo(instance, database);
         return this.CreateNewConnection(database, mode);
     }
     catch (Exception)
     {
         // Creating the new instance failed. Terminate ESE and remove the 
         // instance information.
         instance.Term();
         this.instances.Remove(database);
         throw;
     }
 }
Exemple #18
0
        /// <summary>
        /// Attach an existing database and return a connection to
        /// the database.
        /// </summary>
        /// <param name="database">The path to the database.</param>
        /// <param name="mode">The mode to open the database in.</param>
        /// <returns>A new connection to the database.</returns>
        public virtual Connection AttachDatabase(string database, DatabaseOpenMode mode)
        {
            database = Path.GetFullPath(database);

            lock (this.lockObject)
            {
                this.SetGlobalParameters();
                this.Tracer.TraceInfo("attach database '{0}'", database);

                if (!this.instances.ContainsKey(database))
                {
                    return this.CreateNewInstanceAndConnection(database, mode);
                }

                return this.CreateNewConnection(database, mode);
            }
        }
Exemple #19
0
 /// <summary>
 /// Creates a new database from an MSI handle.
 /// </summary>
 /// <param name="handle">Native MSI database handle.</param>
 /// <param name="ownsHandle">True if the handle should be closed
 /// when the database object is disposed</param>
 /// <param name="filePath">Path of the database file, if known</param>
 /// <param name="openMode">Mode the handle was originally opened in</param>
 protected internal QDatabase(
     IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode)
     : base(handle, ownsHandle, filePath, openMode)
 {
 }
Exemple #20
0
 /// <summary>
 /// Creates a new database from an MSI handle.
 /// </summary>
 /// <param name="handle">Native MSI database handle.</param>
 /// <param name="ownsHandle">True if the handle should be closed
 /// when the database object is disposed</param>
 /// <param name="filePath">Path of the database file, if known</param>
 /// <param name="openMode">Mode the handle was originally opened in</param>
 protected internal Database(
     IntPtr handle, bool ownsHandle, string filePath, DatabaseOpenMode openMode)
     : base(handle, ownsHandle)
 {
     this.filePath = filePath;
     this.openMode = openMode;
 }