Beispiel #1
0
        private void PrepMsi(string msiPath, string dstDir, PaintDotNet.SystemLayer.ProcessorArchitecture platform, Hashtable msiProperties)
        {
            string dstMsiExt  = "." + platform.ToString().ToLower() + ".msi";
            string dstMsiName = Path.ChangeExtension(msiPath, dstMsiExt);

            if (!Directory.Exists(dstDir))
            {
                Directory.CreateDirectory(dstDir);
            }

            string dstMsiPath = Path.Combine(dstDir, dstMsiName);

            this.statusText.Text = dstMsiName;
            WizardHost.Update();

            File.Copy(msiPath, dstMsiPath, true);
            ++this.progressBar.Value;

            Msi.SetMsiTargetPlatform(dstMsiPath, platform);
            ++this.progressBar.Value;

            foreach (string key in msiProperties.Keys)
            {
                string value = (string)msiProperties[key];
                Msi.SetMsiProperties(dstMsiPath, Msi.PropertyTable, new string[1] {
                    key
                }, new string[1] {
                    value
                });
                ++this.progressBar.Value;
            }

            ++this.progressBar.Value;
        }
        private void DoInstallation()
        {
            WizardHost.SetNextEnabled(false);
            WizardHost.SetBackEnabled(false);
            WizardHost.SetCancelEnabled(false);

            IntPtr hWnd = this.Handle;

            uint result = NativeMethods.MsiSetInternalUI(
                NativeConstants.INSTALLUILEVEL_BASIC | NativeConstants.INSTALLUILEVEL_HIDECANCEL,
                ref hWnd);

            // value of result is discarded

            string ourDir = PdnInfo.GetApplicationDir();
            string originalPackagePath = Path.Combine(ourDir, msiName);
            string targetDir           = WizardHost.GetMsiProperty(PropertyNames.TargetDir, null);
            string stagingDir          = Path.Combine(targetDir, stagingDirName);

            // The 'old' target dir is read from the registry.
            // This way if they are reinstalling to a new directory, we will propertly uninstall and cleanup
            // from the old directory.
            // The 'old' target dir defaults to the 'new' target dir (in case of new installation)
            string oldTargetDir  = WizardHost.GetMsiProperty(PropertyNames.TargetDir, targetDir, true);
            string oldStagingDir = Path.Combine(oldTargetDir, stagingDirName);

            // Uninstallers should skip certain parts of cleanup when we're going to turn around
            // and install a newer version right away
            WizardHost.SetMsiProperty(PropertyNames.SkipCleanup, "0");

            // Uninstall anything already in the staging directory (should only be the previous version)
            if (Directory.Exists(oldStagingDir))
            {
                this.infoText.Text = this.uninstallingText;
                WizardHost.SetMsiProperty(PropertyNames.SkipCleanup, "1");

                foreach (string filePath in Directory.GetFiles(oldStagingDir, "*.msi"))
                {
                    uint result2 = NativeMethods.MsiInstallProduct(
                        filePath,
                        "REMOVE=ALL " +
                        PropertyNames.SkipCleanup + "=1 " +
                        PropertyNames.DesktopShortcut + "=" + WizardHost.GetMsiProperty(PropertyNames.DesktopShortcut, "1"));
                }
            }

            // Proceed with installation
            this.infoText.Text = this.installingText;

            Directory.CreateDirectory(stagingDir);
            string msiPath        = Path.Combine(stagingDir, msiName);
            string dstPackagePath = GetOriginalMsiName(msiPath);

            // Copy the MSI to the Staging directory before installing. This way it will always
            // be available when Windows Installer needs to refer to it.
            FileInfo info = new FileInfo(originalPackagePath);

            info.CopyTo(dstPackagePath, true);

            // Keep an open file handle so that setupngen.exe cannot delete the file.
            // This happens if the current installation of Paint.NET

            // We need to set the Target Platform property of the MSI before we install it.
            // This way if the user types "C:\Program Files\Whatever" on an x64 system, it will
            // not get redirected over to "C:\Program Files (x86)\Whatever"
            Msi.SetMsiTargetPlatform(dstPackagePath, PaintDotNet.SystemLayer.Processor.NativeArchitecture);

            string commandLine1 = WizardHost.GetMsiCommandLine();
            string commandLine  = commandLine1;

            if (commandLine.Length > 0)
            {
                commandLine += " ";
            }

            commandLine += PropertyNames.QueueNgen + "=1";

            // Install newest package
            result = NativeMethods.MsiInstallProduct(dstPackagePath, commandLine);

            if (result == NativeConstants.ERROR_SUCCESS ||
                result == NativeConstants.ERROR_SUCCESS_REBOOT_INITIATED ||
                result == NativeConstants.ERROR_SUCCESS_REBOOT_REQUIRED)
            {
                ShowBanners();

                WizardHost.SaveMsiProperties();

                // clean up staging dir
                string msiFileName = Path.GetFileName(dstPackagePath);
                foreach (string filePath in Directory.GetFiles(stagingDir, "*.msi"))
                {
                    string fileName = Path.GetFileName(filePath);

                    if (0 != string.Compare(msiFileName, fileName, true, CultureInfo.InvariantCulture))
                    {
                        File.Delete(filePath);
                    }
                }

                // Run "ngen.exe executeQueuedItems", aka "Optimizing performance for your system..."
                if (Application.VisualStyleState == VisualStyleState.ClientAreaEnabled ||
                    Application.VisualStyleState == VisualStyleState.ClientAndNonClientAreasEnabled)
                {
                    this.progressBar.Style   = ProgressBarStyle.Marquee;
                    this.progressBar.Visible = true;
                }

                string       ngenExe = PdnInfo.GetNgenPath();
                const string ngenArg = "executeQueuedItems";

                try
                {
                    this.infoText.Text = this.optimizingText;
                    ProcessStartInfo psi = new ProcessStartInfo(ngenExe, ngenArg);
                    psi.UseShellExecute = false;
                    psi.CreateNoWindow  = true;
                    Process process = Process.Start(psi);

                    while (!process.HasExited)
                    {
                        System.Threading.Thread.Sleep(10);
                        Application.DoEvents();
                    }
                }

                catch
                {
                    // If this fails, do not fail the installation
                }

                // Try to write locale setting to registry
                try
                {
                    Settings.SystemWide.SetString("LanguageName", CultureInfo.CurrentUICulture.Name);
                }

                catch (Exception)
                {
                    // Ignore errors, however
                }

                SystemSounds.Beep.Play();

                WizardHost.SetFinished(true);
                this.progressBar.Visible = false;

                // set text to indicate success
                WizardHost.HeaderText = PdnResources.GetString("SetupWizard.InstallingPage.HeaderText.Success");
                string infoFormat;

                if (result == NativeConstants.ERROR_SUCCESS)
                {
                    WizardHost.RebootRequired = false;
                    infoFormat = PdnResources.GetString("SetupWizard.InstallingPage.InfoText.Text.Success.Format");
                }
                else
                {
                    WizardHost.RebootRequired = true;
                    infoFormat = PdnResources.GetString("SetupWizard.InstallingPage.InfoText.Text.Success.RebootRequired.Format");
                }

                this.infoText.Text = string.Format(infoFormat, this.appName);
                WizardHost.SetBackEnabled(false);
            }
            else
            {
                WizardHost.SetFinished(true);
                this.progressBar.Visible = false;

                // set text to indicate failure
                WizardHost.HeaderText = PdnResources.GetString("SetupWizard.InstallingPage.HeaderText.Failure");
                string infoFormat  = PdnResources.GetString("SetupWizard.InstallingPage.InfoText.Text.Failure.Format");
                string errorString = NativeMethods.FormatMessageW(result);
                this.errorLabel.Font    = WizardHost.NormalTextFont;
                this.errorLabel.Visible = true;
                this.errorLabel.Text    = errorString;
                this.infoText.Text      = string.Format(infoFormat, this.appName) + " (" + result.ToString() + ")";
                WizardHost.SetBackEnabled(false);
            }
        }