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