Пример #1
0
        public static ActionResult InstallPreset(Session session)
        {
            string presetStr        = session.CustomActionData["PRESET"];
            string appStartMenuPath = session.CustomActionData["APP_START_MENU_PATH"];
            string installDir       = session.CustomActionData["INSTALLDIR"];

            RollbarHelper.ConfigureRollbarSingleton(session.CustomActionData["MSI_VERSION"]);

            var preset = Preset.ParsePreset.Parse(presetStr, session, installDir, appStartMenuPath);

            if (preset == null)
            {
                session.Log("No valid preset set");
                return(ActionResult.Failure);
            }

            try
            {
                var res = preset.Install();
                if (res != ActionResult.Success)
                {
                    RollbarReport.Error(string.Format("unexpected failure in Preset installation"), session);
                }
                return(res);
            }
            catch (Exception err)
            {
                RollbarReport.Critical(string.Format("unknown error in language preset: {0}", err), session);
                return(ActionResult.Failure);
            }
        }
Пример #2
0
        private ActionResult CmdPromptShortcut()
        {
            string shortcutLocation = Path.Combine(appStartMenuPath, "Developer Command Prompt.lnk");

            session.Log("Installing Cmd Prompt shortcut at {0}", shortcutLocation);

            string target = Path.Combine(session.CustomActionData["INSTALLDIR"], "bin", "shell.bat");

            if (!System.IO.File.Exists(target))
            {
                session.Log(string.Format("shell.bat does not exist in path: {0}", target));
                RollbarReport.Error(string.Format("shell.bat does not exist in path: {0}", target), session);
                return(ActionResult.Failure);
            }

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

            WshShell     shell    = new WshShell();
            IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutLocation);

            shortcut.Description = "Developer Command Prompt";
            shortcut.TargetPath  = "%comspec%";
            shortcut.Arguments   = " /k " + "\"" + target + "\"";
            shortcut.Save();
            return(ActionResult.Success);
        }
Пример #3
0
        private static void RollbackStateToolInstall(Session session)
        {
            if (session.CustomActionData["STATE_TOOL_INSTALLED"] == "false")
            {
                Status.ProgressBar.StatusMessage(session, "Rolling back State Tool installation");
                // If we installed the state tool then we want to remove it
                // along with any environment entries.
                // We cannot pass data between non-immediate custom actions
                // so we use the known State Tool installation path from the
                // state deploy custom acion.
                string stateToolInstallDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ActiveState", "bin");

                session.Log(string.Format("Attemping to remove State Tool installation directory: {0}", stateToolInstallDir));
                ActionResult result = Remove.Dir(session, stateToolInstallDir);
                if (!result.Equals(ActionResult.Success))
                {
                    string msg = string.Format("Not successful in removing State Tool installation directory, got action result: {0}", result);
                    session.Log(msg);
                    RollbarReport.Error(msg);
                }

                session.Log(string.Format("Removing environment entries containing: {0}", stateToolInstallDir));
                result = Remove.EnvironmentEntries(session, stateToolInstallDir);
                if (!result.Equals(ActionResult.Success))
                {
                    string msg = string.Format("Not successful in removing State Tool environment entries, got action result: {0}", result);
                    session.Log(msg);
                    RollbarReport.Error(msg);
                }
            }
        }
Пример #4
0
        public async Task TrackS3Event(Session session, string cid, string sessionID, string category, string action, string label)
        {
            string pixelURL = string.Format(
                "https://cli-msi.s3.amazonaws.com/pixel.txt?x-referrer={0}&x-session={1}&x-event={2}&x-event-category={3}&x-event-value={4}",
                cid, sessionID, action, category, label
                );

            session.Log(string.Format("Downloading S3 pixel from URL: {0}", pixelURL));
            try
            {
                await Task.Run(() =>
                {
                    // retry up to 3 times to download the S3 pixel
                    RetryHelper.RetryOnException(session, 3, TimeSpan.FromSeconds(1), () =>
                    {
                        var client = new TimeoutWebClient();
                        // try to complete an s3 tracking event in seven seconds or less.
                        client.Timeout = 7 * 1000;
                        var res        = client.DownloadString(pixelURL);
                        session.Log("Received response {0}", res);
                    });
                });
            }
            catch (Exception e)
            {
                string msg = string.Format("Encountered exception downloading S3 pixel file: {0}", e.ToString());
                session.Log(msg);
                RollbarReport.Error(msg, session);
            }
            session.Log("Successfully downloaded S3 pixel string");
        }
Пример #5
0
        /// <summary>
        /// SetDetails writes the error details to the user's registry.
        /// This function must be run from a deferred custom action
        /// </summary>
        public static void SetDetails(Session session, string errorType, string msg)
        {
            string            registryKey           = string.Format("HKEY_USERS\\{0}\\SOFTWARE\\ActiveState\\{1}", session.CustomActionData["USERSID"], session.CustomActionData["PRODUCT_NAME"]);
            RegistryValueKind registryEntryDataType = RegistryValueKind.String;

            session.Log("Setting registry key: {0}", registryKey);
            try
            {
                Registry.SetValue(registryKey, TypeRegistryKey, errorType, registryEntryDataType);
                Registry.SetValue(registryKey, MessageRegistryKey, msg, registryEntryDataType);
            }
            catch (Exception registryException)
            {
                string registryExceptionMsg = string.Format("Could not set error registry values. Exception: {0}", registryException.ToString());
                session.Log(registryExceptionMsg);
                RollbarReport.Error(registryExceptionMsg, session);
            }
        }
Пример #6
0
        public static ActionResult CustomOnError(Session session)
        {
            session.Log("Begin SetError");

            // Get the registry values set on error in the _installStateTool function
            // Do not fail if we cannot get the values, simply present the fatal custom
            // error dialog without any mention of network errors
            string registryKey = string.Format("SOFTWARE\\ActiveState\\{0}", session["ProductName"]);
            RegistryKey productKey = Registry.CurrentUser.CreateSubKey(registryKey);
            try
            {
                Object errorType = productKey.GetValue(Error.TypeRegistryKey);
                Object errorMessage = productKey.GetValue(Error.MessageRegistryKey);
                session.Log("errorType={0}, error_message={1}", errorType, errorMessage);
                session["ERROR"] = errorType as string;
                session["ERROR_MESSAGE"] = errorMessage as string;
            } catch (Exception e)
            {
                string msg = string.Format("Could not read network error registry keys. Exception: {0}", e.ToString());
                session.Log(msg);
                RollbarReport.Error(msg, session);
            }

            if (session["ERROR"] == new NetworkError().Type()) {
                session.Log("Network error type");
                session.DoAction("GAReportUserNetwork");
                session.DoAction("CustomNetworkError");
                RollbarReport.Error("user_network: " + session["ERROR_MESSAGE"], session);
            } else if (session["ERROR"] == new SecurityError().Type()) {
                session.Log("Path error type");
                session.DoAction("GAReportUserSecurity");
                session.DoAction("CustomSecurityError");
                RollbarReport.Error("user_security: " + session["ERROR_MESSAGE"], session);
            }
            else
            {
                session.Log("Default error type");
                session.DoAction("GAReportFailure");
                session.DoAction("CustomFatalError");
            }

            return ActionResult.Success;
        }
Пример #7
0
        private static void RollbackDeploy(Session session)
        {
            Status.ProgressBar.StatusMessage(session, "Rolling back language installation");
            ActionResult result = Remove.Dir(session, session.CustomActionData["INSTALLDIR"]);

            if (!result.Equals(ActionResult.Success))
            {
                string msg = string.Format("Not successful in removing deploy directory, got action result: {0}", result);
                session.Log(msg);
                RollbarReport.Error(msg);
            }

            result = Remove.EnvironmentEntries(session, session.CustomActionData["INSTALLDIR"]);
            if (!result.Equals(ActionResult.Success))
            {
                string msg = string.Format("Not successful in removing Deployment environment entries, got action result: {0}", result);
                session.Log(msg);
                RollbarReport.Error(msg);
            }
        }
Пример #8
0
        /// <summary>
        /// ResetErrorDetails clears the registry entries for network errors.
        /// This function must be run from a deferred custom action
        /// </summary>
        public static void ResetErrorDetails(Session session)
        {
            // Deferred custom actions run as administrator so we have to specifically set
            // the registry key for the user using their SID in order for the value to
            // be available in later immediate custom actions
            string            registryKey           = string.Format("HKEY_USERS\\{0}\\SOFTWARE\\ActiveState\\{1}", session.CustomActionData["USERSID"], session.CustomActionData["PRODUCT_NAME"]);
            RegistryValueKind registryEntryDataType = RegistryValueKind.String;

            try
            {
                Registry.SetValue(registryKey, TypeRegistryKey, "", registryEntryDataType);
                Registry.SetValue(registryKey, MessageRegistryKey, "", registryEntryDataType);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not delete network error registry keys. Exception: {0}", e.ToString());
                session.Log(msg);
                RollbarReport.Error(msg, session);
            }
        }
Пример #9
0
        public static ActionResult UninstallPreset(Session session)
        {
            var presetStr   = session.CustomActionData["PRESET"];
            var installDir  = session.CustomActionData["REMEMBER"];
            var shortcutDir = session.CustomActionData["REMEMBER_SHORTCUTDIR"];

            var p = ParsePreset.Parse(presetStr, session, installDir, shortcutDir);

            try
            {
                return(p.Uninstall());
            } catch (Exception err)
            {
                string msg = string.Format("unknown error during preset-uninstall {0}", err);
                session.Log(msg);
                RollbarReport.Error(string.Format("unknown error during uninstall: {0}", err), session);

                // We finish the uninstallation anyways, as otherwise the MSI becomes un-installable.  And that's bad!
                return(ActionResult.Success);
            }
        }
Пример #10
0
        public static ActionResult Dir(Session session, string dir)
        {
            session.Log(string.Format("Removing directory: {0}", dir));

            if (Directory.Exists(dir))
            {
                try
                {
                    Directory.Delete(dir, true);
                }
                catch (Exception e)
                {
                    string msg = string.Format("Could not delete install directory, got error: {0}", e.ToString());
                    session.Log(msg);
                    RollbarReport.Critical(msg, session);
                    return(ActionResult.Failure);
                }
            }

            return(ActionResult.Success);
        }
Пример #11
0
        private ActionResult PerlCriticShortcut()
        {
            string shortcutLocation = Path.Combine(appStartMenuPath, "Perl Critic" + ".lnk");

            session.Log("Installing Perl Critic shortcut @ {0}", shortcutLocation);

            string target = Path.Combine(session.CustomActionData["INSTALLDIR"], "bin", "wperl.exe");

            if (!System.IO.File.Exists(target))
            {
                session.Log(string.Format("wperl.exe does not exist in path: {0}", target));
                RollbarReport.Error(string.Format("wperl.exe does not exist in path: {0}", target), session);
                return(ActionResult.Failure);
            }

            string perlCriticLocation = Path.Combine(session.CustomActionData["INSTALLDIR"], "bin", "perlcritic-gui");

            if (!System.IO.File.Exists(perlCriticLocation))
            {
                session.Log(string.Format("perlcritic-gui does not exist in path: {0}", perlCriticLocation));
                RollbarReport.Error(string.Format("perlcritic-gui does not exist in path: {0}", perlCriticLocation), session);
                return(ActionResult.Failure);
            }

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

            WshShell     shell    = new WshShell();
            IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutLocation);

            shortcut.Description  = "Perl Critic";
            shortcut.IconLocation = session.CustomActionData["INSTALLDIR"] + "perl.ico";
            shortcut.TargetPath   = target;
            shortcut.Arguments    = " -x " + "\"" + perlCriticLocation + "\"";
            shortcut.Save();
            return(ActionResult.Success);
        }
Пример #12
0
        public static ActionResult InstallStateTool(Session session, out string stateToolPath)
        {
            RollbarHelper.ConfigureRollbarSingleton(session.CustomActionData["COMMIT_ID"]);

            session.Log("Installing State Tool if necessary");
            if (session.CustomActionData["STATE_TOOL_INSTALLED"] == "true")
            {
                stateToolPath = session.CustomActionData["STATE_TOOL_PATH"];
                session.Log("State Tool is installed, no installation required");
                Status.ProgressBar.Increment(session, 1);
                return(ActionResult.Success);
            }

            Status.ProgressBar.StatusMessage(session, "Installing State Tool...");
            Status.ProgressBar.Increment(session, 1);
            stateToolPath = "";

            var    paths     = GetPaths();
            string stateURL  = "https://s3.ca-central-1.amazonaws.com/cli-update/update/state/unstable/";
            string jsonURL   = stateURL + paths.JsonDescription;
            string timeStamp = DateTime.Now.ToFileTime().ToString();
            string tempDir   = Path.Combine(Path.GetTempPath(), timeStamp);

            session.Log(string.Format("Using temp path: {0}", tempDir));
            try
            {
                Directory.CreateDirectory(tempDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not create temp directory at: {0}, encountered exception: {1}", tempDir, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            string versionInfoString;

            session.Log(string.Format("Downloading JSON from URL: {0}", jsonURL));
            try
            {
                WebClient client = new WebClient();
                versionInfoString = client.DownloadString(jsonURL);
            }
            catch (WebException e)
            {
                string msg = string.Format("Encountered exception downloading state tool json info file: {0}", e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            VersionInfo info;

            try
            {
                info = JsonConvert.DeserializeObject <VersionInfo>(versionInfoString);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not deserialize version info. Version info string {0}, exception {1}", versionInfoString, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            string zipPath = Path.Combine(tempDir, paths.ZipFile);
            string zipURL  = stateURL + info.version + "/" + paths.ZipFile;

            session.Log(string.Format("Downloading zip file from URL: {0}", zipURL));
            Status.ProgressBar.StatusMessage(session, "Downloading State Tool...");
            try
            {
                WebClient client = new WebClient();
                client.DownloadFile(zipURL, zipPath);
            }
            catch (WebException e)
            {
                string msg = string.Format("Encoutered exception downloading state tool zip file. URL to zip file: {0}, path to save zip file to: {1}, exception: {2}", zipURL, zipPath, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            SHA256     sha     = SHA256.Create();
            FileStream fInfo   = File.OpenRead(zipPath);
            string     zipHash = BitConverter.ToString(sha.ComputeHash(fInfo)).Replace("-", string.Empty).ToLower();

            if (zipHash != info.sha256v2)
            {
                string msg = string.Format("SHA256 checksum did not match, expected: {0} actual: {1}", info.sha256v2, zipHash.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            Status.ProgressBar.StatusMessage(session, "Extracting State Tool executable...");
            try
            {
                ZipFile.ExtractToDirectory(zipPath, tempDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not extract State Tool, encountered exception. Path to zip file: {0}, path to temp directory: {1}, exception {2})", zipPath, tempDir, e);
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            string stateToolInstallDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ActiveState", "bin");

            try
            {
                Directory.CreateDirectory(stateToolInstallDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not create State Tool install directory at: {0}, encountered exception: {1}", stateToolInstallDir, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }


            stateToolPath = Path.Combine(stateToolInstallDir, "state.exe");
            if (File.Exists(stateToolPath))
            {
                try
                {
                    File.Delete(stateToolPath);
                }
                catch (Exception e)
                {
                    string msg = string.Format("Could not remove existing temporary state tool executable at: {0}, encountered exception: {1}", stateToolPath, e.ToString());
                    session.Log(msg);
                    RollbarReport.Critical(msg);
                    return(ActionResult.Failure);
                }
            }

            try
            {
                File.Move(Path.Combine(tempDir, paths.ExeFile), stateToolPath);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not move State Tool executable to: {0}, encountered exception: {1}", stateToolPath, e);
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            string       configDirCmd = " export" + " config" + " --filter=dir";
            string       output;
            ActionResult runResult = ActiveState.Command.Run(session, stateToolPath, configDirCmd, out output);

            session.Log("Writing install file...");
            // We do not fail the installation if writing the installsource.txt file fails
            if (runResult.Equals(ActionResult.Failure))
            {
                string msg = string.Format("Could not get config directory from State Tool");
                session.Log(msg);
                RollbarReport.Error(msg);
            }
            else
            {
                string contents = "msi-ui";
                if (session.CustomActionData["UI_LEVEL"] == "2")
                {
                    contents = "msi-silent";
                }
                try
                {
                    string installFilePath = Path.Combine(output.Trim(), "installsource.txt");
                    File.WriteAllText(installFilePath, contents);
                }
                catch (Exception e)
                {
                    string msg = string.Format("Could not write install file at path: {0}, encountered exception: {1}", output, e.ToString());
                    session.Log(msg);
                    RollbarReport.Error(msg);
                }
            }

            session.Log("Updating PATH environment variable");
            string oldPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);

            if (oldPath.Contains(stateToolInstallDir))
            {
                session.Log("State tool installation already on PATH");
                return(ActionResult.Success);
            }

            var newPath = string.Format("{0};{1}", stateToolInstallDir, oldPath);

            session.Log(string.Format("updating PATH to {0}", newPath));
            try
            {
                Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.Machine);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not update PATH. Attempted to set path to: {0}, encountered exception: {1}", newPath, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            return(ActionResult.Success);
        }
Пример #13
0
        public static ActionResult StateDeploy(Session session)
        {
            ActiveState.RollbarHelper.ConfigureRollbarSingleton(session.CustomActionData["COMMIT_ID"]);

            if (!Environment.Is64BitOperatingSystem)
            {
                Record record = new Record();
                record.FormatString = "This installer cannot be run on a 32-bit operating system";

                RollbarReport.Critical(record.FormatString);
                session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                return(ActionResult.Failure);
            }

            string       stateToolPath;
            ActionResult res = InstallStateTool(session, out stateToolPath);

            if (res != ActionResult.Success)
            {
                return(res);
            }
            session.Log("Starting state deploy with state tool at " + stateToolPath);

            res = Login(session, stateToolPath);
            if (res.Equals(ActionResult.Failure))
            {
                return(res);
            }

            Status.ProgressBar.StatusMessage(session, string.Format("Deploying project {0}...", session.CustomActionData["PROJECT_OWNER_AND_NAME"]));
            Status.ProgressBar.StatusMessage(session, string.Format("Preparing deployment of {0}...", session.CustomActionData["PROJECT_OWNER_AND_NAME"]));

            var sequence = new ReadOnlyCollection <InstallSequenceElement>(
                new[]
            {
                new InstallSequenceElement("install", string.Format("Installing {0}", session.CustomActionData["PROJECT_OWNER_AND_NAME"])),
                new InstallSequenceElement("configure", "Updating system environment"),
                new InstallSequenceElement("symlink", "Creating shortcut directory"),
            });

            try
            {
                foreach (var seq in sequence)
                {
                    string deployCmd = BuildDeployCmd(session, seq.SubCommand);
                    session.Log(string.Format("Executing deploy command: {0}", deployCmd));

                    Status.ProgressBar.Increment(session, 1);
                    Status.ProgressBar.StatusMessage(session, seq.Description);

                    string output;
                    var    runResult = ActiveState.Command.Run(session, stateToolPath, deployCmd, out output);
                    if (runResult.Equals(ActionResult.UserExit))
                    {
                        // Catch cancel and return
                        return(runResult);
                    }
                    else if (runResult == ActionResult.Failure)
                    {
                        Record record      = new Record();
                        var    errorOutput = FormatErrorOutput(output);
                        record.FormatString = String.Format("{0} failed with error:\n{1}", seq.Description, errorOutput);

                        MessageResult msgRes = session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                        return(runResult);
                    }
                }
            }
            catch (Exception objException)
            {
                string msg = string.Format("Caught exception: {0}", objException);
                session.Log(msg);
                RollbarReport.Critical(msg);
                return(ActionResult.Failure);
            }

            Status.ProgressBar.Increment(session, 1);
            return(ActionResult.Success);
        }
Пример #14
0
        private static ActionResult _installStateTool(Session session, out string stateToolPath)
        {
            Error.ResetErrorDetails(session);

            var paths = GetPaths();
            string stateURL = "https://state-tool.s3.amazonaws.com/update/state/release/";
            string jsonURL = stateURL + paths.JsonDescription;
            string timeStamp = DateTime.Now.ToFileTime().ToString();
            string tempDir = Path.Combine(Path.GetTempPath(), timeStamp);
            string stateToolInstallDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ActiveState", "bin");
            stateToolPath = Path.Combine(stateToolInstallDir, "state.exe");

            if (File.Exists(stateToolPath))
            {
                session.Log("Using existing State Tool executable at install path");
                Status.ProgressBar.Increment(session, 200);
                return ActionResult.Success;
            }

            session.Log(string.Format("Using temp path: {0}", tempDir));
            try
            {
                Directory.CreateDirectory(tempDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not create temp directory at: {0}, encountered exception: {1}", tempDir, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            string versionInfoString = "unset";
            session.Log(string.Format("Downloading JSON from URL: {0}", jsonURL));
            try
            {
                RetryHelper.RetryOnException(session, 3, TimeSpan.FromSeconds(2), () =>
                {
                    var client = new WebClient();
                    versionInfoString = client.DownloadString(jsonURL);
                });
            }
            catch (WebException e)
            {
                string msg = string.Format("Encountered exception downloading state tool json info file: {0}", e.ToString());
                session.Log(msg);
                new NetworkError().SetDetails(session, e.Message);
                return ActionResult.Failure;
            }

            VersionInfo info;
            try
            {
                info = JsonConvert.DeserializeObject<VersionInfo>(versionInfoString);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not deserialize version info. Version info string {0}, exception {1}", versionInfoString, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            string zipPath = Path.Combine(tempDir, paths.ZipFile);
            string zipURL = stateURL + info.version + "/" + paths.ZipFile;
            session.Log(string.Format("Downloading zip file from URL: {0}", zipURL));
            Status.ProgressBar.StatusMessage(session, "Downloading State Tool...");

            var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;

            Task incrementTask = Task.Run(() =>
            {
                incrementProgressBar(session, 50, token);
            });

            Task<ActionResult> downloadTask = Task.Run(() =>
            {
                try
                {
                    RetryHelper.RetryOnException(session, 3, TimeSpan.FromSeconds(2), () =>
                    {
                        var client = new WebClient();
                        client.DownloadFile(zipURL, zipPath);
                    });
                }
                catch (WebException e)
                {
                    string msg = string.Format("Encountered exception downloading state tool zip file. URL to zip file: {0}, path to save zip file to: {1}, exception: {2}", zipURL, zipPath, e.ToString());
                    session.Log(msg);
                    new NetworkError().SetDetails(session, e.Message);
                    return ActionResult.Failure;
                }

                return ActionResult.Success;
            });

            ActionResult result = downloadTask.Result;
            tokenSource.Cancel();
            incrementTask.Wait();
            if (result.Equals(ActionResult.Failure))
            {
                return result;
            }


            SHA256 sha = SHA256.Create();
            FileStream fInfo = File.OpenRead(zipPath);
            string zipHash = BitConverter.ToString(sha.ComputeHash(fInfo)).Replace("-", string.Empty).ToLower();
            if (zipHash != info.sha256v2)
            {
                string msg = string.Format("SHA256 checksum did not match, expected: {0} actual: {1}", info.sha256v2, zipHash.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            Status.ProgressBar.StatusMessage(session, "Extracting State Tool executable...");
            Status.ProgressBar.Increment(session, 50);
            try
            {
                ZipFile.ExtractToDirectory(zipPath, tempDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not extract State Tool, encountered exception. Path to zip file: {0}, path to temp directory: {1}, exception {2})", zipPath, tempDir, e);
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            try
            {
                Directory.CreateDirectory(stateToolInstallDir);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not create State Tool install directory at: {0}, encountered exception: {1}", stateToolInstallDir, e.ToString());
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            try
            {
                File.Move(Path.Combine(tempDir, paths.ExeFile), stateToolPath);
            }
            catch (Exception e)
            {
                string msg = string.Format("Could not move State Tool executable to: {0}, encountered exception: {1}", stateToolPath, e);
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }


            string configDirCmd = " export" + " config" + " --filter=dir";
            string output;
            ActionResult runResult = ActiveState.Command.Run(session, stateToolPath, configDirCmd, out output);
            session.Log("Writing install file...");
            // We do not fail the installation if writing the installsource.txt file fails
            if (runResult.Equals(ActionResult.Failure))
            {
                string msg = string.Format("Could not get config directory from State Tool");
                session.Log(msg);
                RollbarReport.Error(msg, session);
            }
            else
            {
                string contents = "msi-ui";
                if (session.CustomActionData["UI_LEVEL"] == "2")
                {
                    contents = "msi-silent";
                }
                try
                {
                    string installFilePath = Path.Combine(output.Trim(), "installsource.txt");
                    File.WriteAllText(installFilePath, contents, Encoding.ASCII);
                }
                catch (Exception e)
                {
                    string msg = string.Format("Could not write install file at path: {0}, encountered exception: {1}", output, e.ToString());
                    session.Log(msg);
                    RollbarReport.Error(msg, session);
                }
            }

            session.Log("Updating PATH environment variable");
            Status.ProgressBar.Increment(session, 50);
            string oldPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
            if (oldPath.Contains(stateToolInstallDir))
            {
                session.Log("State tool installation already on PATH");
            }
            else
            {
                var newPath = string.Format("{0};{1}", stateToolInstallDir, oldPath);
                session.Log(string.Format("updating PATH to {0}", newPath));
                try
                {
                    Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.Machine);
                }
                catch (Exception e)
                {
                    string msg = string.Format("Could not update PATH. Encountered exception: {0}", e.Message);
                    session.Log(msg);
                    new SecurityError().SetDetails(session, msg);
                    return ActionResult.Failure;
                }
            }

            session.Log("Running prepare step...");
            string prepareCmd = " _prepare";
            string prepareOutput;
            ActionResult prepareRunResult = ActiveState.Command.Run(session, stateToolPath, prepareCmd, out prepareOutput);
            if (prepareRunResult.Equals(ActionResult.Failure))
            {
                string msg = string.Format("Preparing environment caused error: {0}", prepareOutput);
                session.Log(msg);
                RollbarReport.Critical(msg, session);

                Record record = new Record();
                var errorOutput = Command.FormatErrorOutput(prepareOutput);
                record.FormatString = msg;

                session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                return ActionResult.Failure;
            }
            else
            {
                session.Log(string.Format("Prepare Output: {0}", prepareOutput));
            }

            Status.ProgressBar.Increment(session, 50);
            return ActionResult.Success;
        }
Пример #15
0
        private static ActionResult run(Session session)
        {
            var uiLevel = session.CustomActionData["UI_LEVEL"];

            if (uiLevel == "2" /* no ui */ || uiLevel == "3" /* basic ui */)
            {
                // we have to send the start event, because it has not triggered before
                reportStartEvent(session, uiLevel);
            }

            if (!Environment.Is64BitOperatingSystem)
            {
                Record record = new Record();
                record.FormatString = "This installer cannot be run on a 32-bit operating system";

                RollbarReport.Critical(record.FormatString, session);
                session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                return ActionResult.Failure;
            }

            string stateToolPath;
            ActionResult res = InstallStateTool(session, out stateToolPath);
            if (res != ActionResult.Success)
            {
                return res;
            }
            session.Log("Starting state deploy with state tool at " + stateToolPath);

            res = Login(session, stateToolPath);
            if (res.Equals(ActionResult.Failure))
            {
                return res;
            }

            Status.ProgressBar.StatusMessage(session, string.Format("Deploying project {0}...", session.CustomActionData["PROJECT_OWNER_AND_NAME"]));
            Status.ProgressBar.StatusMessage(session, string.Format("Preparing deployment of {0}...", session.CustomActionData["PROJECT_OWNER_AND_NAME"]));

            var sequence = new ReadOnlyCollection<InstallSequenceElement>(
                new[]
                {
                    new InstallSequenceElement("install", string.Format("Installing {0}", session.CustomActionData["PROJECT_OWNER_AND_NAME"])),
                    new InstallSequenceElement("configure", "Updating system environment"),
                    new InstallSequenceElement("symlink", "Creating shortcut directory"),
                });

            try
            {
                foreach (var seq in sequence)
                {
                    string deployCmd = BuildDeployCmd(session, seq.SubCommand);
                    session.Log(string.Format("Executing deploy command: {0}", deployCmd));

                    Status.ProgressBar.StatusMessage(session, seq.Description);
                    string output;
                    var runResult = ActiveState.Command.RunWithProgress(session, stateToolPath, deployCmd, 200, out output);
                    if (runResult.Equals(ActionResult.UserExit))
                    {
                        // Catch cancel and return
                        return runResult;
                    }
                    else if (runResult == ActionResult.Failure)
                    {
                        Record record = new Record();
                        var errorOutput = Command.FormatErrorOutput(output);
                        record.FormatString = String.Format("{0} failed with error:\n{1}", seq.Description, errorOutput);

                        MessageResult msgRes = session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                        TrackerSingleton.Instance.TrackEventSynchronously(session, "stage", "artifacts", "failure");

                        return runResult;
                    }
                }
                TrackerSingleton.Instance.TrackEventSynchronously(session, "stage", "artifacts", "success");
            }
            catch (Exception objException)
            {
                string msg = string.Format("Caught exception: {0}", objException);
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return ActionResult.Failure;
            }

            Status.ProgressBar.Increment(session, 100);
            return ActionResult.Success;

        }
Пример #16
0
        public static ActionResult Uninstall(Session session)
        {
            ActiveState.RollbarHelper.ConfigureRollbarSingleton(session.CustomActionData["MSI_VERSION"]);
            string installDir = session.CustomActionData["REMEMBER"];

            session.Log("Begin uninstallation");

            ActionResult result;

            if (installDir != "")
            {
                result = Remove.Dir(session, installDir);
                if (result.Equals(ActionResult.Failure))
                {
                    session.Log("Could not remove installation directory");

                    Record record = new Record();
                    record.FormatString = string.Format("Could not remove installation directory entry at: {0}, please ensure no files in the directory are currently being used and try again", installDir);

                    session.Message(InstallMessage.Error | (InstallMessage)MessageBoxButtons.OK, record);
                    return(ActionResult.Failure);
                }

                result = Remove.EnvironmentEntries(session, installDir);
                if (result.Equals(ActionResult.Failure))
                {
                    string msg = "Could not remove environment entries";
                    session.Log(msg);
                    RollbarReport.Critical(msg, session);
                    return(ActionResult.Failure);
                }
            }
            else
            {
                session.Log("REMEMBER variable was not set in UNINSTALL");
            }

            string shortcutDir = session.CustomActionData["REMEMBER_SHORTCUTDIR"];

            if (shortcutDir != "")
            {
                result = Remove.Dir(session, shortcutDir);
                if (result.Equals(ActionResult.Failure))
                {
                    string msg = "Could not remove shortcuts directory";
                    session.Log(msg);
                    RollbarReport.Critical(msg, session);
                    return(ActionResult.Failure);
                }
            }
            else
            {
                session.Log("REMEMBER_SHORTCUTDIR was not set in UNINSTALL");
            }

            result = UninstallPreset(session);
            if (result.Equals(ActionResult.Failure))
            {
                string msg = "Could not uninstall language preset";
                session.Log(msg);
                RollbarReport.Critical(msg, session);
                return(ActionResult.Failure);
            }
            return(result);
        }
Пример #17
0
        private static ActionResult RunInternal(Session session, string cmd, string args, int limit, bool reportCmd, out string output)
        {
            var errBuilder    = new StringBuilder();
            var outputBuilder = new StringBuilder();

            try
            {
                if (cmd == "powershell")
                {
                    cmd = Path.Combine(Environment.SystemDirectory, "WindowsPowershell", "v1.0", "powershell.exe");
                    if (!File.Exists(cmd))
                    {
                        session.Log("Did not find powershell @" + cmd);
                        cmd = "powershell.exe";
                    }
                }

                var procStartInfo = new ProcessStartInfo(cmd, args);
                // The following commands are needed to redirect the standard output.
                // This means that it will be redirected to the Process.StandardOutput StreamReader.
                procStartInfo.RedirectStandardOutput = true;
                procStartInfo.RedirectStandardError  = true;
                procStartInfo.UseShellExecute        = false;
                procStartInfo.StandardOutputEncoding = Encoding.UTF8;
                procStartInfo.StandardErrorEncoding  = Encoding.UTF8;
                if (cmd.Contains("state.exe"))
                {
                    procStartInfo.EnvironmentVariables["VERBOSE"] = "true";
                    procStartInfo.EnvironmentVariables["ACTIVESTATE_NONINTERACTIVE"] = "true";
                }
                // Do not create the black window.
                procStartInfo.CreateNoWindow = true;

                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo = procStartInfo;

                proc.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    var line = e.Data;
                    if (!String.IsNullOrEmpty(line))
                    {
                        session.Log("out: " + line);
                        outputBuilder.Append("\n" + line);
                    }
                });
                proc.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    // Prepend line numbers to each line of the output.
                    if (!String.IsNullOrEmpty(e.Data))
                    {
                        // We do not write stderr to our own log, as it comprises the progress bar output
                        session.Log("err: " + e.Data);
                        errBuilder.Append("\n" + e.Data);
                    }
                });
                proc.Start();

                // Asynchronously read the standard output and standard error of the spawned process.
                // This raises OutputDataReceived/ErrorDataReceived events for each line of output/errors.
                proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();

                int count = 0;
                while (!proc.HasExited)
                {
                    try
                    {
                        // This is to update the progress bar and listen for a cancel event
                        if (count < limit)
                        {
                            Status.ProgressBar.Increment(session, 1);
                            Thread.Sleep(150);
                        }
                        else
                        {
                            Status.ProgressBar.Increment(session, 0);
                            Thread.Sleep(150);
                        }
                    }
                    catch (InstallCanceledException)
                    {
                        session.Log("Caught install cancelled exception");
                        Process.KillProcessAndChildren(proc.Id);
                        output = "process got interrupted.";
                        return(ActionResult.UserExit);
                    }
                }
                proc.WaitForExit();

                var exitCode = proc.ExitCode;
                session.Log(String.Format("process returned with exit code: {0}", exitCode));
                proc.Close();
                if (exitCode != 0)
                {
                    outputBuilder.Append('\x00');
                    session.Log("returning due to return code: {0}", exitCode);
                    if (exitCode == 11)
                    {
                        output = outputBuilder.ToString();
                        string message = FormatErrorOutput(output);
                        session.Log("Message details: {0}", message);
                        new NetworkError().SetDetails(session, message);
                    }
                    else
                    {
                        outputBuilder.AppendFormat(" -- Process returned with exit code: {0}", exitCode);
                        output = outputBuilder.ToString();
                        var title = output.Split('\n')[0];
                        if (title.Length == 0)
                        {
                            title = output;
                        }
                        var customData = new Dictionary <string, object> {
                            { "output", output }, { "err", errBuilder.ToString() }
                        };
                        if (reportCmd)
                        {
                            customData["cmd"] = cmd;
                        }
                        RollbarReport.Critical(
                            string.Format("failed due to return code: {0} - start: {1}", exitCode, title),
                            session,
                            customData
                            );
                    }

                    return(ActionResult.Failure);
                }
            }
            catch (Exception objException)
            {
                outputBuilder.Append('\x00');
                var exceptionString = string.Format("Caught exception: {0}", objException);
                outputBuilder.Append(exceptionString);
                output = outputBuilder.ToString();
                session.Log(exceptionString);
                RollbarReport.Error(exceptionString, session);
                return(ActionResult.Failure);
            }
            output = outputBuilder.ToString();
            return(ActionResult.Success);
        }
Пример #18
0
        public static ActionResult Run(Session session, string cmd, string args, out string output)
        {
            var errBuilder    = new StringBuilder();
            var outputBuilder = new StringBuilder();

            try
            {
                if (cmd == "powershell")
                {
                    cmd = Path.Combine(Environment.SystemDirectory, "WindowsPowershell", "v1.0", "powershell.exe");
                    if (!File.Exists(cmd))
                    {
                        session.Log("Did not find powershell @" + cmd);
                        cmd = "powershell.exe";
                    }
                }

                var procStartInfo = new ProcessStartInfo(cmd, args);
                // The following commands are needed to redirect the standard output.
                // This means that it will be redirected to the Process.StandardOutput StreamReader.
                procStartInfo.RedirectStandardOutput = true;
                procStartInfo.RedirectStandardError  = true;
                procStartInfo.UseShellExecute        = false;
                // Do not create the black window.
                procStartInfo.CreateNoWindow = true;

                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo = procStartInfo;

                proc.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    var line = e.Data;
                    if (!String.IsNullOrEmpty(line))
                    {
                        session.Log("out: " + line);
                        outputBuilder.Append("\n" + line);
                    }
                });
                proc.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    // Prepend line numbers to each line of the output.
                    if (!String.IsNullOrEmpty(e.Data))
                    {
                        session.Log("err: " + e.Data);
                        errBuilder.Append("\n" + e.Data);
                    }
                });
                proc.Start();

                // Asynchronously read the standard output and standard error of the spawned process.
                // This raises OutputDataReceived/ErrorDataReceived events for each line of output/errors.
                proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();

                while (!proc.HasExited)
                {
                    try
                    {
                        // This is just hear to throw an InstallCanceled Exception if necessary
                        Status.ProgressBar.Increment(session, 0);
                        Thread.Sleep(200);
                    }
                    catch (InstallCanceledException)
                    {
                        session.Log("Caught install cancelled exception");
                        Process.KillProcessAndChildren(proc.Id);
                        output = "process got interrupted.";
                        return(ActionResult.UserExit);
                    }
                }
                proc.WaitForExit();

                var exitCode = proc.ExitCode;
                session.Log(String.Format("process returned with exit code: {0}", exitCode));
                proc.Close();
                if (exitCode != 0)
                {
                    outputBuilder.Append('\x00');
                    outputBuilder.AppendFormat(" -- Process returned with exit code: {0}", exitCode);
                    output = outputBuilder.ToString();
                    session.Log("returning due to return code - error");
                    var title = output.Split('\n')[0];
                    if (title.Length == 0)
                    {
                        title = output;
                    }
                    if (title.Length > 50)
                    {
                        title = title.Substring(0, 50);
                    }
                    RollbarReport.Critical(
                        string.Format("failed due to return code: {0} - start: {1}", exitCode, title),
                        new Dictionary <string, object> {
                        { "output", output }, { "err", errBuilder.ToString() }, { "cmd", cmd }
                    }
                        );
                    return(ActionResult.Failure);
                }
            }
            catch (Exception objException)
            {
                outputBuilder.Append('\x00');
                var exceptionString = string.Format("Caught exception: {0}", objException);
                outputBuilder.Append(exceptionString);
                output = outputBuilder.ToString();
                session.Log(exceptionString);
                RollbarReport.Error(exceptionString);
                return(ActionResult.Failure);
            }
            output = outputBuilder.ToString();
            return(ActionResult.Success);
        }