Example #1
0
        private ExternalUIHandler CreateProgressHandler(Request request) {
            var currentTotalTicks = -1;
            var currentProgress = 0;
            var progressDirection = 1;
            var actualPercent = 0;

            ExternalUIHandler handler = (type, message, buttons, icon, button) => {
                if (request.IsCanceled) {
                    return MessageResult.Cancel;
                }

                switch (type) {
                    case InstallMessage.Progress:
                        if (message.Length >= 2) {
                            var msg = message.Split(": ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(m => m.ToInt32(0)).ToArray();

                            switch (msg[1]) {
                                // http://msdn.microsoft.com/en-us/library/aa370354(v=VS.85).aspx
                                case 0: //Resets progress bar and sets the expected total number of ticks in the bar.
                                    currentTotalTicks = msg[3];
                                    currentProgress = 0;
                                    if (msg.Length >= 6) {
                                        progressDirection = msg[5] == 0 ? 1 : -1;
                                    }
                                    break;
                                case 1:
                                    //Provides information related to progress messages to be sent by the current action.
                                    break;
                                case 2: //Increments the progress bar.
                                    if (currentTotalTicks == -1) {
                                        break;
                                    }
                                    currentProgress += msg[3]*progressDirection;
                                    break;
                                case 3:
                                    //Enables an action (such as CustomAction) to add ticks to the expected total number of progress of the progress bar.
                                    break;
                            }
                        }

                        if (currentTotalTicks > 0) {
                            var newPercent = (currentProgress*100/currentTotalTicks);
                            if (actualPercent < newPercent) {
                                actualPercent = newPercent;
                                // request.Debug("Progress : {0}", newPercent);
                                request.Progress(_progressId, actualPercent, "installing...");
                            }
                        }
                        break;
                }

                return MessageResult.OK;
            };

            return handler;
        }
Example #2
0
 /// <summary>
 /// Enables an external user-interface handler. This external UI handler is called before the
 /// normal internal user-interface handler. The external UI handler has the option to suppress
 /// the internal UI by returning a non-zero value to indicate that it has handled the messages.
 /// </summary>
 /// <param name="uiHandler">A callback delegate that handles the UI messages</param>
 /// <param name="messageFilter">Specifies which messages to handle using the external message handler.
 /// If the external handler returns a non-zero result, then that message will not be sent to the UI,
 /// instead the message will be logged if logging has been enabled.</param>
 /// <returns>The previously set external handler, or null if there was no previously set handler</returns>
 /// <remarks><p>
 /// To restore the previous UI handler, a second call is made to SetExternalUI using the
 /// ExternalUIHandler returned by the first call to SetExternalUI and specifying
 /// <see cref="InstallLogModes.None"/> as the message filter.
 /// </p><p>
 /// The external user interface handler does not have full control over the external user
 /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to
 /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user
 /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not
 /// handled by the external user interface handler is handled by Windows Installer. The initial
 /// "Preparing to install..." dialog always appears even if the external user interface
 /// handler handles all messages.
 /// </p><p>
 /// SetExternalUI should only be called from a bootstrapping application. You cannot call
 /// it from a custom action
 /// </p><p>
 /// Win32 MSI API:
 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternalui.asp">MsiSetExternalUI</a>
 /// </p></remarks>
 public static ExternalUIHandler SetExternalUI(ExternalUIHandler uiHandler, InstallLogModes messageFilter)
 {
     NativeExternalUIHandler nativeHandler = null;
     if (uiHandler != null)
     {
         nativeHandler = new ExternalUIProxy(uiHandler).ProxyHandler;
         Installer.externalUIHandlers.Add(nativeHandler);
     }
     NativeExternalUIHandler oldNativeHandler = NativeMethods.MsiSetExternalUI(nativeHandler, (uint) messageFilter, IntPtr.Zero);
     if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIProxy)
     {
         Installer.externalUIHandlers.Remove(oldNativeHandler);
         return ((ExternalUIProxy) oldNativeHandler.Target).Handler;
     }
     else
     {
         return null;
     }
 }
Example #3
0
        /// <summary>
        /// Enables an external user-interface handler. This external UI handler is called before the
        /// normal internal user-interface handler. The external UI handler has the option to suppress
        /// the internal UI by returning a non-zero value to indicate that it has handled the messages.
        /// </summary>
        /// <param name="uiHandler">A callback delegate that handles the UI messages</param>
        /// <param name="messageFilter">Specifies which messages to handle using the external message handler.
        /// If the external handler returns a non-zero result, then that message will not be sent to the UI,
        /// instead the message will be logged if logging has been enabled.</param>
        /// <returns>The previously set external handler, or null if there was no previously set handler</returns>
        /// <remarks><p>
        /// To restore the previous UI handler, a second call is made to SetExternalUI using the
        /// ExternalUIHandler returned by the first call to SetExternalUI and specifying
        /// <see cref="InstallLogModes.None"/> as the message filter.
        /// </p><p>
        /// The external user interface handler does not have full control over the external user
        /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to
        /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user
        /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not
        /// handled by the external user interface handler is handled by Windows Installer. The initial
        /// "Preparing to install..." dialog always appears even if the external user interface
        /// handler handles all messages.
        /// </p><p>
        /// SetExternalUI should only be called from a bootstrapping application. You cannot call
        /// it from a custom action
        /// </p><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternalui.asp">MsiSetExternalUI</a>
        /// </p></remarks>
        public static ExternalUIHandler SetExternalUI(ExternalUIHandler uiHandler, InstallLogModes messageFilter)
        {
            NativeExternalUIHandler nativeHandler = null;

            if (uiHandler != null)
            {
                nativeHandler = new ExternalUIProxy(uiHandler).ProxyHandler;
                Installer.externalUIHandlers.Add(nativeHandler);
            }
            NativeExternalUIHandler oldNativeHandler = NativeMethods.MsiSetExternalUI(nativeHandler, (uint)messageFilter, IntPtr.Zero);

            if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIProxy)
            {
                Installer.externalUIHandlers.Remove(oldNativeHandler);
                return(((ExternalUIProxy)oldNativeHandler.Target).Handler);
            }
            else
            {
                return(null);
            }
        }
Example #4
0
 internal ExternalUIProxy(ExternalUIHandler handler)
 {
     this.handler = handler;
 }
Example #5
0
 internal ExternalUIProxy(ExternalUIHandler handler)
 {
     this.handler = handler;
 }
        public void CustomActionTest1()
        {
            InstallLogModes logEverything =
                InstallLogModes.FatalExit |
                InstallLogModes.Error |
                InstallLogModes.Warning |
                InstallLogModes.User |
                InstallLogModes.Info |
                InstallLogModes.ResolveSource |
                InstallLogModes.OutOfDiskSpace |
                InstallLogModes.ActionStart |
                InstallLogModes.ActionData |
                InstallLogModes.CommonData |
                InstallLogModes.Progress |
                InstallLogModes.Initialize |
                InstallLogModes.Terminate |
                InstallLogModes.ShowDialog;

            Installer.SetInternalUI(InstallUIOptions.Silent);
            ExternalUIHandler prevHandler = Installer.SetExternalUI(
                WindowsInstallerTest.ExternalUILogger, logEverything);

            try
            {
                string[] customActions = new string[] { "SampleCA1", "SampleCA2" };
                #if DEBUG
                string caDir = @"..\..\..\..\..\build\debug\x86\";
                #else
                string caDir = @"..\..\..\..\..\build\ship\x86\";
                #endif
                caDir = Path.GetFullPath(caDir);
                string caFile    = "WixToolset.Dtf.Samples.ManagedCA.dll";
                string caProduct = "CustomActionTest.msi";

                this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, false);

                Exception caughtEx = null;
                try
                {
                    Installer.InstallProduct(caProduct, String.Empty);
                }
                catch (Exception ex) { caughtEx = ex; }
                Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException),
                                        "Exception thrown while installing product: " + caughtEx);

                string arch  = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
                string arch2 = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432");
                if (arch == "AMD64" || arch2 == "AMD64")
                {
                    caDir = caDir.Replace("x86", "x64");

                    this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, true);

                    caughtEx = null;
                    try
                    {
                        Installer.InstallProduct(caProduct, String.Empty);
                    }
                    catch (Exception ex) { caughtEx = ex; }
                    Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException),
                                            "Exception thrown while installing 64bit product: " + caughtEx);
                }
            }
            finally
            {
                Installer.SetExternalUI(prevHandler, InstallLogModes.None);
            }
        }
Example #7
0
        [Ignore] // Requires elevation.
        public void InstallerTransactTwoProducts()
        {
            string dbFile1 = "InstallerTransactProduct1.msi";
            string dbFile2 = "InstallerTransactProduct2.msi";
            string productCode1;
            string productCode2;

            using (Database db1 = new Database(dbFile1, DatabaseOpenMode.CreateDirect))
            {
                WindowsInstallerUtils.InitializeProductDatabase(db1);
                WindowsInstallerUtils.CreateTestProduct(db1);

                productCode1 = db1.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];

                db1.Commit();
            }

            using (Database db2 = new Database(dbFile2, DatabaseOpenMode.CreateDirect))
            {
                WindowsInstallerUtils.InitializeProductDatabase(db2);
                WindowsInstallerUtils.CreateTestProduct(db2);

                productCode2 = db2.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];

                db2.Commit();
            }

            ProductInstallation installation1 = new ProductInstallation(productCode1);
            ProductInstallation installation2 = new ProductInstallation(productCode2);

            Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed before starting.");
            Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed before starting.");

            Installer.SetInternalUI(InstallUIOptions.Silent);
            ExternalUIHandler prevHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUILogger,
                                                                    InstallLogModes.FatalExit |
                                                                    InstallLogModes.Error |
                                                                    InstallLogModes.Warning |
                                                                    InstallLogModes.User |
                                                                    InstallLogModes.Info |
                                                                    InstallLogModes.ResolveSource |
                                                                    InstallLogModes.OutOfDiskSpace |
                                                                    InstallLogModes.ActionStart |
                                                                    InstallLogModes.ActionData |
                                                                    InstallLogModes.CommonData |
                                                                    InstallLogModes.Progress |
                                                                    InstallLogModes.Initialize |
                                                                    InstallLogModes.Terminate |
                                                                    InstallLogModes.ShowDialog);

            Assert.IsNull(prevHandler, "Checking that returned previous UI handler is null.");

            Transaction transaction = new Transaction("TestInstallTransaction", TransactionAttributes.None);

            Exception caughtEx = null;

            try
            {
                Installer.InstallProduct(dbFile1, String.Empty);
            }
            catch (Exception ex) { caughtEx = ex; }
            Assert.IsNull(caughtEx, "Exception thrown while installing product 1: " + caughtEx);

            Console.WriteLine();
            Console.WriteLine("===================================================================");
            Console.WriteLine();

            try
            {
                Installer.InstallProduct(dbFile2, String.Empty);
            }
            catch (Exception ex) { caughtEx = ex; }
            Assert.IsNull(caughtEx, "Exception thrown while installing product 2: " + caughtEx);

            transaction.Commit();
            transaction.Close();

            prevHandler = Installer.SetExternalUI(prevHandler, InstallLogModes.None);
            Assert.AreEqual <ExternalUIHandler>(WindowsInstallerTest.ExternalUILogger, prevHandler, "Checking that previously-set UI handler is returned.");

            Assert.IsTrue(installation1.IsInstalled, "Checking that product 1 is installed.");
            Assert.IsTrue(installation2.IsInstalled, "Checking that product 2 is installed.");

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("===================================================================");
            Console.WriteLine("===================================================================");
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();

            ExternalUIRecordHandler prevRecHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUIRecordLogger,
                                                                             InstallLogModes.FatalExit |
                                                                             InstallLogModes.Error |
                                                                             InstallLogModes.Warning |
                                                                             InstallLogModes.User |
                                                                             InstallLogModes.Info |
                                                                             InstallLogModes.ResolveSource |
                                                                             InstallLogModes.OutOfDiskSpace |
                                                                             InstallLogModes.ActionStart |
                                                                             InstallLogModes.ActionData |
                                                                             InstallLogModes.CommonData |
                                                                             InstallLogModes.Progress |
                                                                             InstallLogModes.Initialize |
                                                                             InstallLogModes.Terminate |
                                                                             InstallLogModes.ShowDialog);

            Assert.IsNull(prevRecHandler, "Checking that returned previous UI record handler is null.");

            transaction = new Transaction("TestUninstallTransaction", TransactionAttributes.None);

            try
            {
                Installer.InstallProduct(dbFile1, "REMOVE=All");
            }
            catch (Exception ex) { caughtEx = ex; }
            Assert.IsNull(caughtEx, "Exception thrown while removing product 1: " + caughtEx);

            try
            {
                Installer.InstallProduct(dbFile2, "REMOVE=All");
            }
            catch (Exception ex) { caughtEx = ex; }
            Assert.IsNull(caughtEx, "Exception thrown while removing product 2: " + caughtEx);

            transaction.Commit();
            transaction.Close();

            Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed after removing.");
            Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed after removing.");

            prevRecHandler = Installer.SetExternalUI(prevRecHandler, InstallLogModes.None);
            Assert.AreEqual <ExternalUIRecordHandler>(WindowsInstallerTest.ExternalUIRecordLogger, prevRecHandler, "Checking that previously-set UI record handler is returned.");
        }