/// <summary> /// Grab from a settings file. /// </summary> /// <param name="path"></param> /// <param name="logger"></param> public void PopulateFromSettingsFile(string path, ILoggerInterface logger) { string file = UtilsSystem.CombinePaths(path, "artifact-settings.yml"); if (!File.Exists(file)) { return; } var configfile = new Configuration.YamlConfigurationFile(); try { // This file might be malformed, do not crash and let other // environment information sources have their chance configfile.ParseFromFile(file); } catch (Exception e) { logger.LogException(new Exception("Error parsing file: " + file, e)); return; } // Parse the artifact settings... this.branch = configfile.GetStringValue("repo-branch", null); this.commit_sha = configfile.GetStringValue("repo-commit", null); this.version = configfile.GetStringValue("build-id", null); }
/// <summary> /// Get a setting /// </summary> /// <typeparam name="TType"></typeparam> /// <param name="name"></param> /// <param name="defaultValue"></param> /// <param name="logger"></param> /// <param name="isEnum"></param> /// <returns></returns> public TType GetSettingPersistent <TType>(string name, TType defaultValue, ILoggerInterface logger, bool isEnum = false) { this.privateDataPersistent = this.privateDataPersistent ?? new Dictionary <string, object>(); TType result = defaultValue; if (!this.privateDataPersistent.ContainsKey(name)) { return(defaultValue); } try { if (isEnum) { result = (TType)Enum.Parse(typeof(TType), Convert.ToString(this.privateDataPersistent[name])); } else { result = (TType)this.privateDataPersistent[name]; } } catch (Exception e) { logger.LogInfo(false, "source value: '" + Convert.ToString(this.privateDataPersistent[name]) + "'"); logger.LogException(e); } return(result); }
public static List <ProcessInfo> GetPathProcessesInfo(string path, ILoggerInterface logger, bool logDetails = false) { List <ProcessInfo> result = new List <ProcessInfo>(); foreach (var process in GetProcessesThatBlockPathHandle(path, logger, logDetails)) { try { result.Add(GetProcessInfo(process.pid, logger)); } catch (Exception e) { logger.LogException(e, EventLogEntryType.Warning); } } return(result); }
private static List <Handle> GetProcessesThatBlockPathHandle(string path, ILoggerInterface logger, bool logDetails = false) { if (!File.Exists(path) && !Directory.Exists(path)) { return(new List <Handle>()); } string key = "SOFTWARE\\Sysinternals\\Handle"; string name = "EulaAccepted"; // This Utility has an EULA GUI on first run... try to avoid that // by manually setting the registry int?eulaaccepted64 = (int?)UtilsRegistry.GetRegistryKeyValue64(RegistryHive.CurrentUser, key, name, null); int?eulaaccepted32 = (int?)UtilsRegistry.GetRegistryKeyValue32(RegistryHive.CurrentUser, key, name, null); bool eulaaccepted = (eulaaccepted32 == 1 && eulaaccepted64 == 1); if (!eulaaccepted) { UtilsRegistry.SetRegistryValue(RegistryHive.CurrentUser, key, name, 1, RegistryValueKind.DWord); } // Normalize the path, to ensure that long path is not used, otherwise handle.exe won't work as expected string fileName = UtilsSystem.RemoveLongPathSupport(path); List <Handle> result = new List <Handle>(); string outputTool = string.Empty; // Gather the handle.exe from the embeded resource and into a temp file var handleexe = UtilsSystem.GetTempPath("handle") + Guid.NewGuid().ToString().Replace("-", "_") + ".exe"; UtilsSystem.EmbededResourceToFile(Assembly.GetExecutingAssembly(), "_Resources.Handle.exe", handleexe); try { using (Process tool = new Process()) { tool.StartInfo.FileName = handleexe; tool.StartInfo.Arguments = fileName; tool.StartInfo.UseShellExecute = false; tool.StartInfo.Verb = "runas"; tool.StartInfo.RedirectStandardOutput = true; tool.Start(); outputTool = tool.StandardOutput.ReadToEnd(); tool.WaitForExit(1000); if (!tool.HasExited) { tool.Kill(); } } } catch (Exception e) { logger.LogException(e, EventLogEntryType.Warning); } finally { UtilsSystem.DeleteFile(handleexe, logger, 5); } string matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)"; foreach (Match match in Regex.Matches(outputTool, matchPattern)) { if (int.TryParse(match.Value, out var pid)) { if (result.All(i => i.pid != pid)) { result.Add(new Handle() { pid = pid }); } } } if (result.Any() && logDetails) { logger?.LogInfo(true, outputTool); } return(result); }
/// <summary> /// Closes all the handles that block any files in the specified path /// </summary> /// <param name="path"></param> /// <param name="allowedProcesses">List of whitelisted processes</param> /// <param name="logger"></param> public static void ClosePathProcesses( string path, List <string> allowedProcesses, ILoggerInterface logger) { if (string.IsNullOrWhiteSpace(path)) { return; } // Make sure the path exists if (!File.Exists(path) && !Directory.Exists(path)) { return; } // Load list of processes that block directory var processes = GetPathProcessesInfo(path, logger); // Filter the whitelisted string regex = string.Join("|", allowedProcesses); var processesThatWillBeClosed = processes.Where((i) => i.MainModulePath != null && Regex.IsMatch(i.MainModulePath, regex)).ToList(); if (!processesThatWillBeClosed.Any()) { return; } // Message of processes that will not be closed var processesThatWillNotBeClosed = processes.Except(processesThatWillBeClosed).ToList(); if (processesThatWillNotBeClosed.Any()) { logger.LogWarning(true, "The following processes are not whitelisted and will not be closed {0}", string.Join(", ", processesThatWillNotBeClosed.Select((i) => i.ProcessName))); } // Grab the actual process instances var processesInstances = GetProcessInstance(processesThatWillBeClosed); // First kill al the processes. foreach (var p in processesInstances) { try { logger.LogInfo(true, "Killing process: {0}", p.ProcessName); if (!p.HasExited) { p.Kill(); p.WaitForExit(3000); } } catch (Exception e) { logger.LogException(e, EventLogEntryType.Warning); } } // Even though the processes have exited, handles take a while to be released Thread.Sleep(500); foreach (var p in processesInstances) { bool hasClosed = UtilsSystem.WaitWhile(() => !p.HasExited, 15000, $"Waiting for process {p.ProcessName} to close.", logger); logger.LogInfo(true, "Process {0} has closed: {1}", p.ProcessName, hasClosed); } }
/// <summary> /// Create a user or return one if it does not exist. /// </summary> /// <param name="identity"></param> /// <param name="password"></param> /// <param name="displayName"></param> /// <param name="logger"></param> /// <param name="acp"></param> /// <returns></returns> public static UserPrincipal EnsureUserExists( string identity, string password, string displayName, ILoggerInterface logger, AccountManagementPrincipalContext acp) { var parsedUserName = new FqdnNameParser(identity); if (parsedUserName.UserPrincipalName.Length > 64) { throw new Exception($"Windows account userPrincipalName '{parsedUserName.UserPrincipalName}' cannot be longer than 64 characters."); } using (PrincipalContext pc = BuildPrincipal(acp)) { UserPrincipal up = FindUser(identity, pc); string samAccountName = parsedUserName.SamAccountName; logger.LogInfo(false, $"Ensure windows account exists '{samAccountName}@{password}' with userPrincipal '{identity}'"); if (up == null) { up = new UserPrincipal(pc, samAccountName, password, true); } else { logger.LogInfo(true, $"Found account IsAccountLockedOut={up.IsAccountLockedOut()}, SamAccountName={up.SamAccountName}"); // Make sure we have the latest password, just in case // the pwd algorithm generation changes... try { up.SetPassword(password); } catch (Exception e) { logger.LogWarning(true, "Cannot update password for account: " + e.Message + e.InnerException?.Message); } } up.UserCannotChangePassword = true; up.PasswordNeverExpires = true; up.Enabled = true; up.DisplayName = displayName; up.Description = parsedUserName.UserPrincipalName; // If we are in a domain, assign the user principal name if (pc.ContextType == ContextType.Domain) { logger.LogInfo(true, "Setting UserPrincipalName to '{0}'", parsedUserName.UserPrincipalName); up.UserPrincipalName = parsedUserName.UserPrincipalName + "@" + parsedUserName.DomainName.ToLower(); } if (up.IsAccountLockedOut()) { try { up.UnlockAccount(); } catch (Exception e) { logger.LogWarning(true, "Cannot unlock account: " + e.Message + e.InnerException?.Message); } } try { up.Save(); } catch (Exception e) { logger.LogException(new Exception("Error while saving user", e), EventLogEntryType.Warning); // Sometimes it crashes, but everything was OK (weird?) // so we check again if the user has been created Thread.Sleep(500); up = FindUser(identity, pc); if (up == null) { // Rethrow the original, whatever it was. ExceptionDispatchInfo.Capture(e).Throw(); } } return(up); } }