/// <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; }
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); }
/// <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); }
/// <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) { }
/// <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) { }
/// <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); }
/// <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) { }
/// <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) { }
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; }
/// <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)); }
/// <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) { }
/// <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; }
/// <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> /// 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); } }