Ejemplo n.º 1
0
        /// <summary>
        /// Sets a record stream field from a Stream object. Stream data cannot be inserted into temporary fields.
        /// </summary>
        /// <param name="field">Specifies the field of the Record to set.</param>
        /// <param name="stream">Specifies the stream data.</param>
        /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the
        /// number of fields in the Record.</exception>
        /// <remarks><p>
        /// The stream persists if the Record is inserted into the Database and the Database is committed.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordsetstream.asp">MsiRecordsetStream</a>
        /// </p></remarks>
        public void SetStream(int field, Stream stream)
        {
            this.CheckRange(field);

            if (stream == null)
            {
                uint ret = RemotableNativeMethods.MsiRecordSetStream((int)this.Handle, (uint)field, null);
                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }
            }
            else
            {
                Stream writeStream = null;
                string tempPath    = Path.GetTempFileName();
                try
                {
                    writeStream = new FileStream(tempPath, FileMode.Truncate, FileAccess.Write);
                    byte[] buf = new byte[512];
                    int    count;
                    while ((count = stream.Read(buf, 0, buf.Length)) > 0)
                    {
                        writeStream.Write(buf, 0, count);
                    }
                    writeStream.Close();
                    writeStream = null;

                    uint ret = RemotableNativeMethods.MsiRecordSetStream((int)this.Handle, (uint)field, tempPath);
                    if (ret != 0)
                    {
                        throw InstallerException.ExceptionFromReturnCode(ret);
                    }
                }
                finally
                {
                    if (writeStream != null)
                    {
                        writeStream.Close();
                    }
                    if (File.Exists(tempPath))
                    {
                        try
                        {
                            File.Delete(tempPath);
                        }
                        catch (IOException)
                        {
                            if (this.view != null)
                            {
                                this.view.Database.DeleteOnClose(tempPath);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public static void AdvertiseScript(string scriptFile, int flags, bool removeItems)
        {
            uint ret = NativeMethods.MsiAdvertiseScript(scriptFile, (uint)flags, IntPtr.Zero, removeItems);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Reinstalls a product.
        /// </summary>
        /// <param name="product">Product code for the product to be reinstalled</param>
        /// <param name="reinstallModes">Reinstall modes</param>
        /// <exception cref="InstallCanceledException">the user exited the installation</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msireinstallproduct.asp">MsiReinstallProduct</a>
        /// </p></remarks>
        public static void ReinstallProduct(string product, ReinstallModes reinstallModes)
        {
            uint ret = NativeMethods.MsiReinstallProduct(product, (uint)reinstallModes);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// [MSI 3.1] Migrates a user's application configuration data to a new SID.
        /// </summary>
        /// <param name="oldSid">Previous user SID that data is to be migrated from</param>
        /// <param name="newSid">New user SID that data is to be migrated to</param>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msinotifysidchange.asp">MsiNotifySidChange</a>
        /// </p></remarks>
        public static void NotifySidChange(string oldSid, string newSid)
        {
            uint ret = NativeMethods.MsiNotifySidChange(oldSid, newSid);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Installs files that are unexpectedly missing.
        /// </summary>
        /// <param name="product">Product code for the product that owns the component to be installed</param>
        /// <param name="component">Component to be installed</param>
        /// <param name="installState">Specifies the way the component should be installed.</param>
        /// <exception cref="InstallCanceledException">the user exited the installation</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiinstallmissingcomponent.asp">MsiInstallMissingComponent</a>
        /// </p></remarks>
        public static void InstallMissingComponent(string product, string component, InstallState installState)
        {
            uint ret = NativeMethods.MsiInstallMissingComponent(product, component, (int)installState);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Installs files that are unexpectedly missing.
        /// </summary>
        /// <param name="product">Product code for the product that owns the file to be installed</param>
        /// <param name="file">File to be installed</param>
        /// <exception cref="InstallCanceledException">the user exited the installation</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiinstallmissingfile.asp">MsiInstallMissingFile</a>
        /// </p></remarks>
        public static void InstallMissingFile(string product, string file)
        {
            uint ret = NativeMethods.MsiInstallMissingFile(product, file);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Enables logging of the selected message type for all subsequent install sessions in
        /// the current process space.
        /// </summary>
        /// <param name="logModes">One or more mode flags specifying the type of messages to log</param>
        /// <param name="logFile">Full path to the log file.  A null path disables logging,
        /// in which case the logModes paraneter is ignored.</param>
        /// <param name="append">If true, the log lines will be appended to any existing file content.
        /// If false, the log file will be truncated if it exists.  The default is false.</param>
        /// <param name="flushEveryLine">If true, the log will be flushed after every line.
        /// If false, the log will be flushed every 20 lines.  The default is true.</param>
        /// <exception cref="ArgumentException">an invalid log mode was specified</exception>
        /// <remarks><p>
        /// This method takes effect on any new installation processes.  Calling this
        /// method from within a custom action will not start logging for that installation.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienablelog.asp">MsiEnableLog</a>
        /// </p></remarks>
        public static void EnableLog(InstallLogModes logModes, string logFile, bool append, bool flushEveryLine)
        {
            uint ret = NativeMethods.MsiEnableLog((uint)logModes, logFile, (append ? (uint)1 : 0) + (flushEveryLine ? (uint)2 : 0));

            if (ret != 0 && ret != (uint)NativeMethods.Error.FILE_INVALID)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Formats and writes the previously stored properties into the standard summary information stream.
        /// </summary>
        /// <exception cref="InstallerException">The stream cannot be successfully written.</exception>
        /// <remarks><p>
        /// This method may only be called once after all the property values have been set. Properties may
        /// still be read after the stream is written.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfopersist.asp">MsiSummaryInfoPersist</a>
        /// </p></remarks>
        public void Persist()
        {
            uint ret = NativeMethods.MsiSummaryInfoPersist((int)this.Handle);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Processes an advertise script file into the specified locations.
        /// </summary>
        /// <param name="scriptFile">Path to a script file generated by
        /// <see cref="GenerateAdvertiseScript(string,string,string,int,ProcessorArchitecture,bool)"/></param>
        /// <param name="iconFolder">An optional path to a folder in which advertised icon files and transform
        /// files are located. If this parameter is null, no icon or transform files are written.</param>
        /// <param name="shortcuts">True if shortcuts should be created</param>
        /// <param name="removeItems">True if specified items are to be removed instead of created</param>
        /// <remarks><p>
        /// The process calling this function must be running under the LocalSystem account. To advertise an
        /// application for per-user installation to a targeted user, the thread that calls this function must
        /// impersonate the targeted user. If the thread calling this function is not impersonating a targeted
        /// user, the application is advertised to all users for installation with elevated privileges.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiprocessadvertisescript.asp">MsiProcessAdvertiseScript</a>
        /// </p></remarks>
        public static void ProcessAdvertiseScript(string scriptFile, string iconFolder, bool shortcuts, bool removeItems)
        {
            uint ret = NativeMethods.MsiProcessAdvertiseScript(scriptFile, iconFolder, IntPtr.Zero, shortcuts, removeItems);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Sets all fields in a record to null.
        /// </summary>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordcleardata.asp">MsiRecordClearData</a>
        /// </p></remarks>
        public void Clear()
        {
            uint ret = RemotableNativeMethods.MsiRecordClearData((int)this.Handle);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Opens an installer package for use with functions that access the product database and install engine,
        /// returning an Session object.
        /// </summary>
        /// <param name="packagePath">Path to the package</param>
        /// <param name="ignoreMachineState">Specifies whether or not the create a Session object that ignores the
        /// computer state and that is incapable of changing the current computer state. A value of false yields
        /// the normal behavior.  A value of true creates a "safe" Session object that cannot change of the current
        /// machine state.</param>
        /// <returns>A Session object allowing access to the product database and install engine</returns>
        /// <exception cref="InstallerException">The product could not be opened</exception>
        /// <exception cref="InstallerException">The installer configuration data is corrupt</exception>
        /// <remarks><p>
        /// Note that only one Session object can be opened by a single process. OpenPackage cannot be used in a
        /// custom action because the active installation is the only session allowed.
        /// </p><p>
        /// A "safe" Session object ignores the current computer state when opening the package and prevents
        /// changes to the current computer state.
        /// </p><p>
        /// The Session object should be <see cref="InstallerHandle.Close"/>d after use.
        /// 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>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiopenpackage.asp">MsiOpenPackage</a>,
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiopenpackageex.asp">MsiOpenPackageEx</a>
        /// </p></remarks>
        public static Session OpenPackage(string packagePath, bool ignoreMachineState)
        {
            int  sessionHandle;
            uint ret = NativeMethods.MsiOpenPackageEx(packagePath, ignoreMachineState ? (uint)1 : 0, out sessionHandle);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
            return(new Session((IntPtr)sessionHandle, true));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Sets the value of a field to an integer.
        /// </summary>
        /// <param name="field">Specifies the field to set.</param>
        /// <param name="value">new value of the field</param>
        /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the
        /// number of fields in the Record.</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordsetinteger.asp">MsiRecordSetInteger</a>
        /// </p></remarks>
        /// <seealso cref="SetNullableInteger(int,int?)"/>
        public void SetInteger(int field, int value)
        {
            this.CheckRange(field);

            uint ret = RemotableNativeMethods.MsiRecordSetInteger((int)this.Handle, (uint)field, value);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Obtains and stores the user information and product ID from an installation wizard.
 /// </summary>
 /// <remarks><p>
 /// This method is typically called by an application during the first run of the application. The application
 /// first gets the <see cref="ProductInstallation.ProductId"/> or <see cref="ProductInstallation.RegOwner"/>.
 /// If those properties are missing, the application calls CollectUserInfo.
 /// CollectUserInfo opens the product's installation package and invokes a wizard sequence that collects
 /// user information. Upon completion of the sequence, user information is registered. Since this API requires
 /// an authored user interface, the user interface level should be set to full by calling
 /// <see cref="Installer.SetInternalUI(InstallUIOptions)"/> as <see cref="InstallUIOptions.Full"/>.
 /// </p><p>
 /// The CollectUserInfo method invokes a FirstRun dialog from the product installation database.
 /// </p><p>
 /// Win32 MSI API:
 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msicollectuserinfo.asp">MsiCollectUserInfo</a>
 /// </p></remarks>
 public void CollectUserInfo()
 {
     if (this.properties == null)
     {
         uint ret = NativeMethods.MsiCollectUserInfo(this.InstallationCode);
         if (ret != 0)
         {
             throw InstallerException.ExceptionFromReturnCode(ret);
         }
     }
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Sets the install level for the current installation to a specified value and
        /// recalculates the Select and Installed states for all features in the Feature
        /// table. Also sets the Action state of each component in the Component table based
        /// on the new level.
        /// </summary>
        /// <param name="installLevel">New install level</param>
        /// <exception cref="InvalidHandleException">the Session handle is invalid</exception>
        /// <remarks><p>
        /// The SetInstallLevel method sets the following:<list type="bullet">
        /// <item><description>The installation level for the current installation to a specified value</description></item>
        /// <item><description>The Select and Installed states for all features in the Feature table</description></item>
        /// <item><description>The Action state of each component in the Component table, based on the new level</description></item>
        /// </list>
        /// If 0 or a negative number is passed in the ilnstallLevel parameter,
        /// the current installation level does not change, but all features are still
        /// updated based on the current installation level.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetinstalllevel.asp">MsiSetInstallLevel</a>
        /// </p></remarks>
        public void SetInstallLevel(int installLevel)
        {
            this.ValidateSessionAccess();

            uint ret = RemotableNativeMethods.MsiSetInstallLevel((int)this.Handle, installLevel);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Enumerates the source media in the source list of the patch or product installation.
        /// </summary>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistenummediadisks.asp">MsiSourceListEnumMediaDisks</a>
        /// </p></remarks>
        public IEnumerator <MediaDisk> GetEnumerator()
        {
            uint          diskId;
            StringBuilder volumeBuf     = new StringBuilder(40);
            uint          volumeBufSize = (uint)volumeBuf.Capacity;
            StringBuilder promptBuf     = new StringBuilder(80);
            uint          promptBufSize = (uint)promptBuf.Capacity;

            for (uint i = 0; true; i++)
            {
                uint ret = NativeMethods.MsiSourceListEnumMediaDisks(
                    this.installation.InstallationCode,
                    this.installation.UserSid,
                    this.installation.Context,
                    (uint)this.installation.InstallationType,
                    i,
                    out diskId,
                    volumeBuf,
                    ref volumeBufSize,
                    promptBuf,
                    ref promptBufSize);

                if (ret == (uint)NativeMethods.Error.MORE_DATA)
                {
                    volumeBuf.Capacity = (int)++volumeBufSize;
                    promptBuf.Capacity = (int)++promptBufSize;

                    ret = NativeMethods.MsiSourceListEnumMediaDisks(
                        this.installation.InstallationCode,
                        this.installation.UserSid,
                        this.installation.Context,
                        (uint)this.installation.InstallationType,
                        i,
                        out diskId,
                        volumeBuf,
                        ref volumeBufSize,
                        promptBuf,
                        ref promptBufSize);
                }

                if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }

                yield return(new MediaDisk((int)diskId, volumeBuf.ToString(), promptBuf.ToString()));
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Gets or sets the string value of a named installer property, as maintained by the
        /// Session object in the in-memory Property table, or, if it is prefixed with a percent
        /// sign (%), the value of a system environment variable for the current process.
        /// </summary>
        /// <exception cref="InvalidHandleException">the Session handle is invalid</exception>
        /// <remarks><p>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetproperty.asp">MsiGetProperty</a>,
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetproperty.asp">MsiSetProperty</a>
        /// </p></remarks>
        public string this[string property]
        {
            get
            {
                if (String.IsNullOrEmpty(property))
                {
                    throw new ArgumentNullException("property");
                }

                if (!this.sessionAccessValidated &&
                    !Session.NonImmediatePropertyNames.Contains(property))
                {
                    this.ValidateSessionAccess();
                }

                StringBuilder buf     = new StringBuilder();
                uint          bufSize = 0;
                uint          ret     = RemotableNativeMethods.MsiGetProperty((int)this.Handle, property, buf, ref bufSize);
                if (ret == (uint)NativeMethods.Error.MORE_DATA)
                {
                    buf.Capacity = (int)++bufSize;
                    ret          = RemotableNativeMethods.MsiGetProperty((int)this.Handle, property, buf, ref bufSize);
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }
                return(buf.ToString());
            }

            set
            {
                if (String.IsNullOrEmpty(property))
                {
                    throw new ArgumentNullException("property");
                }

                this.ValidateSessionAccess();

                if (value == null)
                {
                    value = String.Empty;
                }

                uint ret = RemotableNativeMethods.MsiSetProperty((int)this.Handle, property, value);
                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }
            }
        }
Ejemplo n.º 17
0
        private static void CheckInstallResult(uint ret)
        {
            switch (ret)
            {
            case (uint)NativeMethods.Error.SUCCESS: break;

            case (uint)NativeMethods.Error.SUCCESS_REBOOT_REQUIRED: Installer.rebootRequired = true; break;

            case (uint)NativeMethods.Error.SUCCESS_REBOOT_INITIATED: Installer.rebootInitiated = true; break;

            default: throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 18
0
        private static IntPtr[] Begin(string transactionName, TransactionAttributes attributes)
        {
            int    hTransaction;
            IntPtr hChangeOfOwnerEvent;
            uint   ret = NativeMethods.MsiBeginTransaction(transactionName, (int)attributes, out hTransaction, out hChangeOfOwnerEvent);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }

            return(new IntPtr[] { (IntPtr)hTransaction, hChangeOfOwnerEvent });
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Forces the installer to search the source list for a valid
        /// source the next time a source is required. For example, when the
        /// installer performs an installation or reinstallation, or when it
        /// requires the path for a component that is set to run from source.
        /// </summary>
        /// <remarks><p>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistforceresolution.asp">MsiSourceListForceResolution</a>,
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistforceresolutionex.asp">MsiSourceListForceResolutionEx</a>
        /// </p></remarks>
        public void ForceResolution()
        {
            uint ret = NativeMethods.MsiSourceListForceResolutionEx(
                this.installation.InstallationCode,
                this.installation.UserSid,
                this.installation.Context,
                (uint)this.installation.InstallationType);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Removes all source media from the list.
        /// </summary>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistclearallex.asp">MsiSourceListClearAllEx</a>
        /// </p></remarks>
        public void Clear()
        {
            uint ret = NativeMethods.MsiSourceListClearAllEx(
                this.installation.InstallationCode,
                this.installation.UserSid,
                this.installation.Context,
                (uint)NativeMethods.SourceType.Media | (uint)this.installation.InstallationType);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Apply a transform to the database, specifying error conditions to suppress.
        /// </summary>
        /// <param name="transformFile">Path to the transform file</param>
        /// <param name="errorConditionsToSuppress">Error conditions that are to be suppressed</param>
        /// <exception cref="InstallerException">the transform could not be applied</exception>
        /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseapplytransform.asp">MsiDatabaseApplyTransform</a>
        /// </p></remarks>
        public void ApplyTransform(string transformFile, TransformErrors errorConditionsToSuppress)
        {
            if (String.IsNullOrEmpty(transformFile))
            {
                throw new ArgumentNullException("transformFile");
            }

            uint ret = NativeMethods.MsiDatabaseApplyTransform((int)this.Handle, transformFile, (int)errorConditionsToSuppress);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Enumerates product installations based on certain criteria.
        /// </summary>
        /// <param name="productCode">ProductCode (GUID) of the product instances to be enumerated. Only
        /// instances of products within the scope of the context specified by the
        /// <paramref name="userSid"/> and <paramref name="context"/> parameters will be
        /// enumerated. This parameter may be set to null to enumerate all products in the specified
        /// context.</param>
        /// <param name="userSid">Specifies a security identifier (SID) that restricts the context
        /// of enumeration. A SID value other than s-1-1-0 is considered a user SID and restricts
        /// enumeration to the current user or any user in the system. The special SID string
        /// s-1-1-0 (Everyone) specifies enumeration across all users in the system. This parameter
        /// can be set to null to restrict the enumeration scope to the current user. When
        /// <paramref name="context"/> is set to the machine context only,
        /// <paramref name="userSid"/> must be null.</param>
        /// <param name="context">Specifies the user context.</param>
        /// <returns>An enumeration of product objects for enumerated product instances.</returns>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumproductsex.asp">MsiEnumProductsEx</a>
        /// </p></remarks>
        public static IEnumerable <ProductInstallation> GetProducts(
            string productCode, string userSid, UserContexts context)
        {
            StringBuilder buf = new StringBuilder(40);
            UserContexts  targetContext;
            StringBuilder targetSidBuf = new StringBuilder(40);

            for (uint i = 0; ; i++)
            {
                uint targetSidBufSize = (uint)targetSidBuf.Capacity;
                uint ret = NativeMethods.MsiEnumProductsEx(
                    productCode,
                    userSid,
                    context,
                    i,
                    buf,
                    out targetContext,
                    targetSidBuf,
                    ref targetSidBufSize);
                if (ret == (uint)NativeMethods.Error.MORE_DATA)
                {
                    targetSidBuf.Capacity = (int)++targetSidBufSize;
                    ret = NativeMethods.MsiEnumProductsEx(
                        productCode,
                        userSid,
                        context,
                        i,
                        buf,
                        out targetContext,
                        targetSidBuf,
                        ref targetSidBufSize);
                }

                if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }

                yield return(new ProductInstallation(
                                 buf.ToString(),
                                 targetSidBuf.ToString(),
                                 targetContext));
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Finalizes the persistent form of the database. All persistent data is written
        /// to the writeable database, and no temporary columns or rows are written.
        /// </summary>
        /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
        /// <remarks><p>
        /// For a database open in <see cref="DatabaseOpenMode.ReadOnly"/> mode, this method has no effect.
        /// </p><p>
        /// For a database open in <see cref="DatabaseOpenMode.CreateDirect" /> or <see cref="DatabaseOpenMode.Direct" />
        /// mode, it is not necessary to call this method because the database will be automatically committed
        /// when it is closed. However this method may be called at any time to persist the current state of tables
        /// loaded into memory.
        /// </p><p>
        /// For a database open in <see cref="DatabaseOpenMode.Create" /> or <see cref="DatabaseOpenMode.Transact" />
        /// mode, no changes will be persisted until this method is called. If the database object is closed without
        /// calling this method, the database file remains unmodified.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabasecommit.asp">MsiDatabaseCommit</a>
        /// </p></remarks>
        public void Commit()
        {
            if (this.summaryInfo != null && !this.summaryInfo.IsClosed)
            {
                this.summaryInfo.Persist();
                this.summaryInfo.Close();
                this.summaryInfo = null;
            }
            uint ret = NativeMethods.MsiDatabaseCommit((int)this.Handle);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 24
0
        public void Execute(Record executeParams)
        {
            uint ret = RemotableNativeMethods.MsiViewExecute(
                (int)this.Handle,
                (executeParams != null ? (int)executeParams.Handle : 0));

            if (ret == (uint)NativeMethods.Error.BAD_QUERY_SYNTAX)
            {
                throw new BadQuerySyntaxException(this.sql);
            }
            else if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Adds or updates a disk of the media source for the product or patch.
        /// </summary>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistaddmediadisk.asp">MsiSourceListAddMediaDisk</a>
        /// </p></remarks>
        public void Add(MediaDisk item)
        {
            uint ret = NativeMethods.MsiSourceListAddMediaDisk(
                this.installation.InstallationCode,
                this.installation.UserSid,
                this.installation.Context,
                (uint)this.installation.InstallationType,
                (uint)item.DiskId,
                item.VolumeLabel,
                item.DiskPrompt);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Removes a specified disk from the set of registered disks.
        /// </summary>
        /// <param name="diskId">ID of the disk to remove</param>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistclearmediadisk.asp">MsiSourceListClearMediaDisk</a>
        /// </p></remarks>
        public bool Remove(int diskId)
        {
            uint ret = NativeMethods.MsiSourceListClearMediaDisk(
                this.installation.InstallationCode,
                this.installation.UserSid,
                this.installation.Context,
                (uint)this.installation.InstallationType,
                (uint)diskId);

            if (ret != 0)
            {
                // TODO: Figure out when to return false.
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
            return(true);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Sets a record stream field from a file. Stream data cannot be inserted into temporary fields.
        /// </summary>
        /// <param name="field">Specifies the field of the Record to set.</param>
        /// <param name="filePath">Specifies the path to the file containing the stream.</param>
        /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the
        /// number of fields in the Record.</exception>
        /// <remarks><p>
        /// The contents of the specified file are read into a stream object. The stream persists if
        /// the Record is inserted into the Database and the Database is committed.
        /// </p><p>
        /// To reset the stream to its beginning you must pass in null for filePath.
        /// Do not pass an empty string, "", to reset the stream.
        /// </p><p>
        /// Setting a stream with this method is more efficient than setting a field to a
        /// FileStream object.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordsetstream.asp">MsiRecordsetStream</a>
        /// </p></remarks>
        public void SetStream(int field, string filePath)
        {
            this.CheckRange(field);

            if (String.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath");
            }

            uint ret = RemotableNativeMethods.MsiRecordSetStream((int)this.Handle, (uint)field, filePath);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Executes an action sequence described in the specified table.
        /// </summary>
        /// <param name="sequenceTable">Name of the table containing the action sequence.</param>
        /// <exception cref="InvalidHandleException">the Session handle is invalid</exception>
        /// <exception cref="InstallCanceledException">the user exited the installation</exception>
        /// <remarks><p>
        /// This method queries the specified table, ordering the actions by the numbers in the Sequence column.
        /// For each row retrieved, an action is executed, provided that any supplied condition expression does
        /// not evaluate to FALSE.
        /// </p><p>
        /// An action sequence containing any actions that update the system, such as the InstallFiles and
        /// WriteRegistryValues actions, cannot be run by calling DoActionSequence. The exception to this rule is if
        /// DoActionSequence is called from a custom action that is scheduled in the InstallExecuteSequence table
        /// between the InstallInitialize and InstallFinalize actions. Actions that do not update the system, such
        /// as AppSearch or CostInitialize, can be called.
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisequence.asp">MsiSequence</a>
        /// </p></remarks>
        public void DoActionSequence(string sequenceTable)
        {
            if (String.IsNullOrEmpty(sequenceTable))
            {
                throw new ArgumentNullException("sequenceTable");
            }

            this.ValidateSessionAccess();

            uint ret = RemotableNativeMethods.MsiSequence((int)this.Handle, sequenceTable, 0);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Checks to see if sufficient disk space is present for the current installation.
        /// </summary>
        /// <returns>True if there is sufficient disk space; false otherwise.</returns>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiverifydiskspace.asp">MsiVerifyDiskSpace</a>
        /// </p></remarks>
        public bool VerifyDiskSpace()
        {
            this.ValidateSessionAccess();

            uint ret = RemotableNativeMethods.MsiVerifyDiskSpace((int)this.Handle);

            if (ret == (uint)NativeMethods.Error.DISK_FULL)
            {
                return(false);
            }
            else if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }
            return(true);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Makes the current process the owner of the multi-package installation transaction.
        /// </summary>
        /// <param name="attributes">Select optional behavior when joining the transaction.</param>
        /// <exception cref="InvalidHandleException">The transaction handle is not valid.</exception>
        /// <exception cref="InstallerException">The transaction could not be joined.</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msijointransaction.asp">MsiJoinTransaction</a>
        /// </p></remarks>
        public void Join(TransactionAttributes attributes)
        {
            IntPtr hChangeOfOwnerEvent;
            uint   ret = NativeMethods.MsiJoinTransaction((int)this.Handle, (int)attributes, out hChangeOfOwnerEvent);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }

            this.ownerChangeEvent = hChangeOfOwnerEvent;
            if (this.ownerChangeEvent != IntPtr.Zero && this.ownerChangeListeners.Count >= 1)
            {
                new Thread(this.WaitForOwnerChange).Start();
            }
        }